I am doing the right thing to convert decibel from -120 - 0 to 0 - 120

I would like to measure the volume of ambient sound, not too sure that I am doing the right thing.

I would like to create a VU counter of range 0 (quiet) to 120 (very noisy).

I got the power of Peak and Avg, but very high in the usual calm environment. Give me some pointer.

- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //creating an audio CAF file in the temporary directory, this isn't ideal but it's the only way to get this class functioning (the temporary directory is erased once the app quits). Here we also specifying a sample rate of 44.1kHz (which is capable of representing 22 kHz of sound frequencies according to the Nyquist theorem), and 1 channel (we do not need stereo to measure noise). NSDictionary* recorderSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey, [NSNumber numberWithInt:44100],AVSampleRateKey, [NSNumber numberWithInt:1],AVNumberOfChannelsKey, [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey, [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey, [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey, nil]; NSError* error; NSURL *url = [NSURL fileURLWithPath:@"/dev/null"]; recorder = [[AVAudioRecorder alloc] initWithURL:url settings:recorderSettings error:&error]; //enable measuring //tell the recorder to start recording: [recorder record]; if (recorder) { [recorder prepareToRecord]; recorder.meteringEnabled = YES; [recorder record]; levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector: @selector(levelTimerCallback:) userInfo: nil repeats: YES]; } else { NSLog(@"%@",[error description]); } } - (void)levelTimerCallback:(NSTimer *)timer { [recorder updateMeters]; const double ALPHA = 0.05; double peakPowerForChannel = pow(10, (0.05 * [recorder averagePowerForChannel:0])); lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults; NSLog(@"Average input: %f Peak input: %f Low pass results: %f", [recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults); float tavgPow =[recorder averagePowerForChannel:0] + 120.0; float tpPow = [recorder peakPowerForChannel:0] + 120.0; float avgPow = tavgPow;//(float)abs([recorder averagePowerForChannel:0]); float pPow = tpPow;//(float)abs([recorder peakPowerForChannel:0]); NSString *tempAvg = [NSString stringWithFormat:@"%0.2f",avgPow]; NSString *temppeak = [NSString stringWithFormat:@"%0.2f",pPow]; [avg setText:tempAvg]; [peak setText:temppeak]; NSLog(@"Average input: %f Peak input: %f Low pass results: %f", avgPow,pPow , lowPassResults); } 
+7
source share
5 answers

The formula for converting linear amplitude to decibels when you want to use 1.0 as your reference (for 0db) is

 20 * log10(amp); 

So, I'm not sure about the intent to look at your code, but you probably want to

 float db = 20 * log10([recorder averagePowerForChannel:0]); 

This will go from -infinity with an amplitude of zero to 0db with an amplitude of 1. If you really need it to rise between 0 and 120, you can add 120 and use the maximum function to zero.

So, after the line above:

 db += 120; db = db < 0 ? 0 : db; 

The formula you use seems to be the formula for converting the database to an amplifier, which, I think, is the opposite of what you want.

Edit: I am re-reading and it seems that you already have a decibel value.

If so, just don't convert to amplitude and add 120.

So change

 double peakPowerForChannel = pow(10, (0.05 * [recorder averagePowerForChannel:0])); 

to

 double peakPowerForChannel = [recorder averagePowerForChannel:0]; 

and you should be fine.

+8
source

Apple uses the lookup table in its SpeakHere sample, which converts from dB to the linear value displayed on the level meter. This is necessary to save the power of the device (I think).

I also needed this, but I did not think that a couple of floating calculations every 1 / 10s (my refresh rate) would cost that much power of the device. So, instead of creating a table, I formatted their code:

 float level; // The linear 0.0 .. 1.0 value we need. const float minDecibels = -80.0f; // Or use -60dB, which I measured in a silent room. float decibels = [audioRecorder averagePowerForChannel:0]; if (decibels < minDecibels) { level = 0.0f; } else if (decibels >= 0.0f) { level = 1.0f; } else { float root = 2.0f; float minAmp = powf(10.0f, 0.05f * minDecibels); float inverseAmpRange = 1.0f / (1.0f - minAmp); float amp = powf(10.0f, 0.05f * decibels); float adjAmp = (amp - minAmp) * inverseAmpRange; level = powf(adjAmp, 1.0f / root); } 

I use AVAudioRecorder , so you see that dB with averagePowerForChannel: but you can fill in your own dB value there.

Apple’s example used double calculations, which I don’t understand, because the accuracy of measuring a float sound is more than sufficient and costs less than the device’s power.

Needless to say, you can now scale this calculated level to a range of 0 .. 120 with a simple level * 120.0f .

The above code can be accelerated when we fix root in 2.0f by replacing powf(adjAmp, 1.0f / root) with sqrtf(adjAmp) ; but this is a minor thing, and a very good compiler can do this for us. And I'm pretty sure that inverseAmpRange will be computed once at compile time.

+23
source

In fact, the decibel range is from -160 to 0, but it can go to positive values. ( Link to the AVAudioRecorder class - averagePowerForChannel: method)

Then it is better to write db += 160; instead of db += 120; . Of course, you can also put an offset to correct it.

+1
source

I am doing a regression model to convert a mapping relationship between wav data generated from NSRecorder and decibel data from NSRecorder.averagePowerForChannel

NSRecorder.averagePowerForChannel (dB) = -80 + 6 wav_RMS ( wav_RMS )

Where wav_RMS is the rms value of the wav data in a short time, i.e. 0.1 s.

0
source

Just set the maximum and minimum value. How do you get a range of 0-120. If you need a range of 0-60. Just divide the value by half to get half the range, etc.

-3
source

All Articles