1

I'm developing a music application for iOS using the AVAudioplayer, in which I want to implement an equalizer. I searched the internet for a good solution, and ended up with and AUGraph configuration like this:

// multichannel mixer unit
AudioComponentDescription mixer_desc;
mixer_desc.componentType = kAudioUnitType_Mixer;
mixer_desc.componentSubType = kAudioUnitSubType_MultiChannelMixer;
mixer_desc.componentManufacturer = kAudioUnitManufacturer_Apple;
mixer_desc.componentFlags = 0;
mixer_desc.componentFlagsMask = 0;
// iPodEQ unit
AudioComponentDescription eq_desc;
eq_desc.componentType = kAudioUnitType_Effect;
eq_desc.componentSubType = kAudioUnitSubType_AUiPodEQ;
eq_desc.componentManufacturer =  kAudioUnitManufacturer_Apple;
eq_desc.componentFlags = 0;
eq_desc.componentFlagsMask = 0;
// output unit
AudioComponentDescription output_desc;
output_desc.componentType = kAudioUnitType_Output;
output_desc.componentSubType = kAudioUnitSubType_GenericOutput;
output_desc.componentManufacturer =  kAudioUnitManufacturer_Apple;
output_desc.componentFlags = 0;
output_desc.componentFlagsMask =  0;

// create a new AUGraph
OSStatus result = NewAUGraph(&mGraph);
// Add Audio Nodes to graph
AUNode outputNode;
AUNode eqNode;
AUNode mixerNode;
AUGraphAddNode(mGraph, &mixer_desc, &mixerNode);
AUGraphAddNode(mGraph, &eq_desc, &eqNode);

AUGraphAddNode(mGraph, &output_desc, &outputNode);

// open the graph AudioUnits (but not initialized)
result = AUGraphOpen(mGraph);
// grab the audio unit instances from the nodes
AudioUnit mEQ;
AudioUnit mMixer;
result = AUGraphNodeInfo(mGraph, mixerNode, NULL, &mMixer);
result = AUGraphNodeInfo(mGraph, eqNode, NULL, &mEQ);

// set number of input buses for the mixer Audio Unit
UInt32 numbuses = 0;
AudioUnitSetProperty ( mMixer, kAudioUnitProperty_ElementCount,
                      kAudioUnitScope_Input, 0, &numbuses, sizeof(numbuses));

// get the equalizer factory presets list
CFArrayRef mEQPresetsArray;
UInt32 sizeof1 = sizeof(mEQPresetsArray);
AudioUnitGetProperty(mEQ, kAudioUnitProperty_FactoryPresets,
                     kAudioUnitScope_Global, 0, &mEQPresetsArray, &sizeof1);


result = AUGraphConnectNodeInput(mGraph, mixerNode, 0, eqNode, 0);
result = AUGraphConnectNodeInput(mGraph, eqNode, 0, outputNode, 0);

AudioUnitSetParameter(mMixer, kMultiChannelMixerParam_Enable, kAudioUnitScope_Input, 0, 1, 0);

AUPreset *aPreset = (AUPreset*)CFArrayGetValueAtIndex(mEQPresetsArray, 7);
AudioUnitSetProperty (mEQ, kAudioUnitProperty_PresentPreset,
                      kAudioUnitScope_Global, 0, aPreset, sizeof(AUPreset));

AUGraphInitialize(mGraph);
AUGraphStart(mGraph);

The AUGraph is running, but the EQ isn't applied. The argument '7' in AUPreset *aPreset = (AUPreset*)CFArrayGetValueAtIndex(mEQPresetsArray, 7); is the index of the equalizer that should be applied. (Electronic) I got that index from logging the values of the mEQPresetsArray-Array:

for (int i = 0; i < CFArrayGetCount(mEQPresetsArray); i++) {
    AUPreset *aPreset = (AUPreset*)CFArrayGetValueAtIndex(mEQPresetsArray, i);
    NSLog(@"%d: %@", (int)aPreset->presetNumber, aPreset->presetName);
}

How can I solve my problem? I've already tried the NVDSP, but it didn't seem to be working as well. I didn't find any other solution on the internet.

Thanks in advance, Fabian.

FTFT1234
  • 435
  • 8
  • 17

2 Answers2

0

If this is for iOS then you need to use kAudioUnitSubType_RemoteIO instead of kAudioUnitSubType_GenericOutput.

dave234
  • 4,793
  • 1
  • 14
  • 29
  • Okay, I tried it, but it doesn't apply the equalizer at all. I'm getting still the same output sound. – FTFT1234 May 13 '15 at 21:21
  • You must be using the simulator if you were getting sound with kAudioUnitSubType_GenericOutput. I tried it on an iOS device, it works fine. – dave234 May 14 '15 at 13:59
  • On my iPhone 6 running iOS 8.4 it doesn't work neither with kAudioUnitSubType_RemoteIO nor with kAudioUnitSubType_GenericOutput. Which audio player did you use? – FTFT1234 May 14 '15 at 14:02
  • I generated a saw wave in a callback https://gist.github.com/dave234/3465e328d3cef297fa28 – dave234 May 14 '15 at 14:09
  • Okay, thanks. When I load this ViewController a tone gets played nonstop. The equalizer is applied to this tone. But the music from my AVAudioPlayer isn't effected by the equalizer. Do I have to use another audio player to apply the equalizer to my music? – FTFT1234 May 14 '15 at 14:19
  • I think you can still use AVFoundation with a MTAudioProcessingTap MTAudioProcessingTap but I haven't tried it myself https://developer.apple.com/library/ios/samplecode/AudioTapProcessor/Introduction/Intro.html#//apple_ref/doc/uid/DTS40012324. I use the old audio units API with an AUFilePlayer, but if I were to start learning now I would look in to the new AVAudioEngine first. https://developer.apple.com/library/prerelease/ios/documentation/AVFoundation/Reference/AVAudioEngine_Class/index.html – dave234 May 14 '15 at 14:39
  • Yes, thank you really much! I'm now using an AVAudioEngine with AVAudioPlayerNode and AVAudioUnitEQ. How can I set up a ten band AVAudioUnitEQ with parameters? If I try this, I have set the globalGain from the AVAudioUnitEQ to about 170 to hear the music. – FTFT1234 May 14 '15 at 16:00
  • You should accept my answer then ask a separate question. – dave234 May 14 '15 at 16:28
0

You cannot use AVAudioPlayer to do your EQ, you need AVPlayer.

See here for a sample project using the audio tap:

https://developer.apple.com/library/ios/samplecode/AudioTapProcessor/Introduction/Intro.html

Daniel Broad
  • 2,512
  • 18
  • 14