アプリケーションで再生されているオーディオを録音 (ドキュメント ディレクトリにファイルとして保存) したいと考えていました。基本的に、オーディオ出力バッファにフックして、それらのバッファをファイルに読み込んだり保存したりできますか?
私はいくつかのブログを読み、グーグルで検索しました。それらのほとんどは、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 からのバッファの読み取りで何らかの間違いを犯したのでしょう。
どんな種類の助けも大歓迎です。