Нет звука из CoreAudio AUGraph

У меня проблемы с получением аудио из AUGraph с использованием MixerUnit и OutputUnit. Я построил график, который смешивает 2 аудиофайла. Вот код, где я создаю график. У меня нет ошибок.

NSLog(@"initializeAUGraph");

mAudioFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32
                                                sampleRate:kSampleRate
                                                  channels:2
                                               interleaved:NO];

CheckError(NewAUGraph(&mGraph),"Error creating new graph");

AUNode outputNode;

AudioComponentDescription outputcd = {0};
outputcd.componentType = kAudioUnitType_Output;
outputcd.componentSubType = kAudioUnitSubType_DefaultOutput;
outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;

AudioComponent comp = AudioComponentFindNext(NULL, &outputcd);
if (comp == NULL) {
    printf ("can't get output unit"); exit (-1);
}

AUNode mixerNode;

AudioComponentDescription mixerDescription = {0};
mixerDescription.componentType = kAudioUnitType_Mixer;
mixerDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer;
mixerDescription.componentManufacturer = kAudioUnitManufacturer_Apple;

CheckError(AUGraphAddNode(mGraph, &outputcd, &outputNode), "Error adding Output node to graph");

CheckError(AUGraphAddNode(mGraph, &mixerDescription, &mixerNode), "Error adding Mixer mode to graph");

CheckError(AUGraphOpen(mGraph), "AUGraphOpen failed");

CheckError(AUGraphConnectNodeInput(mGraph, mixerNode, 0, outputNode, 0),"AUGraphConnectModeInput");

CheckError(AUGraphNodeInfo(mGraph, mixerNode, NULL, &mMixer), "Error loading mixer node info");

CheckError(AUGraphNodeInfo(mGraph, outputNode, NULL, &mOutput), "Error loading output node info");

UInt32 numbuses = 2;

CheckError(AudioUnitSetProperty(mMixer, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &numbuses, sizeof(numbuses)) , "Error setting prop to mixer");

for (int i = 0; i < numbuses; ++i) {
    // setup render callback struct
    AURenderCallbackStruct renderCallbackStruct;
    renderCallbackStruct.inputProc = &renderAudioInput;
    renderCallbackStruct.inputProcRefCon = mSoundBuffer;

    // Set a callback for the specified node's specified input
    CheckError((AUGraphSetNodeInputCallback(mGraph, mixerNode, i, &renderCallbackStruct))," AUGraphSetNodeInputCallback failed in cycle");

    //Set the input stream format property

   CheckError(AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, i, mAudioFormat.streamDescription, sizeof(AudioStreamBasicDescription)),"Set proprety in cycle error");

}

CheckError(AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, mAudioFormat.streamDescription, sizeof(AudioStreamBasicDescription)), "AudioUnitSetProperty mixer stream format failed");

/*CheckError(AudioUnitSetProperty(mOutput, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, mAudioFormat.streamDescription, sizeof(AudioStreamBasicDescription)), "AudioUnitSetProperty output stream format failed");*/

CheckError(AUGraphInitialize(mGraph),"AUGraphInitialize failed");

Консольный вывод:

2018-05-23 01:19:22.676281+0300 Mixer2Mac[37249:1285521] loadAudioFiles
2018-05-23 01:19:22.676918+0300 Mixer2Mac[37249:1285521] 2017569 frames in GuitarMonoSTP.aif
2018-05-23 01:19:22.676939+0300 Mixer2Mac[37249:1285521] 2017569 frames after sample ratio multiplied in GuitarMonoSTP.aif
2018-05-23 01:19:22.682277+0300 Mixer2Mac[37249:1285521] 2017569 frames in DrumsMonoSTP.aif
2018-05-23 01:19:22.682303+0300 Mixer2Mac[37249:1285521] 2017569 frames after sample ratio multiplied in DrumsMonoSTP.aif
2018-05-23 01:19:22.687415+0300 Mixer2Mac[37249:1285521] initializeAUGraph
2018-05-23 01:19:23.860541+0300 Mixer2Mac[37249:1285521] startPlaying
2018-05-23 01:19:24.830917+0300 Mixer2Mac[37249:1285521] stopPlaying
2018-05-23 01:19:28.218856+0300 Mixer2Mac[37249:1285521] startPlaying
2018-05-23 01:20:13.009934+0300 Mixer2Mac[37249:1285693] Starting over at frame 0 for bus 0
2018-05-23 01:20:13.010091+0300 Mixer2Mac[37249:1285693] Starting over at frame 0 for bus 1

Я вижу, что файлы воспроизводятся в консоли, но не слышат звука. Приложение для MacOs, а не для iOS. В чем может быть проблема?

РЕДАКТИРОВАТЬ 1


Вот функция обратного вызова. Это называется. Я вижу это в консоли. Это печатает "ЛОЛЛОЛ"

