3

「 」が解決策だと思いAudioConverterFillComplexBufferます。

しかし、この方法が正しいかどうかはわかりません。

+1。AudioUnit

initialize AudioUnit : "recordingCallback" はコールバック メソッドです。出力形式は PCM です。ファイルに録音します(録音したファイルを再生しました)。

+2。オーディオコンバーター

add "AudioConverterFillComplexBuffer" よくわかりません。追加した、

+3。問題

「audioConverterComplexInputDataProc」メソッドは 1 回だけ呼び出されます。

AudioConverter API を使用するにはどうすればよいですか?

私のコードを添付

#import "AACAudioRecorder.h"
#define kOutputBus 0
#define kInputBus 1
@implementation AACAudioRecorder
            
            

これは AudioConverterFillComplexBuffer のコールバック メソッドです。

static OSStatus audioConverterComplexInputDataProc(  AudioConverterRef               inAudioConverter,
                                      UInt32*                         ioNumberDataPackets,
                                      AudioBufferList*                ioData,
                                      AudioStreamPacketDescription**  outDataPacketDescription,
                                      void*                           inUserData){
    ioData = (AudioBufferList*)inUserData;
    return 0;
}

これは AudioUnit のコールバックです。

static OSStatus recordingCallback(void *inRefCon, 
                                        AudioUnitRenderActionFlags *ioActionFlags, 
                                        const AudioTimeStamp *inTimeStamp, 
                                        UInt32 inBusNumber, 
                                        UInt32 inNumberFrames, 
                                        AudioBufferList *ioData) {
   @autoreleasepool {

       AudioBufferList *bufferList;
       
       AACAudioRecorder *THIS = (AACAudioRecorder *)inRefCon;
       OSStatus err = AudioUnitRender(THIS-> m_audioUnit , 
                                             ioActionFlags, 
                                             inTimeStamp, 1, inNumberFrames, bufferList);    

       if (err) { NSLog(@"%s AudioUnitRender error %d\n",__FUNCTION__, (int)err); return err; }
       
       NSString *recordFile = 
                       [NSTemporaryDirectory() stringByAppendingPathComponent: @"auioBuffer.pcm"];
       FILE *fp;
       fp = fopen([recordFile UTF8String], "a+");
       fwrite(bufferList->mBuffers[0].mData, sizeof(Byte), 
bufferList->mBuffers[0].mDataByteSize, fp);
       fclose(fp);    

       [THIS convert:bufferList ioOutputDataPacketSize:&inNumberFrames];     

   if (err) {NSLog(@"%s : AudioFormat Convert error %d\n",__FUNCTION__, (int)err);  }
    }
    return noErr;
}

状態確認方法

static void checkStatus(OSStatus status, const char* str){
    if (status != noErr) {
        NSLog(@"%s %s error : %ld ",__FUNCTION__, str, status);
    }
}

変換方法:PCM→AAC

- (void)convert:(AudioBufferList*)input_bufferList ioOutputDataPacketSize:(UInt32*)packetSizeRef 
{
    UInt32 size = sizeof(UInt32);
    UInt32 maxOutputSize;
    AudioConverterGetProperty(m_audioConverterRef, 
                              kAudioConverterPropertyMaximumOutputPacketSize, 
                              &size, 
                              &maxOutputSize);
    
    AudioBufferList *output_bufferList = (AudioBufferList *)malloc(sizeof(AudioBufferList));

    output_bufferList->mNumberBuffers               = 1;
    output_bufferList->mBuffers[0].mNumberChannels  = 1;
    output_bufferList->mBuffers[0].mDataByteSize    = *packetSizeRef * 2;
    output_bufferList->mBuffers[0].mData  = (AudioUnitSampleType *)malloc(*packetSizeRef * 2);

    OSStatus        err;
    err = AudioConverterFillComplexBuffer(
                                          m_audioConverterRef,
                                          audioConverterComplexInputDataProc,
                                          input_bufferList,
                                          packetSizeRef,
                                          output_bufferList,
                                          NULL
                                          );


    if (err) {NSLog(@"%s : AudioFormat Convert error %d\n",__FUNCTION__, (int)err);  }
}

これが初期化メソッドです。

