代码之家  ›  专栏  ›  技术社区  ›  Mohammed Atif

使用原始PCM生成视频或音频

  •  2
  • Mohammed Atif  · 技术社区  · 6 年前

    生成的过程是什么。mov或。m4a文件使用Int16阵列作为音频的sterio通道?

    我可以轻松生成原始PCM数据,如下所示 [Int16] 来自。mov文件,并将其存储在两个文件中 leftChannel.pcm rightChannel.pcm 并执行一些操作以供以后使用。但我无法从这些文件中重新生成视频。

    任何过程,即使用原始PCM直接生成视频或使用PCM生成m4a的中间步骤都可以工作。

    我想出了如何将PCM阵列转换为音频文件。但它不会播放。

    private func convertToM4a(leftChannel leftPath : URL, rightChannel rigthPath : URL, converterCallback : ConverterCallback){
    
        let m4aUrl = FileManagerUtil.getTempFileName(parentFolder: FrameExtractor.PCM_ENCODE_FOLDER, fileNameWithExtension: "encodedAudio.m4a")
        if FileManager.default.fileExists(atPath: m4aUrl.path) {
            try! FileManager.default.removeItem(atPath: m4aUrl.path)
        }
        do{
            let leftBuffer = try NSArray(contentsOf: leftPath, error: ()) as! [Int16]
            let rightBuffer = try NSArray(contentsOf: rigthPath, error: ()) as! [Int16]
    
            let sampleRate = 44100
            let channels = 2
            let frameCapacity = (leftBuffer.count + rightBuffer.count)/2
    
            let outputSettings = [
                AVFormatIDKey : NSInteger(kAudioFormatMPEG4AAC),
                AVSampleRateKey : NSInteger(sampleRate),
                AVNumberOfChannelsKey : NSInteger(channels),
                AVAudioFileTypeKey : NSInteger(kAudioFileAAC_ADTSType),
                AVLinearPCMIsBigEndianKey : true,
                ] as [String : Any]
    
            let audioFile = try AVAudioFile(forWriting: m4aUrl, settings: outputSettings, commonFormat: .pcmFormatInt16, interleaved: false)
    
            let format = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: Double(sampleRate), channels: AVAudioChannelCount(channels), interleaved: false)!
    
            let pcmBuffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: AVAudioFrameCount(frameCapacity))!
            pcmBuffer.frameLength = pcmBuffer.frameCapacity
    
            for i in 0..<leftBuffer.count {
                pcmBuffer.int16ChannelData![0][i] = leftBuffer[i]
            }
    
            for i in 0..<rightBuffer.count {
                pcmBuffer.int16ChannelData![1][i] = rightBuffer[i]
            }
    
            try! audioFile.write(from: pcmBuffer)
    
            converterCallback.m4aEncoded(to: m4aUrl)
    
        } catch {
            print(error.localizedDescription)
        }
    }
    

    将其另存为。m4a带 AVAudioFileTypeKey m4a type 提供的文件格式错误。

    将其另存为。具有上述设置的aac播放文件,但声音中断。只是原始音频的嗡嗡声和一些缓慢的mo效果,最初我认为这与采样率的输入和输出有关,但事实并非如此。

    我假设输出字典中有问题。任何帮助都将不胜感激。

    1 回复  |  直到 6 年前
        1
  •  0
  •   Stephan Schlecht    6 年前

    至少创建AAC文件时,您显示的代码是有效的。

    我用有效的Int16音频数据写出了两个NSarray,并用您的代码得到了一个有效的结果,例如,在QuickTime Player中播放时(使用后缀.aac),声音与输入相同。

    encoded audio

    您如何创建输入?

    例如,如果您使用AVAudioFormat读取音频数据,就会出现嗡嗡声(伴有大量噪音),例如:。 .pcmFormatInt16 格式,但实际读取的数据 .pcmFormatFloat32 格式(最常见的默认格式)。不幸的是,如果您尝试这样做,则没有运行时警告。

    如果是这样的话,试着使用 .pcmFormatFloat32 .如果你需要的话 Int16 您可以通过基本上将两个通道的[-1,1]映射到[-3276832767]来转换它。

    let fac = Float(1 << 15)
    for i in 0..<count {
        let val = min(max(inBuffer!.floatChannelData![ch][i] * fac, -fac), fac - 1)
        xxx[I] = Int16(val)
    }
    ...