static OSStatus renderAudioInput(void *inRefCon, AudioUnitRenderActionFlags *actionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberOfFrames, AudioBufferList *ioData)
{
    NSLog(@"LOLLOLO");

    SoundBufferPtr soundBuffer = (SoundBufferPtr)inRefCon;

    //NSLog(@"numberOfFrames: %d", inNumberOfFrames);

    //Get the frame to start at and total number of samples
    UInt32 sample = soundBuffer[inBusNumber].sampleNumber;
    UInt32 startSample = sample;
    UInt32 bufferTotalSamples = soundBuffer[inBusNumber].numberOfFrames;

    //Get a reference to the input data buffer
    Float32 *inputData = soundBuffer[inBusNumber].data; // audio data buffer

    //Get references to the channel buffers
    Float32 *outLeft = (Float32 *)ioData->mBuffers[0].mData; // output audio buffer for Left channel
    Float32 *outRight = (Float32 *)ioData->mBuffers[1].mData; // output audio buffer for Right channel

    //Loop thru the number of frames and set the output data from the input data.
    //Use the left channel for bus 0 (guitar) and right channel for bus 1 (drums) to distiguish for example
    for (UInt32 i = 0; i < inNumberOfFrames; ++i) {

        if (inBusNumber == 0) {
            outLeft[i] = inputData[sample++];
            outRight[i] = 0;
        } else {    //inBusNumber == 1
            outLeft[i] = 0;
            outRight[i] = inputData[sample++];
        }

        //If the sample is beyond the total number of samples in the loop, start over at the beginning
        if (sample > bufferTotalSamples) {
            // start over from the beginning of the data, our audio simply loops
            sample = 0;
            NSLog(@"Starting over at frame 0 for bus %d", (int)inBusNumber);
        }
    }

    //Set the sample number in the sound buffer struct so we know which frame playback is on
    soundBuffer[inBusNumber].sampleNumber = sample;

    performFFT(&inputData[startSample], inNumberOfFrames, soundBuffer, inBusNumber);

    return noErr;
}

Вывод после NSLog("LOLLOL"):

2018-05-23 12:56:49.297251+0300 Mixer2Mac[39034:1368659] loadAudioFiles
2018-05-23 12:56:49.298417+0300 Mixer2Mac[39034:1368659] 2017569 frames in GuitarMonoSTP.aif
2018-05-23 12:56:49.298445+0300 Mixer2Mac[39034:1368659] 2017569 frames after sample ratio multiplied in GuitarMonoSTP.aif
2018-05-23 12:56:49.309126+0300 Mixer2Mac[39034:1368659] 2017569 frames in DrumsMonoSTP.aif
2018-05-23 12:56:49.309156+0300 Mixer2Mac[39034:1368659] 2017569 frames after sample ratio multiplied in DrumsMonoSTP.aif
2018-05-23 12:56:49.316572+0300 Mixer2Mac[39034:1368659] initializeAUGraph
2018-05-23 12:56:51.206301+0300 Mixer2Mac[39034:1368659] startPlaying
2018-05-23 12:56:51.229420+0300 Mixer2Mac[39034:1368816] LOLLOLO
2018-05-23 12:56:51.229692+0300 Mixer2Mac[39034:1368816] LOLLOLO
2018-05-23 12:56:51.240977+0300 Mixer2Mac[39034:1368816] LOLLOLO
2018-05-23 12:56:51.241162+0300 Mixer2Mac[39034:1368816] LOLLOLO

1 ответ

Новый, улучшенный ответ Этот ответ, который не является дубликатом вашего ответа, поскольку у вас две шины вместо одной, указывает, что в macOS входные громкости микшера по умолчанию равны нулю, а в комментарии добавляется, что выходной том тоже есть, поэтому измените ваш код выглядит так:

for (int i = 0; i < numbuses; ++i) {
    // setup render callback struct
    AURenderCallbackStruct renderCallbackStruct;
    renderCallbackStruct.inputProc = &renderAudioInput;
    renderCallbackStruct.inputProcRefCon = mSoundBuffer;

    // Set a callback for the specified node's specified input
    CheckError((AUGraphSetNodeInputCallback(mGraph, mixerNode, i, &renderCallbackStruct))," AUGraphSetNodeInputCallback failed in cycle");

    //Set the input stream format property

    CheckError(AudioUnitSetProperty(mMixer, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, i, mAudioFormat.streamDescription, sizeof(AudioStreamBasicDescription)),"Set proprety in cycle error");

    // NEW! mixer input volume defaults to zero on macOS. Why!?!?
    CheckError(AudioUnitSetParameter(mMixer, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, i, 1.0, 0), "AudioUnitSetParameter failed");
}

// NEW! Output defaults to zero too!
CheckError(AudioUnitSetParameter(mMixer, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, 0, 1.0, 0), "AudioUnitSetParameter failed");

Документация, кажется, неправильно говорит, что kMultiChannelMixerParam_Volume по умолчанию 1.0:

Глобальная сфера. Значение должно быть числом от 0,0 до 1,0. Значением по умолчанию является 1,0.

Однако это для глобального масштаба.

О, ты начинал это

Вам нужно запустить звуковой график после его инициализации:

OSStatus status = AUGraphStart(mGraph);
Другие вопросы по тегам