使用 ExtAudioFileWrite ios 将流式 mp3 数据包的缓冲区写入 wav 文件

Posted

技术标签:

【中文标题】使用 ExtAudioFileWrite ios 将流式 mp3 数据包的缓冲区写入 wav 文件【英文标题】:Writing buffers of Streamed mp3 packets to wav file using ExtAudioFileWrite ios 【发布时间】:2017-05-07 10:31:24 【问题描述】:

我正在开发在线广播应用程序,我设法使用 AudioQueueServices 播放来自 Icecast 服务器的流式 mp3 数据包,我正在努力实现录制功能。

由于流媒体是 mp3 格式,我无法使用 AudioFileWritePackets 将音频数据包直接写入文件。

为了利用扩展音频的自动转换,我使用 ExtAudioWriteFile 写入 wav 文件。我已经使用 FileStreamOpen 回调函数 AudioFileStream_PropertyListenerProc 和我手动填充的目标格式设置了传入数据包的 AudiostreamBasicDescription。代码成功创建文件并将数据包写入其中,但在播放时我听到的是白噪声; 这是我的代码

// when the recording button is pressed this function creates the file and setup the asbd
    -(void)startRecording
        recording = true;
        OSStatus status;
        NSURL *baseUrl=[self applicationDocumentsDirectory];//returns the document direcotry of the app
        NSURL *audioUrl = [NSURL URLWithString:@"Recorded.wav" relativeToURL:baseUrl];
       //asbd setup for the destination file/wav file
        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;
        //creating the file    
        status = ExtAudioFileCreateWithURL(CFBridgingRetain(audioUrl), kAudioFileWAVEType, &(dstFormat), NULL, kAudioFileFlags_EraseFile, &recordingFilRef);

        // tell the EXtAudio File ApI  what format we will be sending samples
        //recordasbd is the asbd of incoming packets populated in  AudioFileStream_PropertyListenerProc
        status =   ExtAudioFileSetProperty(recordingFilRef, kExtAudioFileProperty_ClientDataFormat, sizeof(recordasbd), &recordasbd);  
    
    // a handler called by packetproc call back function in AudiofileStreamOpen 
    - (void)handlePacketsProc:(const void *)inInputData numberBytes:(UInt32)inNumberBytes numberPackets:(UInt32)inNumberPackets packetDescriptions:(AudioStreamPacketDescription *)inPacketDescriptions 
    if(recording)
         // wrap the destination buffer in an audiobuffer list
         convertedData.mNumberBuffers= 1;
         convertedData.mBuffers[0].mNumberChannels = recordasbd.mChannelsPerFrame;
         convertedData.mBuffers[0].mDataByteSize = inNumberBytes;
         convertedData.mBuffers[0].mData = inInputData;


       ExtAudioFileWrite(recordingFilRef,recordasbd.mFramesPerPacket * inNumberPackets, &convertedData);
         

    

我的问题是:

我的方法对吗?我可以用这种方式将 mp3 数据包写入 wav 文件吗?如果是这样,我错过了什么??

如果我的方法是错误的,请告诉我你认为正确的任何其他方式。朝着正确的方向轻推对我来说已经足够了

我非常感谢任何帮助,我已经阅读了我可以得到的关于这个主题的每一个 SO 问题,我还仔细查看了 apples Convertfile 示例,但我无法弄清楚我错过了什么 在此先感谢您的帮助

【问题讨论】:

【参考方案1】:

为什么不将原始 mp3 数据包直接写入文件?完全不使用ExtAudioFile

它们将形成一个有效的 mp3 文件,并且比等效的 wav 文件小得多。

【讨论】:

我想写入 mp3,但由于版权问题,苹果不支持 mp3 .AudiofileCreateWithurl 返回状态 'fmt?'(kAudioConverterErr_FormatNotSupported) 这就是我尝试将其转换为 wav 的原因。跨度> 我的意思是使用fwritewriteNSFileHandle 的方法将原始数据包写入文件。 Apple 不支持编码 mp3 数据,原因他们没有指定,但您不需要编码器,因为您已经拥有 mp3 数据。他们确实支持解码。

以上是关于使用 ExtAudioFileWrite ios 将流式 mp3 数据包的缓冲区写入 wav 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 ExtAudioFileWrite 在文件末尾写入

ExtAudioFileWrite 创建静音 m4a

Swift 中的 AudioUnitRender 和 ExtAudioFileWrite 错误 -50:尝试将 MIDI 转换为音频文件

从 AudioUnit 格式转换为 ExtAudioFileWrite

使用 AudioToolBox 将 Wave 文件保存到 NSFileWrapper

在 iPhone 上录制播放和麦克风