Запись аудио на диск с устройства ввода-вывода - PullRequest
10 голосов
/ 03 августа 2011

Переписать этот вопрос, чтобы он был немного более подходящим.

Моя проблема в том, что я не могу успешно записать аудиофайл на диск с удаленного модуля ввода-вывода.

Шаги, которые я предпринял, были следующие:

Откройте mp3-файл и извлеките его аудио в буферы.Я настроил asbd для использования с моим графиком на основе свойств графика.Я настраиваю и запускаю свой график, зацикливая извлеченные аудио и звук, успешно выходящий из динамика!

С чем я сталкиваюсь, так это с извлечением аудиосэмплов из удаленного обратного вызова ввода-вывода и записью их в аудиофайл на диске.для которого я использую ExtAudioFileWriteASync.

Аудиофайл записывается и имеет некоторое реальное сходство с оригинальным mp3, но звучит очень искаженно.

Я не уверен, что проблема

A) ExtAudioFileWriteAsync не может записывать сэмплы так быстро, как их обеспечивает обратный вызов модуля io.

  • или -

B) Я настроил ASBDдля ссылки extaudiofile неправильно.Я хотел начать с сохранения файла WAV.Я не уверен, правильно ли я описал это в ASBD ниже.

Во-вторых, я не уверен, какое значение передать для свойства inChannelLayout при создании аудиофайла.

И, наконец, я совершенно не уверен, какой asbd использовать для kExtAudioFileProperty_ClientDataFormat.Я использовал мой формат стереопотока, но при более внимательном рассмотрении документов мы говорим, что это должен быть pcm.Должен ли это быть тот же формат, что и вывод для remoteio?И если так, то я ошибся, установив выходной формат удаленного ввода-вывода в стереостримформат?

Я понимаю, что в этом вопросе есть и очень много, но у меня есть много неопределенностей, которые я не могу устранить самостоятельно.

настройка формата стереопотока

- (void) setupStereoStreamFormat
{

    size_t bytesPerSample = sizeof (AudioUnitSampleType);
    stereoStreamFormat.mFormatID          = kAudioFormatLinearPCM;
    stereoStreamFormat.mFormatFlags       = kAudioFormatFlagsAudioUnitCanonical;
    stereoStreamFormat.mBytesPerPacket    = bytesPerSample;
    stereoStreamFormat.mFramesPerPacket   = 1;
    stereoStreamFormat.mBytesPerFrame     = bytesPerSample;
    stereoStreamFormat.mChannelsPerFrame  = 2;                    // 2 indicates stereo
    stereoStreamFormat.mBitsPerChannel    = 8 * bytesPerSample;
    stereoStreamFormat.mSampleRate        = engineDescribtion.samplerate;

    NSLog (@"The stereo stereo format :");


}

настройка удаленного обратного вызова с использованием формата стереопотока

AudioUnitSetProperty(engineDescribtion.masterChannelMixerUnit, 
                             kAudioUnitProperty_StreamFormat, 
                             kAudioUnitScope_Output, 
                             masterChannelMixerUnitloop, 
                             &stereoStreamFormat, 
                             sizeof(stereoStreamFormat));

        AudioUnitSetProperty(engineDescribtion.masterChannelMixerUnit, 
                             kAudioUnitProperty_StreamFormat, 
                             kAudioUnitScope_Input, 
                             masterChannelMixerUnitloop, 
                             &stereoStreamFormat, 
                             sizeof(stereoStreamFormat));




static OSStatus masterChannelMixerUnitCallback(void *inRefCon, 
                              AudioUnitRenderActionFlags *ioActionFlags, 
                              const AudioTimeStamp *inTimeStamp, 
                              UInt32 inBusNumber, 
                              UInt32 inNumberFrames, 
                              AudioBufferList *ioData)

{

   // ref.equnit;
    //AudioUnitRender(engineDescribtion.channelMixers[inBusNumber], ioActionFlags, inTimeStamp, 0, inNumberFrames, ioData);
    Engine *engine= (Engine *) inRefCon;
    AudioUnitRender(engineDescribtion.equnit, ioActionFlags, inTimeStamp, 0, inNumberFrames, ioData);

    if(engine->isrecording)
    {
        ExtAudioFileWriteAsync(engine->recordingfileref, inNumberFrames, ioData);

    }


    return 0;

}

