构建一个简单的均衡器

10

我想使用AVAudioEngine做一个5段音频均衡器(60Hz、230Hz、910Hz、4kHz、14kHz),并且希望用户可以通过垂直滑块输入每个频段的增益,然后相应地调整正在播放的音频。我尝试使用AVAudioUnitEQ来实现,但是在播放音频时听不到任何差异。我尝试硬编码指定每个频率的增益值,但仍无效。以下是我的代码:

var audioEngine: AVAudioEngine = AVAudioEngine()
var equalizer: AVAudioUnitEQ!
var audioPlayerNode: AVAudioPlayerNode = AVAudioPlayerNode()
var audioFile: AVAudioFile!

// in viewDidLoad():
equalizer = AVAudioUnitEQ(numberOfBands: 5)
audioEngine.attach(audioPlayerNode)
audioEngine.attach(equalizer)
let bands = equalizer.bands
let freqs = [60, 230, 910, 4000, 14000]
audioEngine.connect(audioPlayerNode, to: equalizer, format: nil)
audioEngine.connect(equalizer, to: audioEngine.outputNode, format: nil)
for i in 0...(bands.count - 1) {
    bands[i].frequency = Float(freqs[i])
}

bands[0].gain = -10.0
bands[0].filterType = .lowShelf
bands[1].gain = -10.0
bands[1].filterType = .lowShelf
bands[2].gain = -10.0
bands[2].filterType = .lowShelf
bands[3].gain = 10.0
bands[3].filterType = .highShelf
bands[4].gain = 10.0
bands[4].filterType = .highShelf

do {
    if let filepath = Bundle.main.path(forResource: "song", ofType: "mp3") {
        let filepathURL = NSURL.fileURL(withPath: filepath)
        audioFile = try AVAudioFile(forReading: filepathURL)
        audioEngine.prepare()
        try audioEngine.start()
        audioPlayerNode.scheduleFile(audioFile, at: nil, completionHandler: nil)
        audioPlayerNode.play()
    }
} catch _ {}

由于低频增益为-10,高频增益为10,因此在播放任何媒体时应该会有非常明显的差异。然而,当媒体开始播放时,听起来与没有连接均衡器的情况下播放的声音相同。

我不确定为什么会这样,但我尝试了几种不同的调试方法。我认为可能是函数的顺序问题,所以我尝试将audioEngine.connect调用放在调整所有波段之后,但结果没有任何变化。

我尝试使用AVAudioUnitTimePitch运行相同的代码,它可以完美地工作,因此我对为什么AVAudioUnitEQ无法正常工作感到困惑。

我不想在这个项目中使用任何第三方库或cocoa pods,我想仅使用AVFoundation完成它。

非常感谢您的帮助!

提前致谢。


我对AVKit不熟悉,请问如何将均衡器的输出显示在屏幕上? - user9137841
1个回答

14

AVAudioUnitEQFilterParameters AVAudioUnitEQFilterParameters Documentation 浏览了文档后,我发现除了bypass参数以外的所有参数都被我弄乱了,而改变这个标志似乎修复了一切问题!

因此,我认为这里的主要问题是每个 AVAudioUnitEQ 波段不能被提供的系统值绕过,而应使用程序员设置的值。

所以,我进行了更改:

for i in 0...(bands.count - 1) {
    bands[i].frequency = Float(freqs[i])
}

for i in 0...(bands.count - 1) {
    bands[i].frequency  = Float(freqs[i])
    bands[i].bypass     = false
    bands[i].filtertype = .parametric
}

一切都开始工作了。此外,要制作一个有效的均衡器,允许用户修改各个频率,每个频段的filtertype应设置为.parametric

我仍然不确定应该将带宽设置为多少,但我可以在网上查找或尝试调整,直到声音与其他均衡器应用相匹配。


这非常有帮助……但我也注意到您正在重新分配过滤器类型——首先是参数型,然后是低/高架。 - Nerdy Bunz
谢谢!我正在尝试在我的macOS应用程序中实现一个粗略的ReplayGain方法。这让我更接近目标,因为它向我展示了如何访问该类的全局增益属性。现在我只需要弄清楚如何确定音频文件的最大增益,然后再应用全局增益来增加或减少增益。 - SouthernYankee65

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接