Нет звука из 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);