I am trying to record audio with AVAudioRecorder
. I need to create a simple waveform like this :
When the user speaks into the microphone a circle indicates the level of the user's voice. I tried to measure the voice with this code but the code did not detect any buffer and not work :
func levelTimerCallback(timer:Timer) {
//we have to update meters before we can get the metering values
audioRecorder.updateMeters()
//print to the console if we are beyond a threshold value. Here I've used -7
if audioRecorder.averagePower(forChannel: 1) > -7 {
print(" level I'm hearin' you in dat mic ")
print(audioRecorder.averagePower(forChannel: 0))
}
}
Recording audio :
func startRecording() {
let audioSession = AVAudioSession.sharedInstance()
do {
// Audio Settings
settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 12000,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
audioRecorder = try AVAudioRecorder(url: self.directoryURL(), settings: settings)
audioRecorder.delegate = self
audioRecorder.prepareToRecord()
audioRecorder.isMeteringEnabled = true
} catch {
finishRecording(success: false)
}
do {
try audioSession.setActive(true)
audioRecorder.record()
TIMERRRRR = Timer.scheduledTimer(timeInterval: 0.02, target: self, selector: #selector(ViewController.levelTimerCallback), userInfo: nil, repeats: true)
} catch {
}
}
Here's how to record audio using your iPhone and the Voice Memos app: Open Voice Memos on your iPhone (if you can't find it, it may be in a Utilities folder). Tap the red record circle at the bottom of the screen. Tap the red square to stop recording.
Two problems that I can see.
The first is that you are testing with the wrong channel number in your function levelTimerCallback
. Your test should be for channel 0.
The other is that the value of -7
is actually very loud. averagePower
returns floats between -160 and 0. Try testing against -160 to start with and increasing that to reduce the sensitivity.
This changes your test to:
if audioRecorder.averagePower(forChannel: 1) > -160 {
...
}
There is only a single channel for the input and the count starts at 0. You have this right later on in your call to audioRecorder.averagePower
.
To get a linear scale, you'll need to interpolate. Change the value of scale
to change the range. proportion
will be between 0 and scale
.
let lowerLimit: Float = -100.0
func levelTimerCallback(timer:Timer) {
audioRecorder.updateMeters()
let power = audioRecorder.averagePower(forChannel: 0)
if power > lowerLimit {
// proportion will have a value between 0 and scale
let scale: Float = 10.0
let proportion = -scale * (power - lowerLimit) / lowerLimit
}
}
Edit: fixed the proportion calculation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With