Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/112.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 从IO单元将音频写入磁盘_Iphone_Ios_Core Audio_Audiounit - Fatal编程技术网

Iphone 从IO单元将音频写入磁盘

Iphone 从IO单元将音频写入磁盘,iphone,ios,core-audio,audiounit,Iphone,Ios,Core Audio,Audiounit,把这个问题改写得更成功一点 我的问题是,我无法成功地从远程IO单元将音频文件写入磁盘 我采取的步骤是 打开mp3文件并将其音频提取到缓冲区。 我根据图形的属性设置了一个用于图形的asbd。 我设置并运行我的图形循环提取的音频和声音成功出来的扬声器 我遇到的困难是从远程IO回调中获取音频样本,并将它们写入磁盘上的音频文件中,我正在使用ExtAudioFileWriteASync 音频文件确实被写入,并且与原始mp3有一些相似之处,但听起来非常失真 我不确定问题是否在 A) ExtAudioFile

把这个问题改写得更成功一点

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

我采取的步骤是

打开mp3文件并将其音频提取到缓冲区。 我根据图形的属性设置了一个用于图形的asbd。 我设置并运行我的图形循环提取的音频和声音成功出来的扬声器

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

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

我不确定问题是否在

A) ExtAudioFileWriteAsync无法像io单元回调提供的那样快速写入示例

  • 或-
B) 我为extaudiofile引用设置的ASBD错误。我想先保存一个wav文件。我不确定我是否在下面的ASBD中正确地描述了这一点

其次,我不确定在创建音频文件时为inChannelLayout属性传递什么值

最后,我非常不确定什么是asbd用于kExtAudioFileProperty_ClientDataFormat。 我一直在使用我的立体声流格式,但仔细看文档后发现这一定是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 :");


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

}
使用立体声流格式设置remoteio回调

- (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 :");


}
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

Im附加2个音频样本。第一个是我循环并试图复制的原始音频。第二个是该循环的录制音频。希望它能给一些人一个关于哪里出了问题的线索


经过几天的眼泪和头发拉扯,我有了一个解决办法

在我的代码和其他示例中,我看到在remoteio单元的回调中调用了extaudiofilewriteasync,如下所示

**远程单元回调**

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;

}
在这个回调中,我从另一个应用EQ和混合音频的音频单元中提取音频数据

我从remoteio回调中删除了extaudiofilewriteasync调用,该调用被remoteio拉入并成功写入文件

*Equints回调函数*


为了充分理解我的解决方案的工作原理,有人能向我解释一下为什么从remoteio的iodata bufferlist向文件写入数据会导致音频失真,但再往下一步写入数据会产生完美的音频吗?

愚蠢的问题,但您是否检查了
sizeof(AudioUnitSampleType)是否正确
返回与分配给
mBytesPerPacket
的大小相同的大小?我仔细检查以确保。他们都是同样大小的。@hv你用录音做的,你能解释一下你的解决方案吗。我也面临同样的问题。在回调中写入文件的音频数据失真。我们应该在哪个回调中写入它?这取决于你的曲线图。我从经验中发现,尝试从remoteio(节点0)的输出回调将音频写入磁盘通常不起作用。而是将其放在其他节点的输入回调中。如果你用源代码写一个更完整的问题,我可能会帮你更多。