iOS AudioUnits pass through

后端 未结 1 1256
我寻月下人不归
我寻月下人不归 2021-02-06 10:46

I am trying to write an iOS application that will pass the sound received from microphone to speaker without any changes. I\'ve read apple docs and guides. I choosed the first p

相关标签:
1条回答
  • 2021-02-06 11:37

    As warrenm said setting up a connection between Remote IO elements helped. So the code placed after all initialization done:

    AudioUnitConnection conn;
    conn.destInputNumber = kOutputBus;
    conn.sourceAudioUnit = unit;
    conn.sourceOutputNumber = kInputBus;
    err = AudioUnitSetProperty(unit, kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, kOutputBus, &conn, sizeof(conn));
    if (noErr != err) { [self showStatus:err]; }
    

    UPDATE To make it easy to others to use the solution I will post full code here:

    The .h file

    #import <Foundation/Foundation.h>
    
    @interface AudioController : NSObject
    
    - (void)setUp;
    - (void)start;
    - (void)end;
    @end
    

    The .m file

    #import "AudioController.h"
    #import <AudioToolbox/AudioToolbox.h>
    #import <AVFoundation/AVFoundation.h>
    #import <AudioToolbox/AudioServices.h>
    #define kInputBus 1
    #define kOutputBus 0
    
    @interface AudioController ()
    {
        AudioComponentDescription desc;
        AudioComponent component;
        AudioUnit unit;
        AudioStreamBasicDescription audioFormat;
        double rate;
    }
    @end
    
    @implementation AudioController
    
    - (void)setUp
    {
        AVAudioSession *sess = [AVAudioSession sharedInstance];
        NSError *error = nil;
        rate = 44100.0;
        [sess setPreferredSampleRate:rate error:&error];
        [sess setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
        [sess setActive:YES error:&error];
        rate = [sess sampleRate];
        if (error) {
            NSLog(@"%@", error);
        }
    
        NSLog(@"Initing");
        [self createUnitDesc];
        [self getComponent];
        [self getAudioUnit];
        [self enableIORec];
        [self enableIOPb];
        [self createFormat];
        [self applyFormat];
        OSStatus err = AudioUnitInitialize(unit);
        if (noErr != err) {
            [self showStatus:err];
        }
    
        AudioUnitConnection conn;
        conn.destInputNumber = 0;
        conn.sourceAudioUnit = unit;
        conn.sourceOutputNumber = 1;
        err = AudioUnitSetProperty(unit, kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, 0, &conn, sizeof(conn));
        if (noErr != err) {
            [self showStatus:err];
        }
    }
    
    - (void)createUnitDesc
    {
        desc.componentType = kAudioUnitType_Output;
        desc.componentSubType = kAudioUnitSubType_RemoteIO;
        desc.componentFlags = 0;
        desc.componentFlagsMask = 0;
        desc.componentManufacturer = kAudioUnitManufacturer_Apple;
    
    }
    
    - (void)getComponent
    {
        component = AudioComponentFindNext(NULL, &desc);
    }
    
    - (void)getAudioUnit
    {
        OSStatus res = AudioComponentInstanceNew(component, &unit);
        if (noErr != res) {
            [self showStatus:res];
        }
    }
    
    - (void)enableIORec
    {
        UInt32 flag = 1;
        OSStatus err = AudioUnitSetProperty(unit,
                                      kAudioOutputUnitProperty_EnableIO,
                                      kAudioUnitScope_Input,
                                      kInputBus,
                                      &flag,
                                      sizeof(flag));
        if (noErr != err) {
            [self showStatus:err];
        }
    }
    
    - (void)enableIOPb
    {
        UInt32 flag = 1;
        OSStatus err = AudioUnitSetProperty(unit,
                                      kAudioOutputUnitProperty_EnableIO,
                                      kAudioUnitScope_Output,
                                      kOutputBus,
                                      &flag,
                                      sizeof(flag));
        if (noErr != err) {
            [self showStatus:err];
        }
    }
    
    - (void)createFormat
    {
        // Describe format
        audioFormat.mSampleRate         = rate;
        audioFormat.mFormatID           = kAudioFormatLinearPCM;
        audioFormat.mFormatFlags        = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
        audioFormat.mFramesPerPacket    = 1;
        audioFormat.mChannelsPerFrame   = 1;
        audioFormat.mBitsPerChannel     = 16;
        audioFormat.mBytesPerPacket     = 2;
        audioFormat.mBytesPerFrame      = 2;
    }
    
    - (void)applyFormat
    {
        OSStatus err = AudioUnitSetProperty(unit,
                                      kAudioUnitProperty_StreamFormat,
                                      kAudioUnitScope_Output,
                                      kInputBus,
                                      &audioFormat,
                                      sizeof(audioFormat));
        if (noErr != err) {
            [self showStatus:err];
        }
    }
    
    - (void)start
    {
        NSLog(@"starting");
        OSStatus err = AudioOutputUnitStart(unit);
        if (noErr != err) {
            [self showStatus:err];
        }
    }
    
    - (void)end
    {
        NSLog(@"ending");
        OSStatus err = AudioOutputUnitStop(unit);
        if (noErr != err) {
            [self showStatus:err];
        }
    }
    
    - (void)showStatus:(OSStatus)st
    {
        NSString *text = nil;
        switch (st) {
            case kAudioUnitErr_CannotDoInCurrentContext: text = @"kAudioUnitErr_CannotDoInCurrentContext"; break;
            case kAudioUnitErr_FailedInitialization: text = @"kAudioUnitErr_FailedInitialization"; break;
            case kAudioUnitErr_FileNotSpecified: text = @"kAudioUnitErr_FileNotSpecified"; break;
            case kAudioUnitErr_FormatNotSupported: text = @"kAudioUnitErr_FormatNotSupported"; break;
            case kAudioUnitErr_IllegalInstrument: text = @"kAudioUnitErr_IllegalInstrument"; break;
            case kAudioUnitErr_Initialized: text = @"kAudioUnitErr_Initialized"; break;
            case kAudioUnitErr_InstrumentTypeNotFound: text = @"kAudioUnitErr_InstrumentTypeNotFound"; break;
            case kAudioUnitErr_InvalidElement: text = @"kAudioUnitErr_InvalidElement"; break;
            case kAudioUnitErr_InvalidFile: text = @"kAudioUnitErr_InvalidFile"; break;
            case kAudioUnitErr_InvalidOfflineRender: text = @"kAudioUnitErr_InvalidOfflineRender"; break;
            case kAudioUnitErr_InvalidParameter: text = @"kAudioUnitErr_InvalidParameter"; break;
            case kAudioUnitErr_InvalidProperty: text = @"kAudioUnitErr_InvalidProperty"; break;
            case kAudioUnitErr_InvalidPropertyValue: text = @"kAudioUnitErr_InvalidPropertyValue"; break;
            case kAudioUnitErr_InvalidScope: text = @"kAudioUnitErr_InvalidScope"; break;
            case kAudioUnitErr_NoConnection: text = @"kAudioUnitErr_NoConnection"; break;
            case kAudioUnitErr_PropertyNotInUse: text = @"kAudioUnitErr_PropertyNotInUse"; break;
            case kAudioUnitErr_PropertyNotWritable: text = @"kAudioUnitErr_PropertyNotWritable"; break;
            case kAudioUnitErr_TooManyFramesToProcess: text = @"kAudioUnitErr_TooManyFramesToProcess"; break;
            case kAudioUnitErr_Unauthorized: text = @"kAudioUnitErr_Unauthorized"; break;
            case kAudioUnitErr_Uninitialized: text = @"kAudioUnitErr_Uninitialized"; break;
            case kAudioUnitErr_UnknownFileType: text = @"kAudioUnitErr_UnknownFileType"; break;
            default: text = @"unknown error";
        }
        NSLog(@"TRANSLATED_ERROR = %li = %@", st, text);
    }
    
    - (void)dealloc
    {
        AudioUnitUninitialize(unit);
    
        [super dealloc];
    }
    
    @end
    
    0 讨论(0)
提交回复
热议问题