I want to develop app to calculate Sound frequency in Android. Android Device will take
Sound from microphone (i.e. out side sound) and I have one color background screen in app.
on sound frequency changes i have to change background color of screen .
So my question is "How can i get sound frequency"?
is there any android API available?
Please help me out of this problem.
Your problem was solved here EDIT: archived here. Also you can analyze the frequency by using FFT.
EDIT: FFTBasedSpectrumAnalyzer (example code, the link from the comment)
Thanks for Reply I have done this by using sample on
http://som-itsolutions.blogspot.in/2012/01/fft-based-simple-spectrum-analyzer.html
Just modify your code for to calculate sound frequency by using below method
// sampleRate = 44100
public static int calculate(int sampleRate, short [] audioData){
int numSamples = audioData.length;
int numCrossing = 0;
for (int p = 0; p < numSamples-1; p++)
{
if ((audioData[p] > 0 && audioData[p + 1] <= 0) ||
(audioData[p] < 0 && audioData[p + 1] >= 0))
{
numCrossing++;
}
}
float numSecondsRecorded = (float)numSamples/(float)sampleRate;
float numCycles = numCrossing/2;
float frequency = numCycles/numSecondsRecorded;
return (int)frequency;
}
The other answers show how to display a spectrogram. I think the question is how to detect a change in fundamental frequency. This is asked so often on Stack Exchange I wrote a blog entry (with code!) about it:
http://blog.bjornroche.com/2012/07/frequency-detection-using-fft-aka-pitch.html
Admittedly, the code is in C, but I think you'll find it easy to port.
In short, you must:
low-pass the input signal so that higher frequency overtones are not mistaken for the fundamental frequency (this may not appear to be an issue in your application, since you are just looking for a change in pitch, but I recommend doing it anyway for reasons that are too complex to go into here).
window the signal, using a proper windowing function. To get the most responsive output, you should overlap the windows, which I don't do in my sample code.
Perform an FFT on the data in each window, and calculate the frequency using the index of maximum absolute peak value.
Keep in mind for your application where you probably want to detect the change in pitch accurately and quickly, the FFT method I describe may not be sufficient. You have two options:
There are techniques for increasing the specificity of the pitch tracking using phase information, not just the absolute peak.
Use a time-domain method based on autocorrelation. Yin is an excellent choice. (google for "yin pitch tracking")
Here is a link to the code mentioned. There's also some other useful code there.
https://github.com/gast-lib/gast-lib/blob/master/library/src/root/gast/audio/processing/ZeroCrossing.java
Here's the deal with ZeroCrossings:
It is inaccurate at determining frequency precisely based on recorded audio on an Android. That said, it is still useful for giving your app a general sense that the sound it is hearing is a constant singing tone, versus just noise.
The code here seems to work quite well for determining frequency, (if you can translate it from C# to java)
http://code.google.com/p/yaalp/
Related
n00b question and I don't even understand enough to be able to Google well (or understand the answers appropriately).
I'm exploring Unity 3D and playing with Gyroscope input The issue is that each axis of the gyro returns values between -1 and +1 with 0 being the devices orientation when the gyro is enabled, where +1 & -1 share a border (like 12 on a clockface). However, the gyro's 0,0,0 point is not being reset when the gyro is enabled. The unity forums suggest deactivating the then re-activating the gyro will help - it doesn't.
In effect the gyro's 0 point is static in the current version of iOS & Unity, which means I need to 'offset' it to take into account the phone's starting position.
My plan was to have something like:
var GyroOffset : Quaternion;
var CurrentGyroAttitude : Quaternion;
var DeadSpotXPos : float;
var DeadSpotXPos : float;
var ThresholdPos : float;
var ThresholdNeg : float;
function Start() {
Input.gyro.enabled = true;
Input.gyro.UpdateInterval = 0.001;
GyroOffset = Input.gryo.attitude;
}
function Update() {
CurrentGyroAttitude = input.gyro.attitude - GyroOffset;
if (CurrentGyroAttitude.x > ThresholdPos) DoSomething(1);
if (CurrentGyroAttitude.x < ThresholdNeg) DoSomething(-1);
if (CurrentGyroAttitude.x > DeadSpotXPos &&
CurrentGyroAttitude.X < ThresholdPos) DoSomethingElse(1);
if (CurrentGyroAttitude.x < DeadSpotXNeg &&
CurrentGyroAttitude.x < ThresholdNeg) DoSomethingElse(-1);
}
* Where DoSomething(arbitraryFloat) and DoSomethingElse(anotherArbitraryFloat) does things that I want done and arbitrary float is not related to Gyro output.
As the Gyro output is between -1 and +1, we could reach a case where CurrentGyroAttitude.x could legitimately be -2 or +2. The problem with this plan is that I have to "offset" to my thresholds & deadspots as well which becomes "not neat" for tuning purposes. I'd much rather only manipulate the CurrentGyroAttitude.
However, I don't know how to do "clock face arthematic" in UnityScript. I think I'm talking about modulus mathematics but I keep running into complex mathematics about crypto that's doing my head in. :)
Can anyone walk me through "cleaning" the gyro attitude output so that my clean output stays between -1 and +1, once 'offset' has been taken into effect?
Incidentally if anyone can shed light on Unity's GyroUpdateInterval that would be awesome because the documentation doesn't explain what the updates are measured in, or what the effect of manipulating is.
I don't suppose you really wanted to access members of the Quaternion - they don't work the way you think they do. What you wanted was Quaternion.eulerAngles.
To make the angle relative to the starting position modify your Update:
Vector3 CurrentGyroEuler=(Quaternion.Inverse(Input.gyro.attitude)* GyroOffset).eulerAngles
I'm working on a guitar tuner app, by recording audio, getting an FFT of the audio, and finding the peak magnitude to find the base freq. So far results show my code works, and will give back an accurate frequency when played pure tones, especially at 500+hz, however with the low frequencies of guitar, and the loud harmonics, results are kind of messy.
I believe i need to introduce a window function, as well as a low pass filter to refine my results and help my app detect the right peak, and not a harmonic, but i'm not too sure
I have implemented a window function, although i'm not sure it's affecting final results, and i'm totally stuck on how to implement a low-pass filter.
byte data[] = new byte[bufferSize]; //the audio data read in
...
double[] window = new double[bufferSize]; //window array
//my window function, not sure if correct
for(int i = 0; i< bufferSize-1; ++i){
window[i] = ((1 - Math.cos(i*2*Math.PI/bufferSize-1))/2);
data[i] = (byte) (data[i] * window[i]);
}
DoubleFFT_1D fft1d = new DoubleFFT_1D(bufferSize);
double[] fftBuffer = new double[bufferSize*2];
for(int i = 0; i < bufferSize-1; ++i){
fftBuffer[2*i] = data[i];
fftBuffer[2*i+1] = 0;
}
fft1d.complexForward(fftBuffer);
//create/populate power spectrum
double[] magnitude = new double[bufferSize/2];
maxVal = 0;
for(int i = 0; i < (bufferSize/2)-1; ++i) {
double real = fftBuffer[2*i];
double imaginary = fftBuffer[2*i + 1];
magnitude[i] = Math.sqrt( real*real + imaginary*imaginary );
Log.i("mag",String.valueOf(magnitude[i]) + " " + i);
//find peak magnitude
for(int i = 0; i < (bufferSize/2)-1; ++i) {
if(magnitude[i] > maxVal){
maxVal = (int) magnitude[i];
binNo = i;
}
}
//results
freq = 8000 * binNo/(bufferSize/2);
Log.i("freq","Bin "+String.valueOf(binNo));
Log.i("freq",String.valueOf(freq) + "Hz");
So yeah, not entirely sure if the window function is doing much, power spectrum contains harmonic peaks regardless, and i'm not sure where to begin with using a low pass filter.
The Window Function can help increase a bit your results.
The purpose of the window is to decrease the amplitude component of the ends of the window, in order to avoid the appearance of spurious high frequency, this is necessary because the Fourier transform assumes the signal to be infinite, so in case of a window, it is repeated countless times for both sides, causing a discontinuity at the borders!
If you apply one window, this problem is minimized, but still occur to some degree.
If are you working with guitar build a low-pass to filter the highest tuned frequency expected, you need Low-pass before apply your Window Function!
you need to consider the Frequency Response from the microphone, I believe it is not easy for these mobile microphones capture low-frequency of a tuned guitar, we are talk about 82.4Hz
Finding the peak of FFT is not a good idea to do tuners !
The FFT can be thought of as a series of band-pass filters, with the magnitude of each bin being the power averaged over the window. A LPF upstream of a FFT isn't going to get you very much - you can just discard higher order FFT bins instead - unless you have a requirement for a particularly steep response.
The approach of implementing a guitar tuner with an FFT is problematic (although
having implementing a successful tuner this way, they aren't insurmountable).
Finding the peak bin is a naive approach and won't give you precise results. Ever. Each bin is a band-pass filter, so you make the assumption that the measured result is the bin centre frequency. Here's what's wrong:
The frequencies of semitones in equal temperament are a geometric progression (the ratio is ~1.06), yet the spacing of FFT bins is linear. If we assume Fs is 44.1k and a 1024 point FFT is used, the bin spacing 44.1Hz. As E2 (the bottom string of a guitar is ~82Hz #A440), it's clear this a tuner using this approach will largely useless. Even trading an extremely large window size for real-time response (and a lot of processing), it's still not very accurate. You're totally screwed trying to tune an electric bass (bottom string: E1, ~41Hz)
What happens with frequencies that straddle bins? As it happens the frequencies of C in all octaves are not far from a power of 2. B - a note a guitar tuner does need to perform well on is close too. For these notes, the fundamental's energy is split almost evenly between two bands. It's likely not the largest any more.
Is the fundamental even the peak frequency? (Hint: it's often not).
Bins overlap. Just how much depends on the window function used.
If you want to persist with FFT solutions, you probably want to be use the STFT. There's a good description of how to do it from DSPDimension.com. The one piece of information missing from that page is that the definition of frequency is as the rate-of-change of phase:
F = dPhi/dt
Consequently, it is possible to estimate F knowing the phase difference between two consecutive windows of results.
Note that windowing is sampling, so sampling theory and the Nyquist rate applies to frequency resolution achievable with it. You need at least 2048-point FFTs for a guitar tuner.
FFT peak magnitude frequency detection usually won't work for determining guitar pitch, since the peak frequency is often not the frequency of the note pitch. Try using a pitch detection or estimation algorithm instead. See More accurate estimating guitar pitch frequency based on FFT(already) result for some alternatives.
I am using the following code to calculate Frame Rate in Unity3d 4.0. It's applied on a NGUI label.
void Update () {
timeleft -= Time.deltaTime;
accum += Time.timeScale/Time.deltaTime;
++frames;
// Interval ended - update GUI text and start new interval
if( timeleft <= 0.0 )
{
// display two fractional digits (f2 format)
float fps = accum/frames;
string format = System.String.Format("{0:F2} FPS",fps);
FPSLabel.text = format;
timeleft = updateInterval;
accum = 0.0F;
frames = 0;
}
}
It was working previously, or at least seemed to be working.Then I was having some problem with physics, so I changed the fixed timestep to 0.005 and the Max timestep to 0.017 . Yeah I know it's too low, but my game is working fine on that.
Now the problem is the above FPS code returns 58.82 all the time. I've checked on separate devices (Android). It just doesn't budge. I thought it might be correct, but when I saw profiler, I can clearly see ups and downs there. So obviously it's something fishy.
Am I doing something wrong? I copied the code from somewhere (must be from the script wiki). Is there any other way to know the correct FPS?
By taking cues from this questions, I've tried all methods in the first answer. Even the following code is returning a constant 58.82 FPS. It's happening in the android device only. In the editor I can see fps difference.
float fps = 1.0f/Time.deltaTime;
So I checked the value of Time.deltaTime and it's 0.017 constant in the device. How can this be possible :-/
It seems to me that the fps counter is correct and the FPS of 58.82 is caused by the changes in your physics time settings. The physics engine probably cannot finish its computation in the available timestep (0.005, which is very low), and that means it will keep computing until it reaches the maximum timestep, which in your case is 0.017. That means all frames will take 0.017 plus any other overhead from rendering / scripts you may have. And 1 / 0.017 equals exactly 58.82.
Maybe you can fix any problems you have with the physics in other ways, without lowering the fixed timestep so much.
I'm in a little bit weird situation. The situation I currently have is typically a good one - no gyro drift at all - but I have no clue why this is the case. I expected the gyroscope to drift a lot as reported everywhere. Therefore this question to find the reason why I do not see any drift.
I use a Galaxy Nexus (Android 4.0.3) and its gyroscope to do some orientation change detection in the end. In the first place, I just wanted to log the sensor readings and expected to see large drifting values as for example here. Also on other websites I read of drifting of about 1 degree per second or similar measurements.
My code to log the sensor data is very basic:
SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);
LogSensorEventListener listener = new LogSensorEventListener(
SensorLoggerActivity.this, Sensor.TYPE_GYROSCOPE);
sm.registerListener(listener, sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
SensorManager.SENSOR_DELAY_FASTEST);
LogSensorEventListener is also a very basic implementation of the SensorEventListenerInterface:
#Override
public void onSensorChanged(SensorEvent event) {
final float dT = (event.timestamp - mTimestamp) / 1000000000.f;
if (dT < 1) { // just a fix for the first step
mRelZ += event.values[2] * dT;
list.add(mRelZ);
list2.add(event.timestamp);
}
mTimestamp = event.timestamp;
mRelZ is initially set to 0 and the two lists should keep track of time and measured value. If finished with my measurement (clicking a button) the values are written to file:
try {
for (int i = 0; i < list.size(); i++) {
long time = list2.get(i);
if (mStartTime < 0) {
mStartTime = time;
time = 0;
} else {
time = time - mStartTime;
}
float timef = time / 1000000000.0f;
sb.append(timef);
sb.append(";");
sb.append(Math.toDegrees(list.get(i)));
sb.append("\n");
}
mOutFileStream.write(sb.toString().getBytes());
mOutFileStream.flush();
mOutFileStream.close();
} catch (IOException e) {
}
Everything works fine but the only drift I can see (for example when having the device lying on a table and logging values for let's say 60 seconds) is about 0.2 degree.
If I move the device to get something like in the screenshot above no drift can be observed at all...
What I'm I doing wrong (or right?)??
Thanks for any advice!
the gyro you have might be a post-filtered one, i found this in some of the SAMSUNG I9100 devices. they use gyros produced by INVENSENSE CORP.
edit 2014/12/10 for commenting #Lourenço Castro
i believe #Lourenço Castro was right about the 'factory drift'(or zero-drift) and 'accumulated drift';
Concerning to complementary/kalman filters, on Android, the 6dof(ACC+GYRO) impl. works fine, it can remove both factory and accumulated drift of gyroscope thanks to accelerometer's calibration;
However, the 9dof impl., or adding a magnetometer sensor into consideration, filter runs into status you dont want. According to my tests, it is caused by uncalibed status of magnetometer which need guys to shake (known as drawing 'eight')the phone to remove before fusion.
9dof provides a full rotation estimation while 6dof can not handle the accumulated drift of rotating around y axis(see android's ref. for axis definition). And I dont think that 'shaking-and-drawing-number-8' before one starts an app is a good UE, so we have to go back to 6dof method and try to find a way to remove factory drift of rotation around y-axis.
(a lot of boring but amazing content about complementary/kalman filter should be here. but i guess those come here already know it.)
You can try a 360 panorama app included in Google Camera which can be downloaded from market. This app use a visual-aid(image processing based motion estimation) for calibrating the sensor before we really start to capturing, it's easy to verify this. And no use of Magnetometer, i guess.
So my advice to use sensor-fusion on Android is:
1. no magnetometer; (dont know if this is a hardware problem or can be solved by software.)
2. accelerometer+gyroscope provides smooth and stable 6dof motion estimation;
3. try to solve the drift around y-axis, mainly means that visual-method should be added to;
4. try 3 and try 3...
Maybe someone will run into this question and i hope all above might be helpful.
thanks to those posts related to this questions on StackOverflow.
i dont remember your names exactly but you all helped me a lot. :)
I was browsing for this subject and, although this is an old question, I don't believe the accepted answer is correct.
The drift that is "reported everywhere" is caused by the integration of noisy gyroscope data (as seen on the link provided by the O.P.), not by simply outputting the sensor data. You will need this integration to calculate orientation changes over time.
Longer integration periods will contain larger noise amounts which will accumulate drift fairly quickly. I believe the internal filtering of the signal which happens on Invensense hardware is used to remove drift caused by their own pre-processing of the gyroscope.
In Android's case, in API 18 (Jelly Bean MR2), a GYROSCOPE_UNCALIBRATED sensor was added, in which you can (presumably) verify this factory drift calibration. Anyway, when you try to integrate either the calibrated and uncalibrated sensor events, you will get drift, since both are pretty noisy. To reduce this issue you will have to delve into complementary or Kalman filters.
(Sorry about not posting more informational links, not enough reputation).
Hope this helps future users.
I try to change the frequency of a single soundfile. I managed to do that in android with the SoundPool thing. But the result sounds really bad.
So I stepped about the Fourier Transformation - but I am not sure if this is what I am looking for.
I want to load a single file and change the frequency of that file every time that file is played. So I can create melodies out of one tone. Is that possible with android/java?
This is the way I managed to do it. With "bad" I mean it sounds out of tune.
If I want to play the next frequency of the note in the file I must multiply it by 2^(1/12). But since it's just a float, I guess it's not precise enough to get the "real" frequency of the next note.
Is there a "simple" way to achieve that goal?
The simplest way with the SoundPool is to adjust the rate on your call to play():
play(aSoundId, leftVolume, rightVolume, 1, 0, rate);
The rate can vary from .5f to 2.0f, though the extremes typically don't sound great, so you may want to set an acceptable range (e.g., .4f) and a minimum rate (e.g., .85f). Then you can have a variable to control where you are within that range (e.g., a float that ranges between .0f and 1.0f):
float rate = RATE_RANGE * pitch + MINIMUM_RATE;