Создайте простой эквалайзер

Я хотел бы сделать 5-полосный звуковой эквалайзер (60 Гц, 230 Гц, 910 Гц, 4 кГц, 14 кГц), используя AVAudioEngine, Я хотел бы получить усиление пользовательского ввода для каждой полосы через вертикальный ползунок и соответственно отрегулировать воспроизводимый звук. Я пытался с помощью 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,

Я не хочу использовать какие-либо сторонние библиотеки или какао-бобы для этого проекта, я хотел бы сделать это с помощью AVFoundation в одиночестве.

Любая помощь будет принята с благодарностью!

Заранее спасибо.

1 ответ

Решение

AVAudioUnitEQFilterParameters AVAudioUnitEQFilterParameters Документация Просматривая документацию, я заметил, что перепутал все параметры, кроме 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,

Я до сих пор не уверен в том, на что мне следует установить полосу пропускания, но, возможно, я могу проверить это онлайн или просто возиться с ней, пока звук не будет соответствовать другому приложению эквалайзера.

Другие вопросы по тегам