2011-08-03 47 views
10

重写这个问题要更有效一些。将音频写入磁盘从IO单元

我的问题是,我无法成功地从远程IO单元写入音频文件到磁盘。

我拿着的步骤是

打开一个mp3文件并提取其音频缓冲区。 我根据图的属性设置了一个asbd以与我的图形一起使用。 我安装并运行我的图形循环提取的音频和声音成功地出来扬声器!

我有困难的是从远程IO回调采取音频采样,并将它们写入磁盘上的音频文件,我正在使用ExtAudioFileWriteASync。

音频文件确实被写入,并且与原始mp3有一些可听的相似之处,但听起来非常失真。

我不知道,如果问题是

A)ExtAudioFileWriteAsync不能以最快的速度IO单元的回调提供了他们写的样本。

  • 或 -

B)我已成立了ASBD为extaudiofile refeference错误。我想先保存一个wav文件。我不确定我是否在下面的ASBD中正确描述了这一点。

其次,我不确定创建音频文件时传递给inChannelLayout属性的值。

最后我很不确定什么asbd用于kExtAudioFileProperty_ClientDataFormat。 我一直在使用我的立体声流格式,但仔细看看文档说这必须是pcm。这应该与remoteio的输出格式相同吗?如果是的话,我错了将远程io的输出格式设置为stereostreamformat?

我意识到这个问题存在很多,但我有很多不确定因素,我似乎无法自行清理。

设置立体声流格式

- (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个样本。第一个是Im循环和尝试复制的原始音频。第二个是该循环的录制音频。希望这可能会给某些人一些线索,看看哪里出了问题。

Original mp3

Problem recording of mp3

+0

愚蠢的问题,但你检查'sizeof(AudioUnitSampleType);'返回相同的大小,你分配给'mBytesPerPacket'? –

+0

我仔细检查确定。他们都是相同的大小。 – dubbeat

+0

@dubbeat hv你用记录音频做了 – Aadil

回答

9

一对夫妇的眼泪&头发拉我有一个解决方案的天之后。

在我的代码和其他例子中,我看到extaudiofilewriteasync在遥控单元的回调中被调用,像这样。

** 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; 

} 

在此回调,我从适用公式和混合音频另一种音频单元拉音频数据。

我从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 bufferlist文件利息导致音频失真,但写作数据又向下走了一步,结果是完美的音频?

+0

你能解释一下你的解决方案吗?我面临同样的问题。在回调中写入文件的音频数据失真。我们应该写入哪个回调? – Namratha

+0

这真的取决于你的AUGraph。我从经验中发现的是,试图从remoteio(节点0)的输出回调中将音频写入磁盘通常不起作用。而应将其放置在某个其他节点的输入回调中。如果您使用源代码编写更完整的问题,我可能会帮助您更多。 – dubbeat