Добавление фильтра AULowPass, между 2 AudioUnits

Я изменил код, предоставленный Тимом Болдстадом http://timbolstad.com/2010/03/16/core-audio-getting-started-pt2/ (да благословит его Бог), и добавил небольшой слайдер, чтобы можно было изменить частота выходного тона составляет от 40 Гц до 200000 Гц. Теперь я хочу использовать LPF для генерируемого тона.

Прежде всего, есть ли у any1 подробное руководство, которое объясняет, как это сделать. Я попытался просто добавить узел между ними, но он не работает, по-видимому, мне нужно преобразовать 16-битные целочисленные сэмплы в плавающий формат 8.24, прежде чем передавать входные аудиосэмплы в фильтр, а затем мне нужно конвертировать вернуться к 16-битному целому числу. Это проблема? или я подключил узел неправильно? Где я должен установить частоту среза фильтров и другие параметры?

Кто-нибудь может объяснить, что делает AudioUnitGetProperty? Документация Apple по этим темам крайне фрагментирована и совершенно бесполезна:(

-(void) initializeAUGraph
{

OSStatus result= noErr;

    result = NewAUGraph(&mGraph);

    AUNode outputNode;
    AUNode mixerNode;
    AUNode effectsNode;

    AudioComponentDescription effects_desc;
    effects_desc.componentType = kAudioUnitType_Effect;
    effects_desc.componentSubType = kAudioUnitSubType_LowPassFilter;
    effects_desc.componentFlags = 0;
    effects_desc.componentFlagsMask = 0;
    effects_desc.componentManufacturer = kAudioUnitManufacturer_Apple;

    AudioComponentDescription mixer_desc;
    mixer_desc.componentType=kAudioUnitType_Mixer;
    mixer_desc.componentSubType=kAudioUnitSubType_MultiChannelMixer;
    mixer_desc.componentFlags=0;
    mixer_desc.componentFlagsMask=0;
    mixer_desc.componentManufacturer=kAudioUnitManufacturer_Apple;

    AudioComponentDescription output_desc;
    output_desc.componentType = kAudioUnitType_Output;
    output_desc.componentSubType = kAudioUnitSubType_RemoteIO;
    output_desc.componentFlags = 0;
    output_desc.componentFlagsMask = 0;
    output_desc.componentManufacturer = kAudioUnitManufacturer_Apple;

   result= AUGraphAddNode(mGraph, &output_desc, &outputNode);
   result= AUGraphAddNode(mGraph, &mixer_desc, &mixerNode);
    result=AUGraphAddNode(mGraph, &effects_desc, &effectsNode);

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

    result=AUGraphOpen(mGraph);

    //getting mixxer

    result = AUGraphNodeInfo(mGraph, mixerNode, NULL, &mMixer);
    result = AUGraphNodeInfo(mGraph, effectsNode, NULL, &mEffects);

    UInt32 numbuses = 1;
    UInt32 size = sizeof(numbuses);
    result = AudioUnitSetProperty(mMixer, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &numbuses, size);


    //=====

    CAStreamBasicDescription desc;

    // Loop through and setup a callback for each source you want to send to the mixer.
    // Right now we are only doing a single bus so we could do without the loop.
    for (int i = 0; i < numbuses; ++i) 
    {

        // Setup render callback struct
        // This struct describes the function that will be called
        // to provide a buffer of audio samples for the mixer unit.
        AURenderCallbackStruct renderCallbackStruct;
        renderCallbackStruct.inputProc = &renderInput;
        renderCallbackStruct.inputProcRefCon = self;

        // Set a callback for the specified node's specified input
        result = AUGraphSetNodeInputCallback(mGraph, mixerNode, i, &renderCallbackStruct);

        // Get a CAStreamBasicDescription from the mixer bus.
        size = sizeof(desc);
        result = AudioUnitGetProperty(  mMixer,
                                      kAudioUnitProperty_StreamFormat,
                                      kAudioUnitScope_Input,
                                      i,
                                      &desc,
                                      &size);
        // Initializes the structure to 0 to ensure there are no spurious values.
        memset (&desc, 0, sizeof (desc));                               

        // Make modifications to the CAStreamBasicDescription
        // We're going to use 16 bit Signed Ints because they're easier to deal with
        // The Mixer unit will accept either 16 bit signed integers or
        // 32 bit 8.24 fixed point integers.

        desc.mSampleRate = kGraphSampleRate; // set sample rate
        desc.mFormatID = kAudioFormatLinearPCM;
        desc.mFormatFlags      = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
        desc.mBitsPerChannel = sizeof(AudioSampleType) * 8; // AudioSampleType == 16 bit signed ints
        desc.mChannelsPerFrame = 1;
        desc.mFramesPerPacket = 1;
        desc.mBytesPerFrame = ( desc.mBitsPerChannel / 8 ) * desc.mChannelsPerFrame;
        desc.mBytesPerPacket = desc.mBytesPerFrame * desc.mFramesPerPacket;

        printf("Mixer file format: "); desc.Print();
        // Apply the modified CAStreamBasicDescription to the mixer input bus
        result = AudioUnitSetProperty(  mMixer,
                                      kAudioUnitProperty_StreamFormat,
                                      kAudioUnitScope_Input,
                                      i,
                                      &desc,
                                      sizeof(desc));
    }

    // Apply the CAStreamBasicDescription to the mixer output bus
    result = AudioUnitSetProperty(   mMixer,
                                  kAudioUnitProperty_StreamFormat,
                                  kAudioUnitScope_Output,
                                  0,
                                  &desc,
                                  sizeof(desc));

    //************************************************************
    //*** Setup the audio output stream ***
    //************************************************************

    // Get a CAStreamBasicDescription from the output Audio Unit
    result = AudioUnitGetProperty(  mMixer,
                                  kAudioUnitProperty_StreamFormat,
                                  kAudioUnitScope_Output,
                                  0,
                                  &desc,
                                  &size);

    // Initializes the structure to 0 to ensure there are no spurious values.
    memset (&desc, 0, sizeof (desc));

    // Make modifications to the CAStreamBasicDescription
    // AUCanonical on the iPhone is the 8.24 integer format that is native to the iPhone.
    // The Mixer unit does the format shifting for you.
    desc.SetAUCanonical(1, true);
    desc.mSampleRate = kGraphSampleRate;

    // Apply the modified CAStreamBasicDescription to the output Audio Unit
    result = AudioUnitSetProperty(  mMixer,
                                  kAudioUnitProperty_StreamFormat,
                                  kAudioUnitScope_Output,
                                  0,
                                  &desc,
                                  sizeof(desc));

    // Once everything is set up call initialize to validate connections
    result = AUGraphInitialize(mGraph);
}

1 ответ

Кто-нибудь может объяснить, что делает AudioUnitGetProperty?

Ну, это получает значение свойства от аудиоустройства. "Свойство" - это обычно то, с чем вы работаете как программист (например, формат аудиопотока, состояние соединения), тогда как "параметр" - это обычно то, что вы предоставляете пользователю (например, частота среза нижних частот, громкость микшера). Обратите внимание, что есть AudioUnitGetParameter а также AudioUnitSetParameter функции, чтобы дополнить AudioUnitGetProperty а также AudioUnitSetProperty функции.

От вас ожидают, что вы просто "знаете", каковы свойства / параметры аудиоустройства и какие значения они ожидают. Лучший источник документации по этому вопросу - два заголовка в AudioUnit.framework. А именно, AudioUnitProperties.h а также AudioUnitParameters.h, Следующий лучший источник - автозаполнение Xcode. Например, параметры AULowPass: kLowPassParam_CutoffFrequency а также kLowPassParam_Resonance, так что вы можете просто набрать kLowPassParam и Xcode покажет вам, что доступно. Другие AU обычно следуют этой схеме.

... но это не работает, по-видимому

Мне нужно больше информации. Вы имеете в виду, что вы просто не можете услышать разницу? AULowPass запускается с очень высокой частотой среза, поэтому, если вы не установите его на что-то более низкое, вы, вероятно, вообще не услышите никакой разницы.

Попробуйте установить частоту среза на что-то довольно низкое, например, 500 Гц. Вы делаете это так:

AudioUnitSetParameter(mEffects,
                      kLowPassParam_CutoffFrequency,
                      kAudioUnitScope_Global,
                      0,
                      500,
                      0);
Другие вопросы по тегам