I´m trying to develop an app that calculates the reverberation time of a room and displays it on the screen.
What I´ve done so far is:
record the audio in a wav file
extract the bytes from the wav file and transform them to "double"
plot the data obtained following the next equation: SPL=20log(samples/ 20 μPa)
then from the figure that I´ve plotted, I can obtain the RT60 easily
The point is that I´m not really sure if what I´m doing has any sense, as wherever I search for info I see that they obtain the RT by octave ( or third of octave ) bands and in my case I´m not doing anything with the frequency, I´m just plotting the graph against time getting something like this:
So my point is, is there anything that I´m missing?
Should the "samples" value in the SPL formula be something else? What Im doing to obtain them is:
double audioSample = (double) (array[i+1] << 8 | array[i] & 0xff)/ 32767.0;
and then I place the [-1,+1] values that I obtain directly in the formula
For what frequency I´m I theorically plotting the RT?
Thanks
You have to use a common frequency for the voice you can use 500hz
, 1000 or 2000. Or an average of the 3 like for the calculus off rt60. Oliver.
Related
1) For some reason, the longitude and latitude are slightly different after storing them. For example, when i first find them, they are:
25.171057657111998 and 35.013447496224636 but after I store them , they are
25.1710586547852 and 35.0134468078613. Why is this happening? I store them as floats in an sqlite database, retrieve them with Cursor.getFloat, and print them with String.format of 13 digit accuracy.Can this difference affect the end results in a significant way? I am working with distances <100m (328 feet)
2)I am trying to find the center of a location cluster. Here
http://www.geomidpoint.com/calculation.html
method C says I can just take a simple average if I work with <400km. Has anyone tried it? Is it working? Or should I go for the first, more accurate method?
3) After finding the center, do I need anything else to create a new location object for distance purposes?
To solve this problem you may store longitude and latitude in your sqlite database by this way:
longitude*10^10 , latitude*10^10
when you get them you will divide them by 10^10.
because with 5 decimal is accurate
As a part of a larger aplication I am currently working on a decibel meters that takes the average sound level of a 10 second timespan.
To achieve this I made a CountDownTimer of 10 000 miliseconds that ticks every 100 miliseconds.
In each onTick event I update the textfield that shows the time left, and I also update the realtime decibel value.
My issue however is converting the maximum amplitude to decibels. I found the "power_db = 20 * log10(amp / amp_ref);" formula here on StackOverflow and I understand how it works, but I seem to always end up with a negative decibel value.
I understand that this is because of a wrong amp_ref value, but I am absolutely stumped on which one I should use. I found alot of different values on the web and none seem to do the trick.
Does anyone have any idea which reference amplitude I should use to get the correct decibel reading on my meter? The phone I am testing this on is a Google Nexus 5. For now it would be good enough if it only was a really accurate value on this phone if thats of any help.
The code I have in my onTick event is the following (I removed the formula for now since it seemed to be wrong anyways):
public void onTick(long ms) {
meetBtn.setText(String.valueOf((ms/1000)+1));
amplitude = mRecorder.getMaxAmplitude();
decibelView.setText(String.valueOf(amplitude));
}
If anyone has any tips or needs more information, please let me know!
Thanks in advance! :)
Negative decibels are fine, because it's a relative measure anyway. In fact it's a common practice to take the maximum possible amplitude as a reference point and as a result have decibels go from 0 down to negative space. Pro systems usually indicate positive decibels as an overload when clipping and distortions of sound may occur.
So for example if your amplitude range is 0 to 1 (an accepted float-PCM standard), then your amp_ref would be 1 and your decibel values will go from some negative value that depends on the bitness resolution of your source (e.g. -186dB for 32 bit, or -90dB for 16-bit source), up to 0dB. This is normal!
Edit: actually, your float-PCM amplitude range is -1 to 1, but decibel calculation "drops" the minus sign and gives the same result for both negative and positive amplitudes.
In my application i want to know the transmit power of a mobile phone when i received from it data (beacon, file, ..). I need to know the transmit power, to use it in distance calculations using Received Signal Strength Indicator (RSSI).
How i can do that?
Ok, to measure distance using signal dampening:
There are different way of doing this. The most basic way is using open space dampening, where you get reference values inside a certain space, e.g a room. Any new furniture or change in surface material affect these values. This document is some guys thesis or something about the subject, you might want to check this out: http://www.s2is.org/Issues/v1/n2/papers/paper14.pdf. Good location is difficult especially, because the dampening is not linear.
This function is for theoretican dampening in open space:
L = 20 log(d) + 20 log(f) + 36.6,
where L is dampening in Db
f is frequency in MHz
and d is distance in miles.
This is the radio theory
I know Visualizer to show some wave while playing audio using android Media Player.
But i want to show Visualizer while recording audio means while recording i want to show linear wave which changes based on user voice beat.
Is it possible to do in android.
by calling every x milliseconds your MediaRecorder.getMaxAmplitude(), you gonna have (from official documentation) :
the maximum absolute amplitude that was sampled since the last call to
this method.
then, you can process this value in real time to draw a graph or change some view properties.
not perfect, but I hope it helps =)
edit: just so you know, the retrieved value will be the same across all android devices : between 0 and 32767. (I have more than 10k user's reports giving me this value when they blow in the mic).
You may need to use AudioRecorder class instead of MediaRecorder.
Check AudioRecorder#read(...) methods which put audio data to byte[] instead of putting it directly to a file.
To show changes on the graph you will have to analyze the data (which is encoded in PCM 8 or 16 bit - link) and update the graph in real time.
Two important things:
you need to convert live bytes (from mic) to numeric values inorder to plot them.
Since you use a real-time graph, to plot those points
use SurfaceView.
Convert recording bytes to numeric values refer:
Android: Listener to record sound if any sound occurs where you will see the variable "temp" holds the numerical value of your audio.
Plot points
These numeric values which indicates your Y values is plotted against increasing X (time interval) values (0,1,2..) as graph. Using SurfaceView
eg..,
//canvas.drawLine(previous X value,previous Y value,X,Y, paint);
canvas.drawPoint(X,Y,paint);
SurfaceHolder.unlockCanvasAndPost(canvas);
You need not plot all values, for efficiency you can filter those values with your conditions and plot for certain intervals of time.
Hope this helps :)
I am using the AudioRecord class to analize raw pcm bytes as it comes in the mic.
So thats working nicely. Now i need convert the pcm bytes into decibel.
I have a formula that takes sound presure in Pa into db.
db = 20 * log10(Pa/ref Pa)
So the question is the bytes i am getting from audiorecorder from the buffer what is it is it amplitude pascal sound pressure or what.
I tried to putting the value into te formula but it comes back with very hight db so i do not think its right
thanks
Disclaimer: I know little about Android.
Your device is probably recording in mono at 44,100 samples per second (maybe less) using two bytes per sample. So your first step is to combine pairs of bytes in your original data into two-byte integers (I don't know how this is done in Android).
You can then compute the decibel value (relative to the peak) of each sample by first taking the normalized absolute value of the sample and passing it to your Db function:
float Db = 20 * log10(ABS(sampleVal) / 32768)
A value near the peak (e.g. +32767 or -32768) will have a Db value near 0. A value of 3277 (0.1) will have a Db value of -20; a value of 327 (.01) will have a Db value of -40 etc.
The problem is likely the definition of the "reference" sound pressure at the mic. I have no idea what it would be or if it's available.
The only audio application I've ever used, defined 0db as "full volume", when the samples were at + or - max value (in unsigned 16 bits, that'd be 0 and 65535). To get this into db I'd probably do something like this:
// assume input_sample is in the range 0 to 65535
sample = (input_sample * 10.0) - 327675.0
db = log10(sample / 327675.0)
I don't know if that's right, but it feels right to the mathematically challenged me. As the input_sample approaches the "middle", it'll look more and more like negative infinity.
Now that I think about it, though, if you want a SPL or something that might require different trickery like doing RMS evaluation between the zero crossings, again something that I could only guess at because I have no idea how it really works.
The reference pressure in Leq (sound pressure level) calculations is 20 micro-Pascal (rms).
To measure absolute Leq levels, you need to calibrate your microphone using a calibrator. Most calibrators fit 1/2" or 1/4" microphone capsules, so I have my doubts about calibrating the microphone on an Android phone. Alternatively you may be able to use the microphone sensitivity (Pa/mV) and then calibrate the voltage level going into the ADC. Even less reliable results could be had from comparing the Android values with the measured sound level of a diffuse stationary sound field using a sound level meter.
Note that in Leq calculations you normally use the RMS values. A single sample's value doesn't mean much.
I held my sound level meter right next to the mic on my google ion and went 'Woooooo!' and noted that clipping occurred about 105 db spl. Hope this helps.
The units are whatever units are used for the reference reading. In the formula, the reading is divided by the reference reading, so the units cancel out and no longer matter.
In other words, decibels is a way of comparing two things, it is not an absolute measurement. When you see it used as if it is absolute, then the comparison is with the quietest sound the average human can hear.
In our case, it is a comparison to the highest reading the device handles (thus, every other reading is negative, or less than the maximum).