**настройки записи **

-(void)startrecording

{

    NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    destinationFilePath = [[NSString alloc] initWithFormat: @"%@/testrecording.wav", documentsDirectory];
    destinationURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)destinationFilePath, kCFURLPOSIXPathStyle, false);

    OSStatus status;

    // prepare a 16-bit int file format, sample channel count and sample rate
    AudioStreamBasicDescription dstFormat;
    dstFormat.mSampleRate=44100.0;
    dstFormat.mFormatID=kAudioFormatLinearPCM;
    dstFormat.mFormatFlags=kAudioFormatFlagsNativeEndian|kAudioFormatFlagIsSignedInteger|kAudioFormatFlagIsPacked;
    dstFormat.mBytesPerPacket=4;
    dstFormat.mBytesPerFrame=4;
    dstFormat.mFramesPerPacket=1;
    dstFormat.mChannelsPerFrame=2;
    dstFormat.mBitsPerChannel=16;
    dstFormat.mReserved=0;

    // create the capture file
  status=  ExtAudioFileCreateWithURL(destinationURL, kAudioFileWAVEType, &dstFormat, NULL, kAudioFileFlags_EraseFile, &recordingfileref);
    CheckError( status ,"couldnt create audio file");
        // set the capture file's client format to be the canonical format from the queue
 status=ExtAudioFileSetProperty(recordingfileref, kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &stereoStreamFormat);

    CheckError( status ,"couldnt set input format");

    ExtAudioFileSeek(recordingfileref, 0);
 isrecording=YES;

  // [documentsDirectory release];


}

редактировать 1

Я сейчас действительно в темноте, но мне нужно использовать аудио конвертер или kExtAudioFileProperty_ClientDataFormatпозаботиться об этом?

изменить 2

Я прилагаю 2 образца звука.Первый - это оригинальное аудио, которое я зацикливаю и пытаюсь скопировать.Второй записанный звук этого цикла.Надеемся, что это может дать кому-то понять, что происходит не так.

Оригинальный mp3

Проблема записи mp3

1 Ответ

9 голосов
/ 05 августа 2011

После нескольких дней слез и распутывания волос у меня есть решение.

В моем коде и в других примерах я видел, как extaudiofilewriteasync вызывался в обратном вызове для модуля remoteio следующим образом.

** дистанционный обратный вызов **

static OSStatus masterChannelMixerUnitCallback(void *inRefCon, 
                              AudioUnitRenderActionFlags *ioActionFlags, 
                              const AudioTimeStamp *inTimeStamp, 
                              UInt32 inBusNumber, 
                              UInt32 inNumberFrames, 
                              AudioBufferList *ioData)

{


    AudioUnitRender(engineDescribtion.equnit, ioActionFlags, inTimeStamp, 0, inNumberFrames, ioData);


    if(isrecording)
    {
        ExtAudioFileWriteAsync(engine->recordingfileref, inNumberFrames, ioData);


    }



    return 0;

}

В этом обратном вызове я извлекаю аудиоданные из другого аудиоустройства, которое применяет эквалайзеры и микширует аудио.

Я удалил вызов extaudiofilewriteasync из обратного вызова remoteio к этому другому обратному вызову, который удаленный remoteio извлекает, и файл успешно записывается !!

* Эквивалент функции обратного вызова *

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


    AudioUnitRender(engineDescribtion.masterChannelMixerUnit, ioActionFlags, inTimeStamp, 0, inNumberFrames, ioData);

   //process audio here    

    Engine *engine= (Engine *) inRefCon;


    OSStatus s;

    if(engine->isrecording)
    {
        s=ExtAudioFileWriteAsync(engine->recordingfileref, inNumberFrames, ioData);


    }


    return noErr;

}

В интересах полного понимания того, почему сработало мое решение, кто-нибудь может объяснить мне, почему запись данных в файл из списка буферов iodata remoteio вызывает искаженное аудио, а запись данных еще на один шаг вниз по цепочке приводит к идеальному аудио?

...