7

Audio Units を使用して音楽録音アプリをコーディングしていますが、結果として得られる M4A ファイルで、それほど素晴らしいブーンというノイズ以外のものを再生する際に問題が発生しています。これらの SOソース 参照として使用し、トラブルシューティングのためにあらゆることを試しました。

AUGraphマルチチャンネルミキサーとリモート I/O の 2 つのノードを持っています。ミキサーには 2 つの入力コールバックがあります。1 つはマイクから入力をプルするもので、もう 1 つはオーディオ ファイルからプルするものです。ミキサー出力は、I/O ユニットの出力スコープの入力要素に接続されています。これにより、同時 I/O が可能になります。

出力をキャプチャするために、コールバックと 2 つのメソッドを追加しました。

コールバック

static OSStatus recordAndSaveCallback (void *                inRefCon,
                                       AudioUnitRenderActionFlags * ioActionFlags,
                                       const AudioTimeStamp *       inTimeStamp,
                                       UInt32                       inBusNumber,
                                       UInt32                       inNumberFrames,
                                       AudioBufferList *            ioData) 
{
    Mixer* THIS = (__bridge Mixer*)inRefCon;
    AudioBufferList bufferList;

    OSStatus status;
    status = AudioUnitRender(THIS.ioUnit,    
                             ioActionFlags,
                             inTimeStamp,
                             0,
                             inNumberFrames,
                             &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);

    OSStatus result;
    if (*ioActionFlags == kAudioUnitRenderAction_PostRender) {
        result =  ExtAudioFileWriteAsync(THIS.extAudioFileRef, inNumberFrames, &bufferList);
        if(result) printf("ExtAudioFileWriteAsync %ld \n", result);}
    return noErr; 
}

録音方法:

- (void)recordFile
{    
    OSStatus result;

    NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *recordFile = [documentsDirectory stringByAppendingPathComponent: @"audio.m4a"];

    CFURLRef destinationURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, 
                                                            (__bridge   CFStringRef)recordFile, 
                                                            kCFURLPOSIXPathStyle, 
                                                            false);    

    AudioStreamBasicDescription destinationFormat;
    memset(&destinationFormat, 0, sizeof(destinationFormat));
    destinationFormat.mChannelsPerFrame = 1;
    destinationFormat.mFormatID = kAudioFormatMPEG4AAC;
    UInt32 size = sizeof(destinationFormat);
    result = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &destinationFormat);        
    if(result) printf("AudioFormatGetProperty %ld \n", result);    


    result = ExtAudioFileCreateWithURL(destinationURL, 
                                       kAudioFileM4AType, 
                                       &destinationFormat, 
                                       NULL, 
                                       kAudioFileFlags_EraseFile, 
                                       &extAudioFileRef);
    if(result) printf("ExtAudioFileCreateWithURL %ld \n", result);


    AudioStreamBasicDescription clientFormat;
    memset(&clientFormat, 0, sizeof(clientFormat));


    UInt32 clientsize = sizeof(clientFormat);   
    result = AudioUnitGetProperty(ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &clientFormat, &clientsize);
    if(result) printf("AudioUnitGetProperty %ld \n", result);

    UInt32 codec = kAppleHardwareAudioCodecManufacturer;

    result = ExtAudioFileSetProperty(extAudioFileRef, 
                                     kExtAudioFileProperty_CodecManufacturer, 
                                     sizeof(codec), 
                                     &codec);

    if(result) printf("ExtAudioFileSetProperty %ld \n", result);


    result = ExtAudioFileSetProperty(extAudioFileRef,kExtAudioFileProperty_ClientDataFormat,sizeof(clientFormat), &clientFormat);
    if(result) printf("ExtAudioFileSetProperty %ld \n", result);


    result =  ExtAudioFileWriteAsync(extAudioFileRef, 0, NULL);
    if (result) {[self printErrorMessage: @"ExtAudioFileWriteAsync error" withStatus: result];}

   result = AudioUnitAddRenderNotify(ioUnit, recordAndSaveCallback, (__bridge void*)self);
    if (result) {[self printErrorMessage: @"AudioUnitAddRenderNotify" withStatus: result];}     
}

保存方法:

- (void) saveFile {
    OSStatus status = ExtAudioFileDispose(extAudioFileRef);
    NSLog(@"OSStatus(ExtAudioFileDispose): %ld\n", status);

}

これは私のコンソールに表示されるものです:

Stopping audio processing graph
OSStatus(ExtAudioFileDispose): 0
ExtAudioFileWriteAsync -50 
ExtAudioFileWriteAsync -50 
ExtAudioFileWriteAsync -50 

私のコードは、これを機能させた人のコードと非常に似ているように思えますが、明らかに重大なエラーを犯しました。きっと他にも悩んでいる人がいるはずです。

誰にも洞察力がありますか?

ありがとう。

4

1 に答える 1

1

私は質問がずっと前に尋ねられたことを知っています、そしてあなたはおそらく今までにエラーを見つけたでしょう、私は同じ問題を抱えているかもしれない他の人に答えているだけです.

私は間違っているかもしれませんが、バッファのスコープ内変数宣言を行っているという事実から問題が発生していると思います。

変えることをお勧めします

SInt16 samples[inNumberFrames];

の中へ

SInt16* samples = malloc(inNumberFrames * sizeof(SInt16));

recordAndSaveCallback はバッファ リストを満たすためのものであるため、スコープ内で宣言を行うと、スコープが終了するとすぐにデータが破棄されます。

于 2012-11-13T16:48:06.920 に答える