Prev: Request Help - how to pass correctly formatted strings to Java in Windows
Next: Static Class Variables and IE8 Loosely Couple Internet Explorer(LCIE)
From: Sélénissime on 9 Jan 2010 07:55 Hello I would like to record a sound (from the microphone) and, at the same time, be able to analyse the sound amplitude. For example, I want to be able to display (in real time) a number indicating how high is the volume recorded from microphone. I've looked at javax.sound.sampled API. I could read bytes from the input Stream, by the method TargetDataLine.read, but I don't how I could analyse these bytes. I've looked at JMF API, but it doesn't seem to do what I want. Thank you in advance for your help --- Cedric (from France)
From: Knute Johnson on 9 Jan 2010 12:47 On 1/9/2010 4:55 AM, S�l�nissime wrote: > Hello > I would like to record a sound (from the microphone) and, at the same > time, be able to analyse the sound amplitude. > For example, I want to be able to display (in real time) a number > indicating how high is the volume recorded from microphone. > > I've looked at javax.sound.sampled API. I could read bytes from the > input Stream, by the method TargetDataLine.read, but I don't how I > could analyse these bytes. > I've looked at JMF API, but it doesn't seem to do what I want. > > Thank you in advance for your help > > --- > Cedric (from France) Cedric: That's actually pretty easy if you know the format of the audio data. If the data for example were encoded PCM_UNSIGNED in 8 bit you could just use the 8 bit value directly. If it is 16 bit signed you would need to read two bytes and convert it to a short or int value. With PCM encoding the value of the data is the volume. Here are the beginnings of some code I wrote to display the peak values. It is configured for PCM_SIGNED 16 bit audio data. Pass it the byte buffer that you used to read the data from the TargetDataLine and the number of bytes of data in the buffer. import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; public class PeakMeter extends JPanel { volatile int peak; volatile double previousLevel; public void draw(byte[] b, int len) { int n = 0; peak = 0; for (int i=0; i<len; i+=2) { n = Math.abs((b[i] << 8) | b[i+1]); if (n > peak) peak = n; } repaint(); } public void paintComponent(Graphics g2d) { Graphics2D g = (Graphics2D)g2d; g.rotate(Math.PI,getWidth()/2,getHeight()/2); double level = peak / 32768.0; if (level < previousLevel) level = previousLevel * 0.80; previousLevel = level; g.setColor(Color.WHITE); g.fillRect(0,0,getWidth(),getHeight()); g.setColor(Color.GREEN); int h = Math.min((int)(level * getHeight()),(int)(0.70 * getHeight())); g.fillRect(0,0,getWidth(),h); if (level > 0.70) { g.setColor(Color.YELLOW); h = Math.min((int)((level - 0.70) * getHeight()), (int)(0.20 * getHeight())); g.fillRect(0,(int)(0.70 * getHeight()),getWidth(),h); } if (level > 0.90) { g.setColor(Color.RED); h = (int)((level - 0.90) * getHeight()); g.fillRect(0,(int)(0.90 * getHeight()),getWidth(),h); } } } -- Knute Johnson email s/nospam/knute2010/
From: Andrew Thompson on 9 Jan 2010 22:14 On Jan 9, 11:55 pm, Sélénissime <cedric.coust...(a)gmail.com> wrote: >...I want to be able to display (in real time) a number > indicating how high is the volume recorded from microphone. I think that what you are asking for is the RMS volume. I implement an RMS volume for Tracker. E.G. <http://pscode.org/tracker/applet.html?media.url=%2Fmedia %2FDead_End.mp3&media.load=on&media.play=on> You can 'cancel' the digitally signed code and it will work equally well (or poorly, depending on how you look at it). Note that an RMS volume can only be calculated for a group of signal samples, so there is always some lag. The amplitude is calculated for the group of samples currently plotted. The group of samples, in turn, is obtained half from the sound just played, and half from sound about to be played. Of course that is not an option for analysing sound coming from a microphone. In any case, the method I use presumes the signal has been resolved to a doubles ranging from -1 to 1 (see Knute's code for converting samples to numbers) and can be seen here <http://pscode.org/javadoc/src-html/org/pscode/ui/audiotrace/ AudioPlotPanel.html#line.996> -- Andrew T. pscode.org
From: Sélénissime on 11 Jan 2010 03:52
Thank you very much! It is exactly what I wanted. I didn't think that it would so easy to analyse the volume from an array of bytes. > Cedric: > > That's actually pretty easy if you know the format of the audio data. > If the data for example were encoded PCM_UNSIGNED in 8 bit you could > just use the 8 bit value directly. If it is 16 bit signed you would > need to read two bytes and convert it to a short or int value. With PCM > encoding the value of the data is the volume. > > Here are the beginnings of some code I wrote to display the peak values. > It is configured for PCM_SIGNED 16 bit audio data. Pass it the byte > buffer that you used to read the data from the TargetDataLine and the > number of bytes of data in the buffer. > [...] |