有没有人成功编写本机 XCode/Swift 代码来实现 ReplayGain 或类似功能,或者知道我在哪里可以找到一些示例代码/教程来实现此目的?
我正在尝试将我的 python 代码转换为 XCode 以用于本机 macOS 应用程序。 我正在 python 中使用 pydub 库,并通过 apply_gain 方法应用增益调整,将我的音频文件标准化为指定的 dBFS,但我已经搜索了很多关于如何在 XCode 中执行此操作的示例代码,我来了几乎两手空空。 我正在使用 Catalina 10.15.4 和 XCode 11.5。
我在here找到了下面的代码,我对其进行了修改以删除均衡器频段并添加全局增益选项。 然而,我现在需要弄清楚如何分析文件以确定峰值分贝/峰值增益并相应地调整全局增益,以确保每个 mp3 的音量几乎相同,而不必一直摆弄音量。
import AVFoundation
var audioEngine: AVAudioEngine = AVAudioEngine()
var equalizer: AVAudioUnitEQ!
var audioPlayerNode: AVAudioPlayerNode = AVAudioPlayerNode()
var audioFile: AVAudioFile!
// in viewDidLoad():
equalizer = AVAudioUnitEQ(numberOfBands: 0)
audioEngine.attach(audioPlayerNode)
audioEngine.attach(equalizer)
let bands = equalizer.bands
//let globalGain = equalizer.globalGain
let freqs = [60, 230, 910, 4000, 14000]
audioEngine.connect(audioPlayerNode, to: equalizer, format: nil)
audioEngine.connect(equalizer, to: audioEngine.outputNode, format: nil)
equalizer.globalGain = 12
var filePath = "some_music_file.mp3"
do {
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 {
print ("An error occured.")
}
经过数小时的研究和挖掘,我想我终于找到了在轨道之间“规范化”音频所需的解决方案。
其实很短。 我将 AVAudioPCMBuffer 发送到该方法,并使用 Accelerate API 进行数学计算,首先计算 RMS(功率),然后将其转换为分贝 (dB) 级别。
我设置了一个默认音量级别,然后从 dB 的绝对值中减去该音量级别,并将该值传递给 AVAudioEQ 的.globalGain 属性。
至少在我听来,这似乎实现了我想要从 Python 迁移过来的目标。 我已经用大量 MP3 对其进行了测试,这些 MP3 从一个曲目到另一个曲目的音频明显更大或更安静,而且似乎工作得很好。
如果您打算在非常大的音频文件上使用它,我建议将其放在它自己的线程中,这样它就不会阻塞。 对于我的应用程序来说,它似乎足够快。
如果你知道更好、更有效的方法,请在下面评论。
斯威夫特 5.3
import Accelerate
import AVFoundation
func getDecibles1(buffer: AVAudioPCMBuffer) -> Float {
// This method will compute the Real Mean Squared (RMS) value of an audio
// PCM buffer that will return the Decibile (dB) level of an audio signal.
// RMS will be calculated for all channels with a signal and averaged
// which then provides true dB of the audio for all channels.
let frameLength = UInt(buffer.frameLength)
let channels = Int(buffer.format.channelCount)
var channelsWithSignal = Float(channels)
var rms:Float = 0
var rmsSumOfChannels: Float = 0
for channel in 0..<channels {
guard let channelData = buffer.floatChannelData?[channel] else { return 0 }
vDSP_measqv(channelData, 1, &rms, frameLength)
if rms > 0 {
rmsSumOfChannels += rms
} else {
channelsWithSignal -= 1
}
}
// If you need the average power, uncomment the line below
//let avgPower = 20 * log10(rmsSumOfChannels/channelsWithSignal)
let dB = 10 * log10(rmsSumOfChannels/channelsWithSignal)
return dB
}
我建议使用 libebur128 来分析整个曲目。这将为您提供 2 个值:响度(即轨道增益)和峰值。
我正在我的 Swift macOS 音频应用程序中执行此操作 - https://github.com/kartik-venugopal/aural-player/tree/main/Source/Core/AudioGraph/EffectsUnits/ReplayGain
您可以在这里看到 ^ 我如何将 libebur128 集成到我的应用程序中(作为 xcframework)。对于分析代码,请参阅 AVFReplayGainScanner 和 FFmpegReplayGainScanner 类 - 两者都使用 libebur128。