3

アプリケーションで再生されているオーディオを録音 (ドキュメント ディレクトリにファイルとして保存) したいと考えていました。基本的に、オーディオ出力バッファにフックして、それらのバッファをファイルに読み込んだり保存したりできますか?

私はいくつかのブログを読み、グーグルで検索しました。それらのほとんどは、AudioUnit を指していました。

AudioUnit - RemoteIO を使用してみましたが、やりたいことを達成できませんでした。おそらく何かを台無しにしました。

以下は、AudioUnit を初期化するために作成したコードです。

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, &mAudioUnit);

// Enable IO for recording
UInt32 flag = 1

// Enable IO for playback
status = AudioUnitSetProperty(mAudioUnit, 
                              kAudioOutputUnitProperty_EnableIO, 
                              kAudioUnitScope_Output, 
                              kOutputBus,
                              &flag, 
                              sizeof(flag));

// Describe format
AudioStreamBasicDescription audioFormat={0};
audioFormat.mSampleRate         = kSampleRate;
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(mAudioUnit, 
                              kAudioUnitProperty_StreamFormat, 
                              kAudioUnitScope_Output, 
                              kInputBus, 
                              &audioFormat, 
                              sizeof(audioFormat));


// Set input callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = playbackCallback;
callbackStruct.inputProcRefCon = self;

status = AudioUnitSetProperty(mAudioUnit, 
                              kAudioUnitProperty_SetRenderCallback, 
                              kAudioUnitScope_Input, 
                              kOutputBus,
                              &callbackStruct, 
                              sizeof(callbackStruct));
AudioUnitInitialize(mAudioUnit);
AudioOutputUnitStart(mAudioUnit);

そして、playbackCallback で:

static OSStatus playbackCallback(void *inRefCon, 
                             AudioUnitRenderActionFlags *ioActionFlags, 
                             const AudioTimeStamp *inTimeStamp, 
                             UInt32 inBusNumber, 
                             UInt32 inNumberFrames, 
                             AudioBufferList *ioData) {    
double timeInSeconds = inTimeStamp->mSampleTime / kSampleRate;
printf("\nPLAYBACK %fs inBusNumber: %lu inNumberFrames: %lu ", timeInSeconds, inBusNumber, inNumberFrames);

AudioBufferList bufferList;

SInt16 samples[inNumberFrames]; // A large enough size to not have to worry about buffer overrun
memset (&samples, 0, sizeof (samples));

bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mData = samples;
bufferList.mBuffers[0].mNumberChannels = 1;
bufferList.mBuffers[0].mDataByteSize = inNumberFrames*sizeof(SInt16);

ViewController* THIS = THIS = (__bridge ViewController *)inRefCon;

OSStatus status;
status = AudioUnitRender(THIS->mAudioUnit,     
                         ioActionFlags, 
                         inTimeStamp, 
                         kOutputBus, 
                         inNumberFrames, 
                         &bufferList);

if (noErr != status) {

    printf("AudioUnitRender error: %ld", status); 
    return noErr;
}

// Now, we have the samples we just read sitting in buffers in bufferList
ExtAudioFileWriteAsync(THIS->mAudioFileRef, inNumberFrames, &bufferList);

return noErr;
}

上記の mAudioFileRef は、 で作成した mp3 ファイルの参照ですviewDidLoad

上記のプログラムを実行すると、AudioUnitRender Error: -50 が発生します。mp3 ファイルにデータが取り込まれていません。

おそらく、オーディオ ユニットの設定または ioData からのバッファの読み取りで何らかの間違いを犯したのでしょう。

どんな種類の助けも大歓迎です。

4

1 に答える 1

0

Ok。ここで多くのことがうまくいかない可能性があります。

  • ExtAudioFileRef をどのように初期化しているのかわかりません。
  • どのクライアント形式に設定していますか。
  • それに設定しているオーディオ形式は何ですか(ええ、mp3です)。
  • 使用しているファイル形式。
  • それらはすべてシームレスに連携する必要があります。

それにもかかわらず、このエントリを見てください。これは完全に機能するサンプル コードです。

RemoteIO から AAC への記録: データは書き込まれていますが、ファイルは再生できません

そして、それはあなたが必要とすることをちょっとします。その場で圧縮オーディオを録音します。

ExtAudioFileWriteAsyncこのように(コールバックの前に)初期化しましたか?

ExtAudioFileWriteAsync(extAudioFileRefVar, 0, NULL);

コードを追加せずに、考えられるすべてのことの中で、何がうまくいかないのかを判断するのは非常に困難です。

于 2012-08-15T15:44:51.857 に答える