この質問をもう少し簡潔になるように書き直します。
私の問題は、リモートIOユニットからディスクにオーディオファイルを正常に書き込めないことです。
私が取った手順は
mp3ファイルを開き、そのオーディオをバッファに抽出します。グラフのプロパティに基づいて、グラフで使用するasbdを設定しました。抽出した音声をループさせてグラフを設定して実行すると、スピーカーから音声が正常に出力されます。
私が苦労しているのは、リモートIOコールバックからオーディオサンプルを取得し、ExtAudioFileWriteASyncを使用しているディスク上のオーディオファイルに書き込むことです。
オーディオファイルは書き込まれ、元のmp3にある程度類似していますが、非常に歪んで聞こえます。
問題が
A)ExtAudioFileWriteAsyncは、ioユニットコールバックが提供する速度でサンプルを書き込むことができません。
- また -
B)extaudiofile参照用にASBDを間違って設定しました。まず、wavファイルを保存したいと思いました。以下のASBDでこれを適切に説明したかどうかはわかりません。
次に、オーディオファイルを作成するときにinChannelLayoutプロパティに渡す値がわかりません。
そして最後に、kExtAudioFileProperty_ClientDataFormatにどのasbdを使用するかについて非常に不確かです。私はステレオストリーム形式を使用していましたが、ドキュメントを詳しく見ると、これはpcmである必要があります。これは、remoteioの出力と同じ形式にする必要がありますか?もしそうなら、私はリモートioの出力フォーマットをステレオストリームフォーマットに設定するのは間違っていましたか?
この質問には非常に多くのことがあることに気づきましたが、私には多くの不確実性があり、自分では解決できないようです。
ステレオストリーム形式の設定
- (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 :");
}
ステレオストリーム形式を使用してremoteioコールバックを設定する
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つのサンプルを添付しています。1つ目は、Imがループしてコピーしようとしている元のオーディオです。2つ目は、そのループの録音されたオーディオです。うまくいけば、それは誰かに何がうまくいかないかについての手がかりを与えるかもしれません。