In my work on my DrumSense app, I constantly battled with the slow level decay time of AVAudioRecorder. For example, if the ambient noise is level is -50 dB and you clap, causing the level to spike up to -10 dB, the meter level doesn't "decay" back to -50 dB right away. In fact, it can be agonizingly slow if you're interested in another sound happening right after that clap. Here's some visual data to illustrate the issue here, with a conversion from the decibel scale of -120 dB to 0 dB to a simpler 0-100 scale.
As you can see, it takes almost 2 seconds for the level to decay back to ambient sound level. While this may be okay in many cases, it's certainly not okay for others. For example, what if I wanted to detect a sound at t = 1.75 s that I knew was going to be quieter than my initial clap? I wouldn't be able to detect it if it didn't reach at least a level of about 90 on the scale above.
The Easy Fix
My easy fix: call "<AVAudioRecorder Name>.meteringEnabled = YES" to reset the level to ambient noise level.
The Project
To demonstrate, I've built a quick sample project. The whole project is available on GitHub at https://github.com/mattlogan/LevelMetering. As an added reference, check out Mobile Orchard's tutorial on detecting when a user blows into the mic. A lot of the code here is adapted from that project.
The Code
This is the code for my levelTimerCallback method, which runs every 0.1 s as a result of an NSTimer object.
Every time the callback method runs, it sends the BOOL "YES" to the meteringEnabled property of my AVAudioRecorder object, myRecorder.
The Result
Here's another visual representation of the level data, this time with the meteringEnabled code added to the level callback method.
Here, the decay time is only about 0.25 s, which is a great improvement from 2 s. Additionally, 0.25 s is probably the realistic peak-to-ambient decay time that we'd expect from a clap.
Notes on Performance and an Alternative
For my DrumSense app, I only called "meteringEnabled = YES" when a peak was detected, then I disregarded any points for a short time interval after that peak.
My initial solution for this problem actually involved calling stop and record, as below.
This solution still works for returning the level back to ambient noise, and it doesn't send the level back to 0, but it is much slower. Whereas the meteringEnabled method only has a delay of 0.02 s, the stop and record method takes about 0.05 s. While this doesn't seem like a huge difference, it matters when you're trying to detect peaks that can be 0.05 s apart as I did in my DrumSense app.

