package greenfoot.sound;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;


| Gets the overall level of the default microphone plugged into the system. | @author Michael | public class MicLevelGrabber { private static final MicLevelGrabber INSTANCE = new MicLevelGrabber(); private final AudioFormat format; private int level; private final Runnable updator; private volatile boolean running; private boolean reportedFailure;
| Create a new mic level grabber and initialise the updator. | private MicLevelGrabber() { format = new AudioFormat(22050, 8, 1, true, true); updator = () -> { try { TargetDataLine line = (TargetDataLine) AudioSystem.getLine(new DataLine.Info(TargetDataLine.class, format)); line.open(); line.start(); int bufferSize = (int) (format.getSampleRate() / 20) * format.getFrameSize(); byte buffer[] = new byte[bufferSize]; int bytesRead = line.read(buffer, 0, bufferSize); line.stop(); line.close(); level = (int) ((getRMS(buffer, bytesRead) / 127) * 100); reportedFailure = false; } catch (LineUnavailableException ex) { if (! reportedFailure) { System.err.println("Couldn't get mic level: line unavailable"); reportedFailure = true; } } catch (IllegalArgumentException iae) { if (! reportedFailure) { System.err.println("Couldn't get mic level: can't match 22050,8,1 audio format"); reportedFailure = true; } } finally { running = false; } }; }
| Get the singleton instance of this class. | @return the instance. | public static MicLevelGrabber getInstance() { return INSTANCE; }
| Update the microphone level (spawns off a new thread) and return the | level. It will most likely be the previous result that's returned, | however for things like meters where the level is being constantly | monitored this shouldn't be a problem. | | @return a microphone input level, between 0 and 100 | public int getLevel() { updateLevel(); return level; }
| Spawn off the thread to update the mic level value, if it isn't already | running. | private synchronized void updateLevel() { if (!running) { running = true; new Thread(updator).start(); } }
| Get the root mean square average of an array of bytes. | @param arr the array of bytes. | @param lim the index to read up to in the array. | @return the root mean square of the values. | private static double getRMS(byte[] arr, int lim) { double average = 0; for (int i = 0; i < arr.length && i < lim; i++) { average += arr[i] * arr[i]; } average /= arr.length; return Math.sqrt(average); } }
top, use, map, class MicLevelGrabber

.   MicLevelGrabber
.   getInstance
.   getLevel
.   updateLevel
.   getRMS




120 neLoCode + 16 LoComm