How to setup for record and playback audio on Mac. VOIP app on Mac
Asked Answered
R

1

17

I want to record and playback audio in Mac. Now, I have some problems about the settings for Input/Output/ChannelFormat … I showed you some code I try below.

// 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. But It’s still doesn’t work. Here is my example project

Rough answered 8/8, 2016 at 4:29 Comment(2)
So you show all your convenience methods but you don't show how and when you call them. Please show the code that uses these methods. Also what exactly doesn't work? Is there an error?Linda
@Linda I posted my test project here github.com/longpham2310/audio-unit-mac-example .Can you have a look please!Rough
L
2

I think you should check kAudioFormatLinearPCM is signed16 or signed32, le or be then

audioFormat.mBitsPerChannel     = 8 * sizeof(UInt32);
audioFormat.mBytesPerPacket     = sizeof(UInt32);
audioFormat.mBytesPerFrame      = sizeof(UInt32);

should be changed accordingly

Laugh answered 19/8, 2016 at 8:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.