CoreAudio AUGraph 没有声音
Posted
技术标签:
【中文标题】CoreAudio AUGraph 没有声音【英文标题】:No sound out of CoreAudio AUGraph 【发布时间】:2018-05-22 22:21:53 【问题描述】:我无法使用 MixerUnit 和 OutputUnit 从 AUGraph 获取音频。 我已经构建了一个混合 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
我看到文件正在控制台中播放,但听不到声音。该应用程序适用于 MacO,而不适用于 iOS。可能是什么问题?
编辑 1
这里是回调函数。它被称为。我可以在控制台中看到它。它打印“LOLLOL”
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
【问题讨论】:
我正在通过 IBAction 使用 AUGraphStart(mGraph) 将图表启动到按钮。 【参考方案1】:新的改进答案 This answer,你的不是完全重复的,因为你有两条总线而不是一条,指出在 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");
The documentation 似乎错误地说 kMultiChannelMixerParam_Volume
默认为 1.0:
全球范围。该值应该是介于 0.0 和 1.0 之间的数字。默认值为 1.0。
但这是针对全球范围的。
哦,你开始了
初始化后需要启动音频图:
OSStatus status = AUGraphStart(mGraph);
【讨论】:
我正在使用 AUGraphStart(mGraph) 通过 IBAction 将图表启动到按钮。 啊好的,你的输入回调被调用了吗?然后可能会显示更多代码,例如您如何开始以及如何播放文件。 增加了输出和回调函数。以上是关于CoreAudio AUGraph 没有声音的主要内容,如果未能解决你的问题,请参考以下文章
核心音频:不推荐使用 AUGraph 时如何通过 MusicPlayer 播放 MIDI MusicSequence?