ios - 如何在 Avfoundation 中正确更改采样率

标签 ios swift audio avfoundation sample-rate

我已经完成了这个简单的程序。它所做的只是同时记录和回放缓冲区。如果采样率为 44100 赫兹,一切正常,但如果我将采样率更改为 16000 或 8000,它根本不会产生任何声音,或者可能是一些听不见的白噪声。为什么会发生这种情况?

How can I record with different sample rate?

我试过以下代码:

import UIKit
import AVFoundation

class ViewController: UIViewController  {

var engine = AVAudioEngine()
let player = AVAudioPlayerNode()
let audioSession = AVAudioSession.sharedInstance()
let newSrc:UnsafeMutablePointer<Float>! = nil
override func viewDidLoad() {
super.viewDidLoad()



let audioSession = AVAudioSession.sharedInstance()
print(audioSession.sampleRate) // here it prints 44100 hz. because it still using the internal mic.
do {

    try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .allowBluetooth)
    try audioSession.setMode(AVAudioSessionModeDefault)
    try audioSession.setActive(true)

} catch {
}
print(audioSession.sampleRate) // here it will print 16000 hz if my bluetooth earbuds is connected, if not it will be 44100 hz.

let input = engine.inputNode
let bus = 0
let mixer = AVAudioMixerNode() // creating mixer as it is needed to set audio format

engine.attach(mixer)
engine.attach(player)
engine.connect(input, to: mixer, format: input.outputFormat(forBus: 0))

let inputFormat = input.inputFormat(forBus: bus)

engine.connect(player, to: engine.mainMixerNode, format: input.inputFormat(forBus: 0))

let fmt = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100.0, channels: 1, interleaved: false)

mixer.installTap(onBus: bus, bufferSize: 1024, format: fmt) { (buffer, time) -> Void in

    print(buffer.format)
    print(buffer.floatChannelData)
    print(buffer.format.streamDescription.pointee.mBytesPerFrame)
    self.player.scheduleBuffer(buffer)
    if self.player.isPlaying {
        print("true")
    }
}


engine.prepare()
do{
    try! engine.start()
    player.play()
} catch {
    print(error)
}
}

}

最佳答案

作为discussed hereAVAudioEngine 混音器节点和水龙头都不会为您进行速率转换。事实上,在你的情况下,而不是抛出或记录错误,混合龙头静静地(明白了吗?)让你沉默。

由于您不能使用 AVAudioMixerNode 进行速率转换,您可以将其替换为方便的 AVAudioConverter,确保设置正确的 输出格式>AVAudioPlayerNode 因为

When playing buffers, there is an implicit assumption that the buffers are at the same sample rate as the node's output format.

如果您不这样做,您可能会听到间隙和/或音调偏移的音频。

像这样

let input = engine.inputNode
let bus = 0
let inputFormat = input.inputFormat(forBus: bus)

engine.attach(player)

let fmt = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 8000, channels: 1, interleaved: false)!
engine.connect(player, to: engine.mainMixerNode, format: fmt)

let converter = AVAudioConverter(from: inputFormat, to: fmt)!

input.installTap(onBus: bus, bufferSize: 1024, format: inputFormat) { (buffer, time) -> Void in
    let inputCallback: AVAudioConverterInputBlock = { inNumPackets, outStatus in
        outStatus.pointee = AVAudioConverterInputStatus.haveData
        return buffer
    }

    let convertedBuffer = AVAudioPCMBuffer(pcmFormat: fmt, frameCapacity: AVAudioFrameCount(fmt.sampleRate) * buffer.frameLength / AVAudioFrameCount(buffer.format.sampleRate))!

    var error: NSError? = nil
    let status = converter.convert(to: convertedBuffer, error: &error, withInputFrom: inputCallback)
    assert(status != .error)

    print(convertedBuffer.format)
    print(convertedBuffer.floatChannelData)
    print(convertedBuffer.format.streamDescription.pointee.mBytesPerFrame)
    self.player.scheduleBuffer(convertedBuffer)
}

关于ios - 如何在 Avfoundation 中正确更改采样率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50382746/

相关文章:

swift - 循环一系列 withAnimation 函数

javascript - 每当表格行插入html表格时,都会收到声音通知

ios - NSNotificationCenter AppDelegate post通知问题

ios - 创建一个能够检查按下的按钮的标题的函数

html - 如何在无响应的移动网站上设置视口(viewport)?

ios - UITableViewCell 按钮在屏幕下方加载时未注册单击

ios - 参数类型 'String' 不符合预期类型 'Sequence'

ios - 我们应该使用 ios 模拟器 7 在 xcode 5 中运行 iPhone 应用程序吗?

C++ - 播放正弦波产生的音调

c++ - SDL_Mixer 崩溃一次;现在所有使用 SDL_Mixer 的程序都会在初始化时崩溃