Applying a low-pass cutoff inside an AU
Applying a low-pass cutoff inside an AU
- Subject: Applying a low-pass cutoff inside an AU
- From: Darren Baptiste <email@hidden>
- Date: Mon, 14 Sep 2009 13:45:55 -0400
Since the iPhone does not allow custom AU units to be created, to get
custom effects I need to add my DSP code into the processing body of
an existing unit.
The code below was taken from a custom AU I developed (really just
modified the Tremolo tutorial) and tested on my Mac. It's a simple low-
pass filter. I've added it to a Multichannel Mixer AU (inside an
AUGraph). However, when the code is actually running, the output is a
horrible-sounding mess. I can tell that (approximately) the right
frequencies are being impacted, but not cleanly. Hmmmpf ... not a very
good description, I know.
Can anyone suggest what I should look at to improving this? (well,
making it actually work :)
The core of the DSP code below was taken from a post here ( http://www.musicdsp.org/showone.php?id=259
) which claims it originally came from a sample from Apple.
// ============================================================
static OSStatus eqMixerCallback(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
//get a reference to the djMixer class, we need this as we are
outside the class
//in just a straight C method.
DJMixer *djMixer = (DJMixer *)inRefCon;
OSStatus err = 0;
// create coefficients for later
// static coefficients for this type of filter
float cutoff_slider = 1000.0; //cutoff_slider range 20-20000hz
float resonance_slider = 0.0; //res_slider range -25/25db
float srate = 44100.0; //srate - sample rate
//
int c_factor = djMixer.the_factor;
switch (c_factor) {
case 0:
break;
case 1:
cutoff_slider = 800.0; //cutoff_slider range 20-20000hz
resonance_slider = 0.0; //res_slider range -25/25db
break;
case 2:
cutoff_slider = 800.0; //cutoff_slider range 20-20000hz
resonance_slider = -6.0; //res_slider range -25/25db
break;
case 3:
cutoff_slider = 10000.0; //cutoff_slider range 20-20000hz
resonance_slider = 0.0; //res_slider range -25/25db
break;
default:
break;
}
//
float mX1 = 0;
float mX2 = 0;
float mY1 = 0;
float mY2 = 0;
//float pi = 22/7;
float k, c1, c2, c3, mA0, mA1, mA2, mB1, mB2;
// float output;
float cutoff = 2 * cutoff_slider / srate;
float res = pow(10, -0.05 * resonance_slider);
k = 0.5 * res * sin(M_PI * cutoff);
c1 = 0.5 * (1 - k) / (1 + k);
c2 = (0.5 + c1) * cos(M_PI * cutoff);
c3 = (0.5 + c1 - c2) * 0.25;
mA0 = 2 * c3;
mA1 = 2 * 2 * c3;
mA2 = 2 * c3;
mB1 = 2 * -c2;
mB2 = 2 * c1;
UInt32 *frameBuffer = ioData->mBuffers[0].mData;
Float32 p;
if (inBusNumber == 0){
//loop through the buffer and fill the frames
for (int j = 0; j < inNumberFrames; j++){
// get NextPacket returns a 32 bit value, one frame.
p = (Float32)[djMixer.loopOne getNextPacket]; // this is pulling
from an in-memory .wav file
frameBuffer[j] = (mA0 * p) + (mA1 * mX1) + (mA2 * mX2) - (mB1 *
mY1) - (mB2 * mY2);
mX2 = mX1;
mX1 = p;
mY2 = mY1;
mY1 = frameBuffer[j];
}
}
// I leave the other channel alone for now -- just as a
reference -- the audio is simply passed through
else if (inBusNumber == 1){
//loop through the buffer and fill the frames
for (int j = 0; j < inNumberFrames; j++){
// get NextPacket returns a 32 bit value, one frame.
frameBuffer[j] = [djMixer.loopTwo getNextPacket];
}
}
return err;
}
// ============================================================
Cheers, and thanks for any insight.
Darren Baptiste
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden