PCMFilePlayerLevelerpublic class PCMFilePlayerLeveler extends Object implements Runnable
Fields Summary |
---|
File | file | AudioInputStream | in | SourceDataLine | line | int | frameSize | byte[] | buffer | Thread | playThread | boolean | playing | boolean | notYetEOF | AudioFormat | format | float | level | static final float | MAX_8_BITS_SIGNED | static final float | MAX_8_BITS_UNSIGNED | static final float | MAX_16_BITS_SIGNED | static final float | MAX_16_BITS_UNSIGNED |
Constructors Summary |
---|
public PCMFilePlayerLeveler(File f)
file = f;
// in = AudioSystem.getAudioInputStream (f);
in = AudioSystem.getAudioInputStream (new BufferedInputStream (new FileInputStream(f)));
format = in.getFormat();
AudioFormat.Encoding formatEncoding = format.getEncoding();
if (! (formatEncoding.equals (AudioFormat.Encoding.PCM_SIGNED) ||
formatEncoding.equals (AudioFormat.Encoding.PCM_UNSIGNED)))
throw new UnsupportedAudioFileException (
file.getName() + " is not PCM audio");
System.out.println ("got PCM format: " +
format.getChannels() + " channels, " +
format.getSampleSizeInBits() + " bit samples");
frameSize = format.getFrameSize();
System.out.println ("got frame size: ");
DataLine.Info info =
new DataLine.Info (SourceDataLine.class, format);
System.out.println ("got info");
line = (SourceDataLine) AudioSystem.getLine (info);
// figure out a small buffer size
int bytesPerSec = format.getSampleSizeInBits() *
(int) format.getSampleRate();
System.out.println ("bytesPerSec = " + bytesPerSec);
int bufferSize = bytesPerSec / 20;
buffer = new byte[bufferSize];
System.out.println ("got line");
line.open();
System.out.println ("opened line");
playThread = new Thread (this);
playing = false;
notYetEOF = true;
playThread.start();
|
Methods Summary |
---|
private void | calculateLevel(byte[] buffer, int readPoint, int leftOver)resets level by finding max value in buffer, taking
into account whether these are 8 or 16 bit values
(doesn't care about mono vs stereo - if one channel
is disproportionately louder than the other, it wins)
int max = 0;
boolean use16Bit = (format.getSampleSizeInBits() == 16);
boolean signed = (format.getEncoding() ==
AudioFormat.Encoding.PCM_SIGNED);
boolean bigEndian = (format.isBigEndian());
if (use16Bit) {
for (int i=readPoint; i<buffer.length-leftOver; i+=2) {
int value = 0;
// deal with endianness
int hiByte = (bigEndian ? buffer[i] : buffer[i+1]);
int loByte = (bigEndian ? buffer[i+1] : buffer [i]);
if (signed) {
short shortVal = (short) hiByte;
shortVal = (short) ((shortVal << 8) | (byte) loByte);
value = shortVal;
} else {
value = (hiByte << 8) | loByte;
}
max = Math.max (max, value);
} // for
} else {
// 8 bit - no endianness issues, just sign
for (int i=readPoint; i<buffer.length-leftOver; i++) {
int value = 0;
if (signed) {
value = buffer [i];
} else {
short shortVal = 0;
shortVal = (short) (shortVal | buffer [i]);
value = shortVal;
}
max = Math.max (max, value);
} // for
} // 8 bit
// express max as float of 0.0 to 1.0 of max value
// of 8 or 16 bits (signed or unsigned)
if (signed) {
if (use16Bit) { level = (float) max / MAX_16_BITS_SIGNED; }
else { level = (float) max / MAX_8_BITS_SIGNED; }
} else {
if (use16Bit) { level = (float) max / MAX_16_BITS_UNSIGNED; }
else { level = (float) max / MAX_8_BITS_UNSIGNED; }
}
| public java.io.File | getFile()
return file;
| public float | getLevel()
return level;
| public javax.sound.sampled.SourceDataLine | getLine()
return line;
| public void | run()
int readPoint = 0;
int bytesRead = 0;
try {
while (notYetEOF) {
if (playing) {
// only write if the line will take at
// least a buffer-ful of data
if (line.available() < buffer.length) {
Thread.yield();
continue;
}
bytesRead = in.read (buffer,
readPoint,
buffer.length - readPoint);
if (bytesRead == -1) {
notYetEOF = false;
break;
}
// how many frames did we get,
// and how many are left over?
int frames = bytesRead / frameSize;
int leftover = bytesRead % frameSize;
// calculate level
calculateLevel (buffer, readPoint, leftover);
// if (level > 1)
// System.out.println ("WTF? level = " + level);
// System.out.println ("level: " + level);
// send to line
line.write (buffer, readPoint, bytesRead-leftover);
// save the leftover bytes
System.arraycopy (buffer, bytesRead,
buffer, 0,
leftover);
readPoint = leftover;
} else {
// if not playing
// Thread.yield();
try { Thread.sleep (10);}
catch (InterruptedException ie) {}
}
} // while notYetEOF
System.out.println ("reached eof");
line.drain();
line.stop();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
// line.close();
}
| public void | start()
playing = true;
if (! playThread.isAlive())
playThread.start();
line.start();
| public void | stop()
playing = false;
line.stop();
|
|