10

この質問をもう少し簡潔になるように書き直します。

私の問題は、リモート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つ目は、そのループの録音されたオーディオです。うまくいけば、それは誰かに何がうまくいかないかについての手がかりを与えるかもしれません。

オリジナルmp3

mp3の録音に問題があります

4

1 に答える 1

9

数日間の涙と髪の毛を引っ張った後、私は解決策を持っています。

私のコードや他の例では、extaudiofilewriteasyncがremoteioユニットのコールバックでそのように呼び出されているのを見てきました。

**remoteiounitコールバック**

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;

}

このコールバックでは、eqsを適用してオーディオをミキシングする別のオーディオユニットからオーディオデータを取得しています。

remoteioコールバックからremoteioがプルし、ファイルが正常に書き込むこの他のコールバックへのextaudiofilewriteasync呼び出しを削除しました!!

* equnitsコールバック関数*

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;

}

私のソリューションが機能した理由を完全に理解するために、remoteioのiodataバッファリストからファイルにデータを書き込むとオーディオが歪むのに、チェーンをさらに1ステップ下にデータを書き込むと完全なオーディオになる理由を誰かが説明できますか?

于 2011-08-05T16:08:16.017 に答える