我正在尝试在Swift中将MIDI文件转换为音频文件(.m4a)。
目前,我正在使用MIKMIDI作为排序和播放MIDI文件的工具,但是它不包含将播放内容保存到文件中的功能。MIKMID的创建者在此处概述了执行此操作的过程。为了捕获输出并将其保存到音频文件中,我遵循了此示例,尝试将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和channel更改为= 1,我解决了ExtAudioFileWrite错误-50。现在我得到了一秒钟带有噪音的音频文件。AudioUnitRender仍然返回错误-50。
您的代码有两个问题:
您AudioBufferList
不同意客户端格式,请尝试
let bufferList = AudioBufferList.allocate(maximumBuffers: Int(clientFormat.mChannelsPerFrame))
您要从中替换错误的节点AUGraph
,并将其余节点连接到自身,从而导致上的无限循环AudioUnitRender
。
但是主要的问题是您没有实现作者建议的解决方案。您希望可以AudioUnitRender
使用比实时时间更快的示例时间戳进行调用,但是作者说不,您必须手动将采样时间转换为主机时间,并且如果需要的话,可以实现Midi播放器的更好部分。
因此,您可以执行此操作(听起来很困难),或者提出功能请求,或者在听音乐时通过在图表的远程IO音频单元中添加渲染通知AudioUnitAddRenderNotify
并在此kAudioUnitRenderAction_PostRender
阶段编写样本来实时记录到文件中。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句