如何在 Mac 上设置录制和播放音频。 Mac 上的 VOIP 应用程序
Posted
技术标签:
【中文标题】如何在 Mac 上设置录制和播放音频。 Mac 上的 VOIP 应用程序【英文标题】:How to setup for record and playback audio on Mac. VOIP app on Mac 【发布时间】:2016-12-13 18:19:05 【问题描述】:我想在 Mac 中录制和播放音频。现在,我对 Input/Output/ChannelFormat 的设置有一些问题……我向您展示了我在下面尝试的一些代码。
// Setup audio device
- (OSStatus) setupAudioDevice // It's oks
AudioComponentDescription desc;
AudioComponent comp;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_VoiceProcessingIO; // This type support for both ios and Mac
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
comp = AudioComponentFindNext(NULL, &desc);
if (comp == NULL)
return -1;
OSStatus err = AudioComponentInstanceNew(comp, &audioUnit);
checkStatus(err);
return err;
//Enable IO
//https://developer.apple.com/library/prerelease/content/technotes/tn2091/_index.html
- (OSStatus) setupEnableIO // It's ok
UInt32 enableIO;
//When using AudioUnitSetProperty the 4th parameter in the method
//refer to an AudioUnitElement. When using an AudioOutputUnit
//the input element will be '1' and the output element will be '0'.
enableIO = 1;
OSStatus err = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
kInputBus, // input element
&enableIO,
sizeof(enableIO));
checkStatus(err);
enableIO = 0;
err = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
kOutputBus, //output element
&enableIO,
sizeof(enableIO));
checkStatus(err);
return err;
// Setup Microphone
- (OSStatus) setupMicInput // It's ok
AudioObjectPropertyAddress addr;
UInt32 size = sizeof(AudioDeviceID);
AudioDeviceID deviceID = 0;
addr.mSelector = kAudioHardwarePropertyDefaultInputDevice;
addr.mScope = kAudioObjectPropertyScopeGlobal;
addr.mElement = kAudioObjectPropertyElementMaster;
OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &size, &deviceID);
checkStatus(err);
if (err == noErr)
err = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceID, size);
checkStatus(err);
int m_valueCount = deviceID / sizeof(AudioValueRange) ;
NSLog(@"Available %d Sample Rates\n",m_valueCount);
NSLog(@"DeviceName: %@",[self deviceName:deviceID]);
NSLog(@"BufferSize: %d",[self bufferSize:deviceID]);
return err;
// Setup Input format
- (OSStatus)setupInputFormat
AudioStreamBasicDescription audioFormat;// = [EZAudioUtilities monoFloatFormatWithSampleRate:SampleRate]
audioFormat.mSampleRate = SampleRate;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = 1;
audioFormat.mBitsPerChannel = 8 * sizeof(UInt32);
audioFormat.mBytesPerPacket = sizeof(UInt32);
audioFormat.mBytesPerFrame = sizeof(UInt32);
UInt32 size = sizeof(AudioStreamBasicDescription);
// Apply format
OSStatus err = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&audioFormat,
size);
checkStatus(err);
err = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
1,
&audioFormat,
size);
checkStatus(err);
return err;
//Setup Input Callback
- (OSStatus)setupInputCallback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = recordingCallback;
callbackStruct.inputProcRefCon = (__bridge void * _Nullable)(self);
UInt32 size = sizeof(AURenderCallbackStruct);
OSStatus err = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
0,
&callbackStruct,
size);
checkStatus(err);
return err;
//Setup Output Playback
- (OSStatus)setupRenderPlayback
// Set output callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = playbackCallback;
callbackStruct.inputProcRefCon = (__bridge void * _Nullable)(self);
UInt32 size = sizeof(AURenderCallbackStruct);
OSStatus err = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
1,
&callbackStruct,
size);
checkStatus(err);
return err;
I try to follow this suggestion。但它仍然不起作用。 Here is my example project
【问题讨论】:
所以你展示了所有方便的方法,但你没有展示如何以及何时调用它们。请显示使用这些方法的代码。还有什么是行不通的?有错误吗? @rocky 我在这里发布了我的测试项目github.com/longpham2310/audio-unit-mac-example。你能看看吗! 【参考方案1】:我认为你应该检查 kAudioFormatLinearPCM 是 signed16 还是 signed32,le 还是 be 那么
audioFormat.mBitsPerChannel = 8 * sizeof(UInt32);
audioFormat.mBytesPerPacket = sizeof(UInt32);
audioFormat.mBytesPerFrame = sizeof(UInt32);
应该相应改变
【讨论】:
以上是关于如何在 Mac 上设置录制和播放音频。 Mac 上的 VOIP 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
Swift 4 - 在 mac os 上使用 AVAssetWriter 进行 avfoundation 屏幕和音频录制 - 视频冻结