1
$\begingroup$

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) {
         left[len] = leftDIS.readShort();
         len++;
     }
 } catch (EOFException e) {
      System.err.println("End of stream");
 }
$\endgroup$
2
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ 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? $\endgroup$ – Cobbles Mar 21 '14 at 18:32
  • $\begingroup$ @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. $\endgroup$ – Peter K. Mar 21 '14 at 20:07
  • $\begingroup$ 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? $\endgroup$ – MackTuesday Mar 21 '14 at 20:14
  • 1
    $\begingroup$ @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. $\endgroup$ – MackTuesday Mar 21 '14 at 20:22
  • $\begingroup$ @MackTuesday: Understood. As I said, it might not be a problem, depending on the data they are displaying. $\endgroup$ – Peter K. Mar 21 '14 at 20:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.