# Java amplitude processing

I have some code that collects amplitudes from a complex sound like a song. I now want to plot a graph of amplitude vs time, for the graph plotting I use JavaFX. However I get about 9 million amplitude shorts for each channel, so how to I select a few samples to plot (as plotting 9 million points is obviously out of the question)? Do I need to use the sample rate or sample size? Is there a particular way I should go about this?

Is this post more suited for StackOverflow?

AudioInputStream in = AudioSystem.getAudioInputStream(file);
AudioInputStream din = null;
AudioFormat baseFormat = in.getFormat();
AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(), //sample rate
16,                         //sample size (bits)
baseFormat.getChannels(),   //channels
baseFormat.getChannels() * 2,//frame size
baseFormat.getSampleRate(), //frame rate
false);                     //little-endian
din = AudioSystem.getAudioInputStream(decodedFormat, in);
byte[] temp = new byte[4];

//....
//leftDos and rightDos are streams of shorts
//....

int i = 0;
while (din.read(temp, 0, 4) != -1) {
if (decodedFormat.getChannels() == 2) {
leftDos.writeShort(temp[1] * 256 + temp[0]);
rightDos.writeShort(temp[3] * 256 + temp[2]);
i++;
}
}

//...retrieve shorts...//
short[] left = new short[(bytes.length / 2)];

int len = 0;
try {
while (1 > 0) {
len++;
}
} catch (EOFException e) {
System.err.println("End of stream");
}


There are a number of ways to do this, but I like this way:

// very rough pseudocode
step_size = 9000000 / width_of_window;  // 9000000 or however many points
for each pixel in width of window
figure out what portion of the audio stream this x value corresponds to
take step_size shorts corresponding to position in audio stream
find the minimum and maximum values in that portion of the stream
draw a vertical line at the current x value with position and length corresponding
to the min and max values you found


So basically you're displaying the min and max values of successive portions of the stream in each column of your draw box, or canvas, or whatever you're using.

• 9000000 / width_of_window seems fairly arbitrary; that would mean on smaller screens I take less samples, but I want to take the same amount of samples but just not 9 million. My question is what should the sample size be? – Cobbles Mar 21 '14 at 18:32
• @Cobbles: If this is going on Android, then the right number of samples to take does depend on the screen size. Anything else will look ugly some of the time (depending on screen size). The only problem I see with MackTuesday's approach is that there will be aliasing... however this might not be a problem, depending on how accurate you want your display to be. – Peter K. Mar 21 '14 at 20:07
• I picked 9000000 because that's how many values you were reading. That's what I meant in the comment, "9000000 or however many points". You'd replace that number with however many values you've read. Sorry that wasn't clear. It sounds like you're trying to smoosh a curve of 9000000 data points into a much smaller pixel area, right? – MackTuesday Mar 21 '14 at 20:14
• @Peter K: Generally aliasing isn't a concern because you're just trying to roughly convey where the signal is loud and where it's soft. I guess if you needed it to be extra pretty you'd massage the graphics a bit, but my approach is a common method. – MackTuesday Mar 21 '14 at 20:22
• @MackTuesday: Understood. As I said, it might not be a problem, depending on the data they are displaying. – Peter K. Mar 21 '14 at 20:27