如何检测最大 dB Swift

Posted

技术标签:

【中文标题】如何检测最大 dB Swift【英文标题】:How to detect max dB Swift 【发布时间】:2016-07-07 13:35:09 【问题描述】:

我正在尝试检测 ios 设备上的 dB,但是,我是 AV 音频基础的新手,无法真正弄清楚。我遇到过这个帖子:iOS - Detect Blow into Mic and convert the results! (swift),但它对我不起作用。

我目前的代码是这样的:

import Foundation
import UIKit
import AVFoundation
import CoreAudio

class ViewController: UIViewController 

var recorder: AVAudioRecorder!
var levelTimer = NSTimer()
var lowPassResults: Double = 0.0

override func viewDidLoad() 
    super.viewDidLoad()

    //make an AudioSession, set it to PlayAndRecord and make it active
    var audioSession:AVAudioSession = AVAudioSession.sharedInstance()
    audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: nil)
    audioSession.setActive(true, error: nil)

    //set up the URL for the audio file
    var documents: AnyObject = NSSearchPathForDirectoriesInDomains( NSSearchPathDirectory.DocumentDirectory,  NSSearchPathDomainMask.UserDomainMask, true)[0]
    var str =  documents.stringByAppendingPathComponent("recordTest.caf")
    var url = NSURL.fileURLWithPath(str as String)

    // make a dictionary to hold the recording settings so we can instantiate our AVAudioRecorder
    var recordSettings: [NSObject : AnyObject] = [AVFormatIDKey:kAudioFormatAppleIMA4,
                                                  AVSampleRateKey:44100.0,
                                                  AVNumberOfChannelsKey:2,AVEncoderBitRateKey:12800,
                                                  AVLinearPCMBitDepthKey:16,
                                                  AVEncoderAudioQualityKey:AVAudioQuality.Max.rawValue

    ]

    //declare a variable to store the returned error if we have a problem instantiating our AVAudioRecorder
    var error: NSError?

    //Instantiate an AVAudioRecorder
    recorder = AVAudioRecorder(URL:url, settings: recordSettings, error: &error)
    //If there's an error, print otherwise, run prepareToRecord and meteringEnabled to turn on metering (must be run in that order)
    if let e = error 
        print(e.localizedDescription)
     else 
        recorder.prepareToRecord()
        recorder.meteringEnabled = true

        //start recording
        recorder.record()

        //instantiate a timer to be called with whatever frequency we want to grab metering values
        self.levelTimer = NSTimer.scheduledTimerWithTimeInterval(0.02, target: self, selector: #selector(ViewController.levelTimerCallback), userInfo: nil, repeats: true)

    



//This selector/function is called every time our timer (levelTime) fires
func levelTimerCallback() 
    //we have to update meters before we can get the metering values
    recorder.updateMeters()

    //print to the console if we are beyond a threshold value. Here I've used -7
    if recorder.averagePowerForChannel(0) > -7 
        print("Dis be da level I'm hearin' you in dat mic ")
        print(recorder.averagePowerForChannel(0))
        print("Do the thing I want, mofo")
    




override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.




【问题讨论】:

【参考方案1】:

我目前正在构建关于电影制作的应用程序,并学习了一些有关如何以 dB 为单位测量声级的知识。

recorder.averagePowerForChannel的原始数据并不是真正的声音分贝级别,它提供的级别范围是-160 - 0,所以我们需要进行一些修改让这个数据更合理

所以我发现了一些东西可以使这个数据(值)转换为 dB 级别的数据。

(抱歉忘记在哪里找到它了!)

这里是代码

/**
 Format dBFS to dB

 - author: RÅGE_Devil_Jåmeson
 - date: (2016-07-13) 20:07:03

 - parameter dBFSValue: raw value of averagePowerOfChannel

 - returns: formatted value
 */
func dBFS_convertTo_dB (dBFSValue: Float) -> Float

var level:Float = 0.0
let peak_bottom:Float = -60.0 // dBFS -> -160..0   so it can be -80 or -60

if dBFSValue < peak_bottom

    level = 0.0

else if dBFSValue >= 0.0

    level = 1.0

else

    let root:Float              =   2.0
    let minAmp:Float            =   powf(10.0, 0.05 * peak_bottom)
    let inverseAmpRange:Float   =   1.0 / (1.0 - minAmp)
    let amp:Float               =   powf(10.0, 0.05 * dBFSValue)
    let adjAmp:Float            =   (amp - minAmp) * inverseAmpRange

    level = powf(adjAmp, 1.0 / root)

return level

我注意到您正在录制 2 个频道,因此它与我的代码略有不同;

希望可以帮助您或给您一些想法:D

最后更新

将编码语言更改为 swift

【讨论】:

哦,顺便说一句,averagePowerForChannel 确实返回分贝。它们从 -160 变为 0,因为它们是 dbFS。 -160 表示静音,它一直向上到 0,即满级。 哦,谢谢提及语言(当然还有 wiki :))。我会尝试快速重写我的答案代码并尽快修改我的答案。 感谢您的帮助:) @EricAya 据我了解,dbFS 值与麦克风自身的最大饱和度 (0dBFS) 相关。这个值是相对于麦克风的属性而言的,难道实际上不可能将其转换为 dB(a) 吗? (除非您有每个麦克风的参考表,其中包含各自的校准详细信息) @itMaxence 不,dbFS 与麦克风属性无关,它们代表一个绝对值。你的麦克风有自己的动态范围,当然,它不太可能是 160db,大多数情况下,好的麦克风会在 80db 左右,这取决于麦克风的质量。但是这个范围可以在 dbFS 范围内的任何地方再现,具体取决于您通过放大器/录音机/等将麦克风输出带到的音量。所以它可能在0dbFS和-80dbFs之间,或者在-80dbFS和-160dbFS之间,或者在-40dbFS和-120dbFS之间,等等。

以上是关于如何检测最大 dB Swift的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中找到 Double 和 Float 的最大值

如何检测一个窗口已经被最大化?

SQLAlchemy 如何获取字段的最大值?

如何在 Swift 4 中为 UICollectionView 的部分设置最大元素数?

如何在 HSQL DB 中创建具有最大行值的序列?

如何在其中一个字段 Mongo Db [重复] 中检索具有最大值的文档