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

Posted

技术标签:

【中文标题】Swift 中的 AudioUnitRender 和 ExtAudioFileWrite 错误 -50:尝试将 MIDI 转换为音频文件【英文标题】:AudioUnitRender and ExtAudioFileWrite error -50 in Swift: Trying to convert MIDI to Audio File 【发布时间】:2016-09-03 18:21:09 【问题描述】:

我正在尝试将 MIDI 文件转换为 Swift 中的音频文件 (.m4a)。

现在我使用MIKMIDI 作为排序和播放 MIDI 文件的工具,但是它不包括将播放保存到文件中的功能。 MIKMID 的创建者概述了执行此操作的过程here。为了捕获输出并将其保存到音频文件,我跟随this example 尝试用 Swift 中的 GeneralIO 节点替换 MIKMIDI Graph 的 RemoteIO 节点。当我尝试使用 AudioUnitRender 和 ExtAudioFileWrite 将输出保存到文件时,它们都返回错误 -50 (kAudio_ParamError)。

    var channels = 2
    var buffFrames = 512
    var bufferList = AudioBufferList.allocate(maximumBuffers: 1)

         for i in 0...bufferList.count-1

               var buffer = AudioBuffer()
               buffer.mNumberChannels = 2
               buffer.mDataByteSize = UInt32(buffFrames*sizeofValue(AudioUnitSampleType))
               buffer.mData = calloc(buffFrames, sizeofValue(AudioUnitSampleType))

               bufferList[i] = buffer

               result = AudioUnitRender(generalIOAudioUnit, &flags, &inTimeStamp, busNum, UInt32(buffFrames), bufferList.unsafeMutablePointer)
               inTimeStamp.mSampleTime += 1

               result = ExtAudioFileWrite(extAudioFile, UInt32(buffFrames), bufferList.unsafeMutablePointer)

         

是什么导致了错误 -50,如何解决它以将 MIDI(离线)渲染为 .m4a 文件?

更新:我已通过将 mNumberChannels 和通道更改为 = 1 解决了 ExtAudioFileWrite 错误 -50。现在我得到了一个带有噪音的一秒音频文件。 AudioUnitRender 仍然返回错误 -50。

【问题讨论】:

您有示例项目吗? 当然,我刚刚创建了一个:link。告诉我结果如何! 酷!但是soundfont文件丢失了。和 podfile 一样。 哎呀!好的,我现在都添加了它们。只需运行 pod install 将 cocoapods 添加到项目中,它应该可以工作了! 【参考方案1】:

您的代码有几个问题:

    你的AudioBufferList不符合客户端格式,试试

    let bufferList = AudioBufferList.allocate(maximumBuffers: Int(clientFormat.mChannelsPerFrame)) 
    

    您从 AUGraph 替换了错误的节点,并将剩余节点连接到自身,从而导致 AudioUnitRender 上的无限循环。

但主要问题是您没有实施author suggested 的解决方案。您希望可以使用示例时间戳调用AudioUnitRender,比实时更快,但作者说不,您必须手动将采样时间转换为主机时间,并实现midi 播放器的更好部分。

所以你可以这样做(听起来很难),或者file a feature request,或者通过使用AudioUnitAddRenderNotify向图形的远程IO音频单元添加渲染通知并编写kAudioUnitRenderAction_PostRender 阶段的样本。

【讨论】:

哇,感谢您的大力支持。我会在这上面花费数周时间!我只是尝试调整 AudioBufferList 频道,我收到了一个 kAudioUnitErr_Uninitialized 错误。为了解决这个问题,我尝试了 AudioUnitInitialize(),但是这让我回到了同样的 -50 错误。在我的完整项目中,我需要渲染长的、以编程方式创建的 midi 序列,并且实时执行的时间过长。现在,我将向 MIKMIDI 提交功能请求。如果我要创建一个播放器,this 会是一个好的起点吗? 对于任何感兴趣的人,我在这里添加了一个功能请求:github.com/mixedinkey-opensource/MIKMIDI/issues/164 正如@bamboostickk 链接的问题中所述,我已向 MIKMIDI 添加了一个示例项目,该项目演示了如何执行 OP 要求执行的操作。请参阅 MIKMIDI 中的 Examples/macOS/MIDI To Audio

以上是关于Swift 中的 AudioUnitRender 和 ExtAudioFileWrite 错误 -50:尝试将 MIDI 转换为音频文件的主要内容,如果未能解决你的问题,请参考以下文章

来自AudioUnitRender swift的paramErr -50

AudioUnit Render 回调中的 Objective-C/Swift 用法

AudioUnitRender 是啥意思?

AudioUnitRender 出现错误 kAudioUnitErr_CannotDoInCurrentContext (-10863)

AudioUnitRender 错误 -50 带有奇数长度的缓冲区

AudioUnit inputCallback 与 AudioUnitRender -> audioBufferList.mBuffers[0].mDataByteSize 之间不匹配!= in