AvaudioEngine - 以特定采样率录制语音 AvaudioEngine for Analysis

Posted

技术标签:

【中文标题】AvaudioEngine - 以特定采样率录制语音 AvaudioEngine for Analysis【英文标题】:AvaudioEngine - Record voice at specific sample rate AvaudioEngine for Analysis 【发布时间】:2022-01-23 11:03:30 【问题描述】:

我们正在开发一个从外部麦克风录制声音的项目。出于分析目的,我们需要大约 5k Hz 的采样率。

我们正在使用 AvAudioEngine 来录制声音。 我们知道 Apple 设备希望能够以特定速率进行录制,因此我们使用 AVAudioConverter 来降低采样率。

但正如您所知,它类似于压缩,因此我们降低采样率越低,文件大小和文件持续时间的影响相同。目前正在发生的事情(如果我错了,请纠正我)。

问题

**问题是降低采样率以缩短文件长度及其对计算和分析的影响。 例如,1 小时的录音被降级为 45 分钟。所以假设如果我们以 5 分钟的时间间隔进行分析,就会出错

最好的解决方案是什么?**

查询

我们已经在互联网上进行了搜索,但无法弄清楚 installTap 上的缓冲区大小有何影响?在当前代码中,我们已将其设置为 2688。

谁能澄清一下?

代码

let bus = 0
let inputNode = engine.inputNode

let equalizer = AVAudioUnitEQ(numberOfBands: 2)

equalizer.bands[0].filterType = .lowPass
equalizer.bands[0].frequency = 3000
equalizer.bands[0].bypass = false

equalizer.bands[1].filterType = .highPass
equalizer.bands[1].frequency = 1000
equalizer.bands[1].bypass = false
engine.attach(equalizer) //Attach equalizer

// Connect nodes
engine.connect(inputNode, to: equalizer, format: inputNode.inputFormat(forBus: 0))
engine.connect(equalizer, to: engine.mainMixerNode, format: inputNode.inputFormat(forBus: 0))

// call before creating converter because this changes the mainMixer's output format
engine.prepare()

let outputFormat = AVAudioFormat(commonFormat: .pcmFormatInt16,
                                 sampleRate: 5000,
                                 channels: 1,
                                 interleaved: false)!

// Downsampling converter
guard let converter: AVAudioConverter = AVAudioConverter(from: engine.mainMixerNode.outputFormat(forBus: 0), to: outputFormat) else 
    print("Can't convert in to this format")
    return


engine.mainMixerNode.installTap(onBus: bus, bufferSize: 2688, format: nil)  (buffer, time) in
    var newBufferAvailable = true
    
    let inputCallback: AVAudioConverterInputBlock =  inNumPackets, outStatus in
        if newBufferAvailable 
            outStatus.pointee = .haveData
            newBufferAvailable = false
            return buffer
         else 
            outStatus.pointee = .noDataNow
            return nil
        
    
    
    
    let convertedBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(outputFormat.sampleRate) * buffer.frameLength / AVAudioFrameCount(buffer.format.sampleRate))!
    
    var error: NSError?
    let status = converter.convert(to: convertedBuffer, error: &error, withInputFrom: inputCallback)
    assert(status != .error)
    
    
    if status == .haveData 
        // Process with converted buffer
    


do 
    try engine.start()
 catch 
    print("Can't start the engine: \(error)")

期待结果

我们可以压缩缓冲区,但我们希望在输出文件中具有相同的记录持续时间。如果我们记录 10 分钟,输出文件应该有 10 分钟的数据。

【问题讨论】:

如果您在获得解决方案后分享您的解决方案,我们将不胜感激 我不明白你的意思:“我们降低采样率越低,文件大小和文件持续时间影响相同。”也不明白“降低文件长度的采样率”......我想我理解“1小时的录音被降级为45分钟”。那么您对较低的采样率导致较小的文件感到惊讶吗?为什么会有问题?当你没有对转换后的缓冲区做任何事情时,你怎么知道文件大小?它只是说“//使用转换后的缓冲区进行处理” @NerdyBunz 我预计文件大小会减少,但我很惊讶为什么音频文件的持续时间会减少。所以假设如果我们压缩任何音频,它会减少它的大小而不是文件的持续时间(总时间)。但就我而言,输出文件中的总录制时间与实际录制时间不同 【参考方案1】:

数字化音频没有固有的持续时间,因为它可以以任何采样率播放。

为了使生成的文件的持续时间达到您的预期,采样率必须达到您在每个阶段的预期:记录、处理和播放。

我怀疑正在发生两种可能的事情之一:

A) 您在 installtap 中收到的缓冲区的采样率不是您想象的那样...并且您正在转换 错误的格式。

B) 您正在以不同于您假设的采样率播放音频。 (你怎么知道你的播放器是以 5000hz 播放的)?

为了检查这一点,您必须将过程分解为更小的部分并检查每个阶段的采样率。

【讨论】:

以上是关于AvaudioEngine - 以特定采样率录制语音 AvaudioEngine for Analysis的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 中以不同的采样率同时录制和播放

以高于 16kHz 的采样率从 AirPod Pro 录制音频

如何使用 AVFoundation 以正确的音高播放不同采样率的音频文件?

如何将 8 kHz 音频采样率提高到 16 kHz STM32

AVAudioEngine 录制在 AVAudioPlayerNode 中播放的声音

将音频缓冲区从 44100 重新采样到 16000