Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS : Create a simple audio waveform animation

I am trying to record audio with AVAudioRecorder. I need to create a simple waveform like this :

enter image description here

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 {

        }

    }
like image 1000
iOS.Lover Avatar asked Apr 03 '17 06:04

iOS.Lover


People also ask

How do I record a sound wave on my iPhone?

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.


1 Answers

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

like image 58
Gary Makin Avatar answered Sep 23 '22 02:09

Gary Makin