我正在尝试将.m4a格式的给定音频文件转换为.aiff格式,使用
this post的答案.我已将代码转换为Swift 3.0.
func convertAudio(_ url: URL,outputURL: URL) { var error : OSStatus = noErr var destinationFile : ExtAudioFileRef? = nil var sourceFile : ExtAudioFileRef? = nil var srcFormat : AudioStreamBasicDescription = AudioStreamBasicDescription() var dstFormat : AudioStreamBasicDescription = AudioStreamBasicDescription() var audioConverter : AudioConverterRef? = nil ExtAudioFileOpenURL(url as CFURL,&sourceFile) var thePropertySize: UInt32 = UInt32(MemoryLayout.stride(ofValue: srcFormat)) ExtAudioFileGetProperty(sourceFile!,kExtAudioFileProperty_FileDataFormat,&thePropertySize,&srcFormat) dstFormat.mSampleRate = 44100 //Set sample rate dstFormat.mFormatID = kAudioFormatLinearPCM dstFormat.mChannelsPerFrame = 1 dstFormat.mBitsPerChannel = 16 dstFormat.mBytesPerPacket = 2 * dstFormat.mChannelsPerFrame dstFormat.mBytesPerFrame = 2 * dstFormat.mChannelsPerFrame dstFormat.mFramesPerPacket = 1 dstFormat.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger //Create destination file ExtAudioFileCreateWithURL(outputURL as CFURL,kAudioFileAIFFType,&dstFormat,nil,AudioFileFlags.eraseFile.rawValue,&destinationFile) ExtAudioFileSetProperty(sourceFile!,kExtAudioFileProperty_ClientDataFormat,thePropertySize,&dstFormat) ExtAudioFileSetProperty(destinationFile!,&dstFormat) var size : UInt32 = UInt32(MemoryLayout.stride(ofValue: audioConverter)) ExtAudioFileGetProperty(destinationFile!,kExtAudioFileProperty_AudioConverter,&size,&audioConverter) var canResume : UInt32 = 0 size = UInt32(MemoryLayout.stride(ofValue: canResume)) error = AudioConverterGetProperty(audioConverter!,kAudioConverterPropertyCanResumeFromInterruption,&canResume) let bufferByteSize : UInt32 = 32768 var srcBuffer = [UInt8](repeating: 0,count: 32768) var sourceFrameOffset : ULONG = 0 print("Converting audio file") while(true){ var fillBufList = AudioBufferList( mNumberBuffers: 1,mBuffers: AudioBuffer( mNumberChannels: 2,mDataByteSize: UInt32(srcBuffer.count),mData: &srcBuffer ) ) var numFrames : UInt32 = 0 if(dstFormat.mBytesPerFrame > 0){ numFrames = bufferByteSize / dstFormat.mBytesPerFrame } ExtAudioFileRead(sourceFile!,&numFrames,&fillBufList) if(numFrames == 0){ error = noErr; break; } sourceFrameOffset += numFrames error = ExtAudioFileWrite(destinationFile!,numFrames,&fillBufList) } ExtAudioFileDispose(destinationFile!) ExtAudioFileDispose(sourceFile!) }
问题是audioConverter似乎在这一行是零
error = AudioConverterGetProperty(audioConverter!,&canResume)
而我似乎无法弄清楚为什么.我错过了什么?
跳过AudioConverterGetProperty
你实际上没有使用它.
以下代码片段将音频文件转换为AIFF:它以一种支持的格式读取sourceFile,创建AIFF编码器,并使用bufferByteSize缓冲区循环它.错误处理得当.
完整代码,swift 3:
func convertAudio(_ url: URL,outputURL: URL) { var error : OSStatus = noErr var destinationFile : ExtAudioFileRef? = nil var sourceFile : ExtAudioFileRef? = nil var srcFormat : AudioStreamBasicDescription = AudioStreamBasicDescription() var dstFormat : AudioStreamBasicDescription = AudioStreamBasicDescription() ExtAudioFileOpenURL(url as CFURL,&srcFormat) dstFormat.mSampleRate = 44100 //Set sample rate dstFormat.mFormatID = kAudioFormatLinearPCM dstFormat.mChannelsPerFrame = 1 dstFormat.mBitsPerChannel = 16 dstFormat.mBytesPerPacket = 2 * dstFormat.mChannelsPerFrame dstFormat.mBytesPerFrame = 2 * dstFormat.mChannelsPerFrame dstFormat.mFramesPerPacket = 1 dstFormat.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger // Create destination file error = ExtAudioFileCreateWithURL( outputURL as CFURL,&destinationFile) reportError(error: error) error = ExtAudioFileSetProperty(sourceFile!,&dstFormat) reportError(error: error) error = ExtAudioFileSetProperty(destinationFile!,&dstFormat) reportError(error: error) let bufferByteSize : UInt32 = 32768 var srcBuffer = [UInt8](repeating: 0,count: 32768) var sourceFrameOffset : ULONG = 0 while(true){ var fillBufList = AudioBufferList( mNumberBuffers: 1,mData: &srcBuffer ) ) var numFrames : UInt32 = 0 if(dstFormat.mBytesPerFrame > 0){ numFrames = bufferByteSize / dstFormat.mBytesPerFrame } error = ExtAudioFileRead(sourceFile!,&fillBufList) reportError(error: error) if(numFrames == 0){ error = noErr; break; } sourceFrameOffset += numFrames error = ExtAudioFileWrite(destinationFile!,&fillBufList) reportError(error: error) } error = ExtAudioFileDispose(destinationFile!) reportError(error: error) error = ExtAudioFileDispose(sourceFile!) reportError(error: error) }
支持方式:
func reportError(error: OSStatus) { // Handle error }
调用:
let sourceUrl = URL(string: Bundle.main.path(forResource: "sample",ofType: "mp3")!) let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true) let documentsDirectory = URL(string: paths.first!) let destUrl = documentsDirectory?.appendingPathComponent("converted.aiff") if let sourceUrl = sourceUrl,let destUrl = destUrl { print("from \(sourceUrl.absoluteString) to \(destUrl.absoluteString)") convertAudio(sourceUrl,outputURL: destUrl) }