- (void)initialize
{ 
    // ...
    
    
    OSStatus status;
    
    // Describe audio component
    AudioComponentDescription desc;
    desc.componentType = kAudioUnitType_Output;
    desc.componentSubType = kAudioUnitSubType_RemoteIO;
    desc.componentFlags = 0;
    desc.componentFlagsMask = 0;
    desc.componentManufacturer = kAudioUnitManufacturer_Apple;
    
    // Get component
    AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);
    
    // Get audio units
    status = AudioComponentInstanceNew(inputComponent, &m_audioUnit);
    checkStatus(status,"AudioComponentInstanceNew");
    
    // Enable IO for recording
    UInt32 flag = 1;
    status = AudioUnitSetProperty(m_audioUnit, 
                                  kAudioOutputUnitProperty_EnableIO, 
                                  kAudioUnitScope_Input, 
                                  kInputBus,
                                  &flag, 
                                  sizeof(flag));
    checkStatus(status,"Enable IO for recording");
    
    // Enable IO for playback
    status = AudioUnitSetProperty(m_audioUnit, 
                                  kAudioOutputUnitProperty_EnableIO, 
                                  kAudioUnitScope_Output, 
                                  kOutputBus,
                                  &flag, 
                                  sizeof(flag));
    checkStatus(status,"Enable IO for playback");
    
    // Describe format
    AudioStreamBasicDescription audioFormat;
    audioFormat.mSampleRate   = 44100.00;
    audioFormat.mFormatID   = kAudioFormatLinearPCM;
    audioFormat.mFormatFlags  = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    audioFormat.mFramesPerPacket = 1;
    audioFormat.mChannelsPerFrame = 1;
    audioFormat.mBitsPerChannel  = 16;
    audioFormat.mBytesPerPacket  = 2;
    audioFormat.mBytesPerFrame  = 2;
    
    // Apply format
    status = AudioUnitSetProperty(m_audioUnit, 
                                  kAudioUnitProperty_StreamFormat, 
                                  kAudioUnitScope_Output, 
                                  kInputBus, 
                                  &audioFormat, 
                                  sizeof(audioFormat));
    checkStatus(status,"Apply format1");
    status = AudioUnitSetProperty(m_audioUnit, 
                                  kAudioUnitProperty_StreamFormat, 
                                  kAudioUnitScope_Input, 
                                  kOutputBus, 
                                  &audioFormat, 
                                  sizeof(audioFormat));
    checkStatus(status,"Apply format2");
    
    
    // Set input callback
    AURenderCallbackStruct callbackStruct;
    callbackStruct.inputProc = recordingCallback;
    callbackStruct.inputProcRefCon = self;
    status = AudioUnitSetProperty(m_audioUnit, 
                                  kAudioOutputUnitProperty_SetInputCallback, 
                                  kAudioUnitScope_Global, 
                                  kInputBus, 
                                  &callbackStruct, 
                                  sizeof(callbackStruct));
    checkStatus(status,"Set input callback");

    // Initialise
    status = AudioUnitInitialize(m_audioUnit);
    checkStatus(status,"AudioUnitInitialize");

    // Set ASBD For converting Output Stream
    
    AudioStreamBasicDescription outputFormat;
    memset(&outputFormat, 0, sizeof(outputFormat));
    outputFormat.mSampleRate  = 44100.00;
    outputFormat.mFormatID   = kAudioFormatMPEG4AAC;
    outputFormat.mFormatFlags       = kMPEG4Object_AAC_Main; 
    outputFormat.mFramesPerPacket = 1024;
    outputFormat.mChannelsPerFrame = 1;
    outputFormat.mBitsPerChannel = 0;
    outputFormat.mBytesPerFrame = 0;
    outputFormat.mBytesPerPacket = 0;

    //Create An Audio Converter
    status = AudioConverterNew( &audioFormat, &outputFormat, &m_audioConverterRef );
    checkStatus(status,"Create An Audio Converter");
    if(m_audioConverterRef) NSLog(@"m_audioConverterRef is created");

}

AudioOutputUnitStart

- (void)StartRecord
{
    OSStatus status = AudioOutputUnitStart(m_audioUnit);
    checkStatus(status,"AudioOutputUnitStart");
}

AudioOutputUnitStop

- (void)StopRecord
{
    OSStatus status = AudioOutputUnitStop(m_audioUnit);
    checkStatus(status,"AudioOutputUnitStop");
}

終了

- (void)finish
{
    AudioUnitUninitialize(m_audioUnit);
}


@end
4

2 に答える 2

1

参照https://developer.apple.com/library/ios/samplecode/iPhoneACFileConvertTest/Introduction/Intro.html

オーディオ コンバーター API を使用して、PCM オーディオ形式から AAC を含む圧縮形式に変換する方法を示します。

于 2014-02-23T15:51:52.580 に答える