Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xcode 设置播放mp3文件的增益(也称为标准化)_Xcode_Avfoundation - Fatal编程技术网

Xcode 设置播放mp3文件的增益(也称为标准化)

Xcode 设置播放mp3文件的增益(也称为标准化),xcode,avfoundation,Xcode,Avfoundation,有没有人成功地编写了本机XCode/Swift代码来实现ReplayGain或类似的函数,或者知道我在哪里可以找到一些这样做的示例代码/教程 我正在尝试将python代码转换为本机macOS应用程序的XCode。我在python中使用pydub库,并通过apply_gain方法应用增益调整,以将音频文件规范化为指定的DBF,但我在XCode中搜索了大量示例代码,以了解如何做到这一点,我几乎空手而归。我正在使用Catalina 10.15.4和XCode 11.5 我找到了下面的代码,并对其进行了

有没有人成功地编写了本机XCode/Swift代码来实现ReplayGain或类似的函数,或者知道我在哪里可以找到一些这样做的示例代码/教程

我正在尝试将python代码转换为本机macOS应用程序的XCode。我在python中使用pydub库,并通过apply_gain方法应用增益调整,以将音频文件规范化为指定的DBF,但我在XCode中搜索了大量示例代码,以了解如何做到这一点,我几乎空手而归。我正在使用Catalina 10.15.4和XCode 11.5

我找到了下面的代码,并对其进行了修改,删除了均衡器频带,添加了globalGain选项。然而,我现在需要弄清楚如何分析文件以确定峰值db/峰值增益,并相应地调整globalGain,以确保每个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进行了测试,从一个曲目到另一个曲目的声音明显更大或更安静,而且它似乎工作得很好

如果你打算在非常大的音频文件上使用它,我建议把它放在自己的线程中,这样它就不会阻塞。对于我的应用程序来说,它似乎足够快了

如果你知道一种更好、更有效的方法,请在下面发表评论

Swift 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
}
导入加速
进口AVF基金会
func getDecibles1(缓冲区:AVAudioPCMBuffer)->Float{
//此方法将计算音频的实际均方值(RMS)
//PCM缓冲区,用于返回音频信号的分贝级。
//将计算具有信号的所有通道的RMS,并取其平均值
//然后为所有通道提供真实的音频分贝。
设frameLength=UInt(buffer.frameLength)
让channels=Int(buffer.format.channelCount)
var信道开关信号=浮动(信道)
变量rms:Float=0
变量rmsSumOfChannels:Float=0
对于0..0中的通道{
rms通道+=rms
}否则{
信道开关信号-=1
}
}
//如果需要平均功率,请取消注释下面的行
//设avgPower=20*log10(RMSSUMOF通道/通道开关信号)
设dB=10*log10(RMSSUMOF通道/通道开关信号)
返回数据库
}

经过数小时的研究和挖掘,我想我终于找到了在曲目之间“正常化”音频的解决方案

实际上很短。我将向该方法发送一个AVAudioPCMBuffer,并使用Accelerate API进行计算,首先计算RMS(功率),然后将其转换为分贝(dB)级别

我设置了一个默认音量级别,然后从dB的绝对值中减去它,并将该值传递给AVAudioEQ的.globalGain属性

至少在我看来,这似乎是为了实现我希望从Python转变过来的目标。我已经用很多MP3进行了测试,从一个曲目到另一个曲目的声音明显更大或更安静,而且它似乎工作得很好

如果你打算在非常大的音频文件上使用它,我建议把它放在自己的线程中,这样它就不会阻塞。对于我的应用程序来说,它似乎足够快了

如果你知道一种更好、更有效的方法,请在下面发表评论

Swift 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
}
导入加速
进口AVF基金会
func getDecibles1(缓冲区:AVAudioPCMBuffer)->Float{
//此方法将计算音频的实际均方值(RMS)
//PCM缓冲区,用于返回音频信号的分贝级。
//将计算具有信号的所有通道的RMS,并取其平均值
//然后为所有通道提供真实的音频分贝。
设frameLength=UInt(buffer.frameLength)
让channels=Int(buffer.format.channelCount)
var信道开关信号=浮动(信道)
变量rms:Float=0
变量rmsSumOfChannels:Float=0
对于0..0中的通道{
rms通道+=rms
}否则{
信道开关信号-=1
}
}
//如果需要平均功率,请取消注释下面的行
//设avgPower=20*log10(RMSSUMOF通道/通道开关信号)
设dB=10*log10(RMSSUMOF通道/通道开关信号)
返回数据库
}

vDSP_measqv的文档说它“计算单个精度向量中的平方平均值”。您需要取其平方根来获得rms吗?另外,如果将通道值添加到一起,正确的方法是什么?也许平均通道值更好,以获得对总输出有意义的值?把所有这些都当作问题来问,因为我的理解水平可能比你低。我停止使用这种方法,因为它在生产环境中不够好。我现在求助于通过ffmpeg的loud_norm过程运行命令行进程,将每个音频文件的LUF设置为相同的值。我可以在Xcode/Swift中找到任何原生的东西。我很好奇是什么原因让你得出结论,这种方法“在生产环境中不够好”。我正在尝试在一个仅供个人使用的应用程序中这样做。我希望避免翻阅我收藏的所有歌曲,手动让它们对我耳朵的响度大致相同(不一定是完全相同的LUFS值)。我开车的时候都在听,所以准确地说