我在swift中使用AVAudioEngine以24位写入wav文件时遇到问题。 对于我的用法,我的输入是一个Float数组。 我有输入文件的音频格式(用AVAudioFile检索)。
因此,我需要将输入的Float数组转换为可写入缓冲区的值。另外,我想找到合适的渠道来写我的数据。 我的代码使用16位和32位文件,但我不知道如何处理24位文件... 这是:
//Static func to write audiofile
fileprivate func writeAudioFile(to outputURL : URL,
withFormat format : AVAudioFormat,
fromSamples music : [Float] )
{
var outputFormatSettings = format.settings
guard let bufferFormat = AVAudioFormat(settings: outputFormatSettings) else{
return
}
var audioFile : AVAudioFile?
do{
audioFile = try AVAudioFile(forWriting: outputURL,
settings: outputFormatSettings,
commonFormat: format.commonFormat,
interleaved: true)
} catch let error as NSError {
print("error:", error.localizedDescription)
}
let frameCount = music.count / Int(format.channelCount)
let outputBuffer = AVAudioPCMBuffer(pcmFormat: bufferFormat,
frameCapacity: AVAudioFrameCount(frameCount))
//We write the data in the right channel
guard let bitDepth = (outputFormatSettings["AVLinearPCMBitDepthKey"] as? Int) else {
return
}
switch bitDepth {
case 16:
for i in 0..<music.count {
var floatValue = music[i]
if(floatValue > 1){
floatValue = 1
}
if(floatValue < -1){
floatValue = -1
}
let value = floatValue * Float(Int16.max)
outputBuffer?.int16ChannelData!.pointee[i] = Int16(value)
}
case 24:
//Here I am not sure of what I do ... Could'nt find the right channel !
for i in 0..<music.count {
outputBuffer?.floatChannelData!.pointee[i] = music[i]
}
case 32:
for i in 0..<music.count {
outputBuffer?.floatChannelData!.pointee[i] = music[i]
}
default:
return
}
outputBuffer?.frameLength = AVAudioFrameCount( frameCount )
do{
try audioFile?.write(from: outputBuffer!)
} catch let error as NSError {
print("error:", error.localizedDescription)
return
}
}
如果有人知道如何处理这个问题,请提前感谢!
答案 0 :(得分:4)
在C中表示一个24位的int并不好玩,所以在Swift中我确定它非常痛苦,而且无论如何都没有API支持它。您最好的选择是转换为更方便的格式进行处理。
AVAudioFile有两种格式和一个内部转换器,可以在它们之间进行转换。其fileFormat表示磁盘上文件的格式,而processingformat表示读取时lpcm数据的格式,以及写入时将接受的lpcm数据的格式。
典型的工作流程是选择标准的processingFormat,使用这种格式进行所有处理,并让AVAudioFile转换为文件格式,以便读取和写入磁盘。所有音频单元API都接受非交错格式,因此我倾向于对所有处理格式使用非交错格式。
这是一个复制音频文件前半部分的示例。它没有解决您现有的代码,但说明了一种更常见的方法:
func halfCopy(src: URL, dst: URL) throws {
let srcFile = try AVAudioFile(forReading: src) //This opens the file for reading using the standard format (deinterleaved floating point).
let dstFile = try AVAudioFile(forWriting: dst,
settings: srcFile.fileFormat.settings,
commonFormat: srcFile.processingFormat.commonFormat,
interleaved: srcFile.processingFormat.isInterleaved) //AVAudioFile(forReading: src) always returns a non-interleaved processing format, this will be false
let frameCount = AVAudioFrameCount(srcFile.length) / 2 // Copying first half of file
guard let buffer = AVAudioPCMBuffer(pcmFormat: srcFile.processingFormat,
frameCapacity: frameCount) else {
fatalError("Derp")
}
try srcFile.read(into: buffer, frameCount: frameCount)
try dstFile.write(from: buffer)
}