I'm trying to make a 10-band equalizer and the kAudioUnitSubType_NBandEQ
audio unit seems the way to go, but Apple's documentation doesn't cover how to set/configure it.
I've already connected the nodes but it errors out when I try to connect the EQNode with the iONode (output): https://gist.github.com/2295463
How do I turn the effect into a working 10-band equalizer?
Update: A working DSP formula with Novocaine is also a solution, any ideas! Those DSP formulas are quite complicated.
Update2: I prefer a working DSP formula with Novocaine since that'd be much cleaner/smaller than programming Audio Nodes.
Update3: "The Multitype EQ unit(of subtype kAudioUnitSubType_NBandEQ) provides an equalizer that can be configured as any one of the types described in “Mutitype EQ Unit Filter Types” (page 68)." Source: http://developer.apple.com/library/ios/DOCUMENTATION/AudioUnit/Reference/AudioUnit_Framework/AudioUnit_Framework.pdf But still no example.
IMPORTANT Update (17/05): I recommend everyone to use my DSP class I released on github: https://github.com/bartolsthoorn/NVDSP It'll probably save you quite some work. It will make developing a n-band equalizer or any kind of audio filters a breeze.
I'm the creator of Novocaine, and I've used it to make a 200-some-odd band EQ using vDSP.
I'm considering switching over to the NBandEQ audio unit, but I have a working solution with vDSP_deq22.
vDSP_deq22 filters data one sample at a time with a 2nd order IIR filter. You can find 2nd order Butterworth coefficients on musicdsp.org, or more generally by Googling. Matlab will also calculate them for you, if you have access to a copy. I used musicdsp.org. You'd create 10 vDSP_deq22 filters, run your audio through each one, multiply that band by a specified gain, and then add up the output of all the filters in the filter bank into your output audio.
10-band equalizer can be configured as below
Please refere below sample code. here i have used iPodEQ unit. Replace the iPodEQunit formatspecification with 10-band equalizer.
AUNode outputNode;
AUNode iPodTimeNode;
AUNode converterNode;
AUNode converterNode2;
AudioUnit converterAU;
AudioUnit converterAU2;
printf("create client format ASBD\n");
// client format audio going into the converter
mClientFormat.SetCanonical(1, false);
mClientFormat.mSampleRate = kGraphSampleRate;
mClientFormat.Print();
printf("create output format ASBD\n");
CAStreamBasicDescription localOutput;
localOutput.SetAUCanonical(2, false);
localOutput.mSampleRate = kGraphSampleRate;
// output format
mOutputFormat.SetCanonical(1, false);
mOutputFormat.mSampleRate = kGraphSampleRate;
mOutputFormat.Print();
OSStatus result = noErr;
printf("-----------\n");
printf("new AUGraph\n");
// create a new AUGraph
result = NewAUGraph(&mGraph);
if (result) { printf("NewAUGraph result %ld %08X %4.4s\n", result,
(unsigned int)result, (char*)&result); return; }
// create three CAComponentDescription for the AUs we want in the graph
// output unit
CAComponentDescription output_desc(kAudioUnitType_Output,
kAudioUnitSubType_GenericOutput,
kAudioUnitManufacturer_Apple);
// iPodTime unit
CAComponentDescription iPodTime_desc(kAudioUnitType_FormatConverter,
kAudioUnitSubType_AUiPodTimeOther,
kAudioUnitManufacturer_Apple);
// AU Converter
CAComponentDescription converter_desc(kAudioUnitType_FormatConverter,
kAudioUnitSubType_AUConverter,
kAudioUnitManufacturer_Apple);
printf("add nodes\n");
// create a node in the graph that is an AudioUnit, using the supplied
// AudioComponentDescription to find and open that unit
result = AUGraphAddNode(mGraph, &output_desc, &outputNode);
result = AUGraphAddNode(mGraph, &iPodTime_desc, &iPodTimeNode);
result = AUGraphAddNode(mGraph, &converter_desc, &converterNode);
result = AUGraphAddNode(mGraph, &converter_desc, &converterNode2);
// connect a node's output to a node's input
// converter -> iPodTime ->converter-> output
result = AUGraphConnectNodeInput(mGraph, converterNode2, 0, iPodTimeNode, 0);
result = AUGraphConnectNodeInput(mGraph, iPodTimeNode, 0, converterNode, 0);
result = AUGraphConnectNodeInput(mGraph, converterNode, 0, outputNode, 0);
// open the graph -- AudioUnits are open but not initialized
// (no resource allocation occurs here)
result = AUGraphOpen(mGraph);
// grab audio unit instances from the nodes
result = AUGraphNodeInfo(mGraph, converterNode, NULL, &converterAU);
result = AUGraphNodeInfo(mGraph, converterNode2, NULL, &converterAU2);
result = AUGraphNodeInfo(mGraph, iPodTimeNode, NULL, &mIPodTime);
result = AUGraphNodeInfo(mGraph, outputNode, NULL, &mOutputUnit);
//Get EQ unit format
UInt32 size ;
CAStreamBasicDescription eqDesc;
AudioUnitGetProperty(mIPodTime, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &eqDesc, &size);
eqDesc.Print();
// setup render callback struct
AURenderCallbackStruct rcbs;
rcbs.inputProc = &renderInput;
rcbs.inputProcRefCon = &mUserData;
printf("set AUGraphSetNodeInputCallback\n");
// set a callback for the specified node's specified input bus (bus 1)
result = AUGraphSetNodeInputCallback(mGraph, converterNode2, 0, &rcbs);
//SetFormat
result = AudioUnitSetProperty(converterAU2, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, &mClientFormat, sizeof(mClientFormat));
result = AudioUnitSetProperty(converterAU2, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, 0, &eqDesc, sizeof(eqDesc));
printf("set converter input bus %d client kAudioUnitProperty_StreamFormat\n", 0);
// set the input stream format, this is the format of the audio
// for the converter input bus (bus 1)
result = AudioUnitSetProperty(converterAU, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, &localOutput, sizeof(localOutput));
// in an au graph, each nodes output stream format (including sample rate)
// needs to be set explicitly this stream format is propagated to its
// destination's input stream format
printf("set converter output kAudioUnitProperty_StreamFormat\n");
// set the output stream format of the converter
result = AudioUnitSetProperty(converterAU, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, 0, &mOutputFormat, sizeof(mOutputFormat));
result = AudioUnitSetProperty(mOutputUnit, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, 0, &mOutputFormat, sizeof(mOutputFormat));
// set the output stream format of the iPodTime unit
result = AudioUnitSetProperty(mIPodTime, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, 0, &localOutput, sizeof(localOutput));
printf("AUGraphInitialize\n");
// add a render notification, this is a callback that the graph will call every time the graph renders
// the callback will be called once before the graph’s render operation, and once after the render operation is complete
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With