Как кодировать данные AAC из данных PCM в iPhone SDK? (iphone dev / Audio) - PullRequest
1 голос
/ 13 января 2012

Полагаю, "AudioConverterFillComplexBuffer" - это решение.

Но я не знаю, правильный ли это путь.

+ 1.AudioUnit

инициализировать AudioUnit: «recordingCallback» является методом обратного вызова.выходной формат PCM.запись в файл. (Я проиграл записанный файл).

+ 2.AudioConverter

добавить «AudioConverterFillComplexBuffer» Я не знаю об этом хорошо.добавлено,

+ 3.Проблема

Метод «audioConverterComplexInputDataProc» вызывается только один раз.

Как использовать API-интерфейс AudioConverter?

Прикреплен мой код

#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

Ответы [ 2 ]

1 голос
/ 16 мая 2015

Мне потребовалось много времени, чтобы понять AudioConverterFillComplexBuffer, и особенно, как использовать его для преобразования звука в режиме реального времени.Я опубликовал свой подход здесь: Как использовать AudioConverter в CoreAudio для кодирования AAC в режиме реального времени?

0 голосов
/ 23 февраля 2014

Ссылка https://developer.apple.com/library/ios/samplecode/iPhoneACFileConvertTest/Introduction/Intro.html

Он демонстрирует использование API-интерфейсов Audio Converter для преобразования аудиоформата PCM в сжатый формат, включая AAC.

...