How does kAudioUnitSubType_NBandEQ work? Or equalizing using DSP formulas with Novocaine?

Go To StackoverFlow.com

8

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.

2012-04-03 21:12
by bartolsthoorn
It looks like there are ~0 people who have used it on the whole internet. Good luck - Adam Shiemke 2012-04-04 18:59
Thanks, someone has to be the first to ask about it, I know some people have used it, like the people that're writing new CoreAudio books - bartolsthoorn 2012-04-04 23:12
When implementing Audio Nodes I found this Apple doc really helpful: http://developer.apple.com/library/ios/#qa/qa1717/_index.htm - Alastair Stuart 2012-04-09 22:46
Also, /Applications/Xcode.app//Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/System/Library/Frameworks/AudioUnit.framework/Headers/AudioUnitParameters.h has info on the unit's parameters - Alastair Stuart 2012-04-09 23:04
Do you have a sample project to go along with your NVDSP classes? This would be really helpful? Trying to make equalizer UI and think this is what i need to get me started. Thanks - tiltem 2012-06-28 20:02
@tiltem I recommend you to start out with the Novocaine sample project and add the NVDSP files for now. You can then easily add the NVDSP files to add the DSP functionality you will need for creating an equalizer. Good idea to add a sample project though, I'll do this tonight or tomorrow! (watch the NVDSP repo for changes - bartolsthoorn 2012-07-02 19:45
@tiltem Sorry for the delay, I added an example of a 10-band equalizer! https://github.com/bartolsthoorn/NVDSP/blob/master/Examples/Equalizer.mm I think this will include exactly what you need - bartolsthoorn 2012-07-19 21:30
Thanks, was really hoping for a working project, but will see what can get from this. Do appreciate the guidance - tiltem 2012-07-25 18:52
Hosting a project would encourage people to use that version of Novocaine while right now you have to download them both separately that will force you to use the latest versions of both (a good thing). However, I think a working project would be great, but adding other filters is more important, you could contribute to the repo with your project, I'll merge the commit - bartolsthoorn 2012-07-27 12:46
@bartolsthoorn hey dear i need your help. What i want to do is control the bass of music in a slider. I'm sure you can help me in this please do help. I had downloaded all your sample code which u added in github please let me know what to do with them so that i can adjust bass of music in a slider - Nikhil Bansal 2012-08-24 07:17
@NikhilBansal While I appreciate your interest in NVDSP I cannot make specific projects for everyone. The case you describe is very easy, you just need one peaking or shelving (to your taste) filter, set the Q and frequency low and you are set! The README and EQ example should contain enough information to do help you out - bartolsthoorn 2012-09-03 20:22
@bartolsthoorn the problem i'm facing is to maintain the player with the method made by you for example pause method is not working for me my song is not getting pause. Help me out pleas - Nikhil Bansal 2012-09-05 08:12


3

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.

2012-04-19 21:07
by alexbw
Hi, I've been trying this for some days and this is what I've got: https://gist.github.com/2483604 It only produces click noises. Could you please please show me an example of how to copy a specific band into a float *buffer with vDSP_deq22? I will give bounty points when I have those available - bartolsthoorn 2012-04-24 20:52
The first two samples of data being passed to vDSPdeq22 have to be initialized from the previous call. So, you'd want to hold onto a float buffer and feed the tailing two samples after a vDSPdeq22 call back to the front of that array for the next time you call - alexbw 2012-04-28 22:30
Yes thanks, I already figured out how to calculate the coefficients, there's only one question left! In what order do I have to pass the coefficients? (and why 5 coefficients and not 6, I have a0, a1, a2, b0, b1, b2, so there's actually 6 of 'em - bartolsthoorn 2012-04-29 19:24
I've turned that last question into a new question on stackoverflow: http://stackoverflow.com/questions/10375359/iir-coefficients-for-peaking-eq-how-to-pass-them-to-vdsp-deq2 - bartolsthoorn 2012-04-29 19:45


2

10-band equalizer can be configured as below

converterNode -> eqNode->converterNode->ioNode.

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
2012-04-11 06:10
by SPrabhu
Doesn't this just show me how to "connect" the nodes rather than actually configuring the NBandEQ unit - bartolsthoorn 2012-04-15 21:27