如何用AVAudioBuffer将样本数组写入24位音频文件?

问题描述:

我在用AVAudioEngine快速写入24位wav文件时遇到了麻烦。 对于我的用法,我的输入是一个Float数组。 我有输入文件的音频格式(用AVAudioFile检索)。如何用AVAudioBuffer将样本数组写入24位音频文件?

所以,我需要将我的输入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

是音乐:[浮动]立体声/交错还是单声道? – dave234

+0

它可以是立体声或单声道,当立体声被交错时。 – NicoC

在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) 

} 
+0

谢谢,我会接受你的回答,因为看起来对我来说没有简单的解决方案......我会尽力处理它! – NicoC