Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Need help with a Java problem: Using the program classes NBCTones and SITTones p

ID: 3813034 • Letter: N

Question

Need help with a Java problem:

Using the program classes NBCTones and SITTones provided below, write a program class called PlayFNotes that plays in order the notes F4, F5, and F6, each for one and a half seconds. The frequency of F4 is 349.228Hz, F5 is 698.456Hz, and F6 is 1396.913Hz. You will need the playTone method so simply copy it from one of the provided example programs into your program. Note that the second parameter, duration, should be the number of seconds to play the tone.

NBCTones.java:

import stdlib.StdAudio;

public class NBCTones {
  
   public static void playTone(double frequency, double duration) {
       final int sliceCount = (int) (StdAudio.SAMPLE_RATE * duration);
       final double[] slices = new double[sliceCount+1];
       for (int i = 0; i <= sliceCount; i++) {
           slices[i] = Math.sin(2 * Math.PI * i * frequency / StdAudio.SAMPLE_RATE);
       }
       StdAudio.play(slices);
   }

   public static void main(String[] args) {
       playTone(196.0, 1.0);
       playTone(329.6, 1.0);
       playTone(261.6, 1.0);
   StdAudio.close();
System.exit(0);
   }

}

SITTones.java:

import stdlib.StdAudio;

public class SITTones {

   public static void playTone(double frequency, double duration) {
       final int sliceCount = (int) (StdAudio.SAMPLE_RATE * duration);
       final double[] slices = new double[sliceCount+1];
       for (int i = 0; i <= sliceCount; i++) {
           slices[i] = Math.sin(2 * Math.PI * i * frequency / StdAudio.SAMPLE_RATE);
       }
       StdAudio.play(slices);
   }

   public static void main(String[] args) {
       playTone(950.0, 0.4);
       playTone(1400.0, 0.4);
       playTone(1800.0, 0.4);
   StdAudio.close();
System.exit(0);
   }

}

StdAudio.java:

package stdlib;
/* ***********************************************************************
* Compilation: javac StdAudio.java
* Execution: java StdAudio
*
* Simple library for reading, writing, and manipulating .wav files.

*
* Limitations
* -----------
* - Does not seem to work properly when reading .wav files from a .jar file.
* - Assumes the audio is monaural, with sampling rate of 44,100.
*
*************************************************************************/

import java.applet.*;
import java.io.*;
import java.net.*;
import javax.sound.sampled.*;

/**
* <i>Standard audio</i>. This class provides a basic capability for
* creating, reading, and saving audio.
* <p>
* The audio format uses a sampling rate of 44,100 (CD quality audio), 16-bit, monaural.
*
* <p>
* For additional documentation, see <a href="http://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
* <i>Introduction to Programming in Java: An Interdisciplinary Approach</i> by Robert Sedgewick and Kevin Wayne.
*/
public final class StdAudio {

   /**
   * The sample rate - 44,100 Hz for CD quality audio.
   */
   public static final int SAMPLE_RATE = 44100;

   private static final int BYTES_PER_SAMPLE = 2; // 16-bit audio
   private static final int BITS_PER_SAMPLE = 16; // 16-bit audio
   private static final double MAX_16_BIT = Short.MAX_VALUE; // 32,767
   private static final int SAMPLE_BUFFER_SIZE = 4096;


   private static SourceDataLine line; // to play the sound
   private static byte[] buffer; // our internal buffer
   private static int bufferSize = 0; // number of samples currently in internal buffer

   // do not instantiate
   private StdAudio() { }


   // static initializer
   static { init(); }

   // open up an audio stream
   private static void init() {
       try {
           // 44,100 samples per second, 16-bit audio, mono, signed PCM, little Endian
           AudioFormat format = new AudioFormat(SAMPLE_RATE, BITS_PER_SAMPLE, 1, true, false);
           DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

           line = (SourceDataLine) AudioSystem.getLine(info);
           line.open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE);

           // the internal buffer is a fraction of the actual buffer size, this choice is arbitrary
           // it gets divided because we can't expect the buffered data to line up exactly with when
           // the sound card decides to push out its samples.
           buffer = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE/3];
       } catch (Exception e) {
           System.out.println(e.getMessage());
           System.exit(1);
       }

       // no sound gets made before this call
       line.start();
   }


   /**
   * Close standard audio.
   */
   public static void close() {
       line.drain();
       line.stop();
   }

   /**
   * Write one sample (between -1.0 and +1.0) to standard audio. If the sample
   * is outside the range, it will be clipped.
   */
   public static void play(double in) {

       // clip if outside [-1, +1]
       if (in < -1.0) in = -1.0;
       if (in > +1.0) in = +1.0;

       // convert to bytes
       short s = (short) (MAX_16_BIT * in);
       buffer[bufferSize++] = (byte) s;
       buffer[bufferSize++] = (byte) (s >> 8); // little Endian

       // send to sound card if buffer is full
       if (bufferSize >= buffer.length) {
           line.write(buffer, 0, buffer.length);
           bufferSize = 0;
       }
   }

   /**
   * Write an array of samples (between -1.0 and +1.0) to standard audio. If a sample
   * is outside the range, it will be clipped.
   */
   public static void play(double[] input) {
       for (int i = 0; i < input.length; i++) {
           play(input[i]);
       }
   }

   /**
   * Read audio samples from a file (in .wav or .au format) and return them as a double array
   * with values between -1.0 and +1.0.
   */
   public static double[] read(String filename) {
       byte[] data = readByte(filename);
       int N = data.length;
       double[] d = new double[N/2];
       for (int i = 0; i < N/2; i++) {
           d[i] = ((short) (((data[2*i+1] & 0xFF) << 8) + (data[2*i] & 0xFF))) / (MAX_16_BIT);
       }
       return d;
   }


   /**
   * Play a sound file (in .wav, .mid, or .au format) in a background thread.
   */
   public static void play(String filename) {
       URL url = null;
       try {
           File file = new File(filename);
           if (file.canRead()) url = file.toURI().toURL();
       }
       catch (MalformedURLException e) { e.printStackTrace(); }
       // URL url = StdAudio.class.getResource(filename);
       if (url == null) throw new RuntimeException("audio " + filename + " not found");
       AudioClip clip = Applet.newAudioClip(url);
       clip.play();
   }

   /**
   * Loop a sound file (in .wav, .mid, or .au format) in a background thread.
   */
   public static void loop(String filename) {
       URL url = null;
       try {
           File file = new File(filename);
           if (file.canRead()) url = file.toURI().toURL();
       }
       catch (MalformedURLException e) { e.printStackTrace(); }
       // URL url = StdAudio.class.getResource(filename);
       if (url == null) throw new RuntimeException("audio " + filename + " not found");
       AudioClip clip = Applet.newAudioClip(url);
       clip.loop();
   }


   // return data as a byte array
   private static byte[] readByte(String filename) {
       byte[] data = null;
       AudioInputStream ais = null;
       try {

           // try to read from file
           File file = new File(filename);
           if (file.exists()) {
               ais = AudioSystem.getAudioInputStream(file);
               data = new byte[ais.available()];
               ais.read(data);
           }

           // try to read from URL
           else {
               URL url = StdAudio.class.getResource(filename);
               ais = AudioSystem.getAudioInputStream(url);
               data = new byte[ais.available()];
               ais.read(data);
           }
       }
       catch (Exception e) {
           System.out.println(e.getMessage());
           throw new RuntimeException("Could not read " + filename);
       }

       return data;
   }

   /**
   * Save the double array as a sound file (using .wav or .au format).
   */
   public static void save(String filename, double[] input) {

       // assumes 44,100 samples per second
       // use 16-bit audio, mono, signed PCM, little Endian
       AudioFormat format = new AudioFormat(SAMPLE_RATE, 16, 1, true, false);
       byte[] data = new byte[2 * input.length];
       for (int i = 0; i < input.length; i++) {
           int temp = (short) (input[i] * MAX_16_BIT);
           data[2*i + 0] = (byte) temp;
           data[2*i + 1] = (byte) (temp >> 8);
       }

       // now save the file
       try {
           ByteArrayInputStream bais = new ByteArrayInputStream(data);
           AudioInputStream ais = new AudioInputStream(bais, format, input.length);
           if (filename.endsWith(".wav") || filename.endsWith(".WAV")) {
               AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File(filename));
           }
           else if (filename.endsWith(".au") || filename.endsWith(".AU")) {
               AudioSystem.write(ais, AudioFileFormat.Type.AU, new File(filename));
           }
           else {
               throw new RuntimeException("File format not supported: " + filename);
           }
       }
       catch (Exception e) {
           System.out.println(e);
           System.exit(1);
       }
   }


   /* *********************************************************************
   * sample test client
   ***********************************************************************/

   // create a note (sine wave) of the given frequency (Hz), for the given
   // duration (seconds) scaled to the given volume (amplitude)
   private static double[] note(double hz, double duration, double amplitude) {
       int N = (int) (StdAudio.SAMPLE_RATE * duration);
       double[] a = new double[N+1];
       for (int i = 0; i <= N; i++)
           a[i] = amplitude * Math.sin(2 * Math.PI * i * hz / StdAudio.SAMPLE_RATE);
       return a;
   }

   /**
   * Test client - play an A major scale to standard audio.
   */
   public static void main(String[] args) {

       // 440 Hz for 1 sec
       double freq = 440.0;
       for (int i = 0; i <= StdAudio.SAMPLE_RATE; i++) {
           StdAudio.play(0.5 * Math.sin(2*Math.PI * freq * i / StdAudio.SAMPLE_RATE));
       }

       // scale increments
       int[] steps = { 0, 2, 4, 5, 7, 9, 11, 12 };
       for (int i = 0; i < steps.length; i++) {
           double hz = 440.0 * Math.pow(2, steps[i] / 12.0);
           StdAudio.play(note(hz, 1.0, 0.5));
       }


       // need to call this in non-interactive stuff so the program doesn't terminate
       // until all the sound leaves the speaker.
       StdAudio.close();

       // need to terminate a Java program with sound
       System.exit(0);
   }
}

Explanation / Answer

import java.applet.*;
import java.io.*;
import java.net.*;
import javax.sound.sampled.*;

/**
* <i>Standard audio</i>. This class provides a basic capability for
* creating, reading, and saving audio.
* <p>
* The audio format uses a sampling rate of 44,100 (CD quality audio), 16-bit, monaural.
*
* <p>
* For additional documentation, see <a href="http://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
* <i>Introduction to Programming in Java: An Interdisciplinary Approach</i> by Robert Sedgewick and Kevin Wayne.
*/
public final class StdAudio {

   /**
   * The sample rate - 44,100 Hz for CD quality audio.
   */
   public static final int SAMPLE_RATE = 44100;

   private static final int BYTES_PER_SAMPLE = 2; // 16-bit audio
   private static final int BITS_PER_SAMPLE = 16; // 16-bit audio
   private static final double MAX_16_BIT = Short.MAX_VALUE; // 32,767
   private static final int SAMPLE_BUFFER_SIZE = 4096;


   private static SourceDataLine line; // to play the sound
   private static byte[] buffer; // our internal buffer
   private static int bufferSize = 0; // number of samples currently in internal buffer

   // do not instantiate
   private StdAudio() { }


   // static initializer
   static { init(); }

   // open up an audio stream
   private static void init() {
       try {
           // 44,100 samples per second, 16-bit audio, mono, signed PCM, little Endian
           AudioFormat format = new AudioFormat(SAMPLE_RATE, BITS_PER_SAMPLE, 1, true, false);
           DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

           line = (SourceDataLine) AudioSystem.getLine(info);
           line.open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE);

           // the internal buffer is a fraction of the actual buffer size, this choice is arbitrary
           // it gets divided because we can't expect the buffered data to line up exactly with when
           // the sound card decides to push out its samples.
           buffer = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE/3];
       } catch (Exception e) {
           System.out.println(e.getMessage());
           System.exit(1);
       }

       // no sound gets made before this call
       line.start();
   }


   /**
   * Close standard audio.
   */
   public static void close() {
       line.drain();
       line.stop();
   }

   /**
   * Write one sample (between -1.0 and +1.0) to standard audio. If the sample
   * is outside the range, it will be clipped.
   */
   public static void play(double in) {

       // clip if outside [-1, +1]
       if (in < -1.0) in = -1.0;
       if (in > +1.0) in = +1.0;

       // convert to bytes
       short s = (short) (MAX_16_BIT * in);
       buffer[bufferSize++] = (byte) s;
       buffer[bufferSize++] = (byte) (s >> 8); // little Endian

       // send to sound card if buffer is full
       if (bufferSize >= buffer.length) {
           line.write(buffer, 0, buffer.length);
           bufferSize = 0;
       }
   }

   /**
   * Write an array of samples (between -1.0 and +1.0) to standard audio. If a sample
   * is outside the range, it will be clipped.
   */
   public static void play(double[] input) {
       for (int i = 0; i < input.length; i++) {
           play(input[i]);
       }
   }

   /**
   * Read audio samples from a file (in .wav or .au format) and return them as a double array
   * with values between -1.0 and +1.0.
   */
   public static double[] read(String filename) {
       byte[] data = readByte(filename);
       int N = data.length;
       double[] d = new double[N/2];
       for (int i = 0; i < N/2; i++) {
           d[i] = ((short) (((data[2*i+1] & 0xFF) << 8) + (data[2*i] & 0xFF))) / (MAX_16_BIT);
       }
       return d;
   }


   /**
   * Play a sound file (in .wav, .mid, or .au format) in a background thread.
   */
   public static void play(String filename) {
       URL url = null;
       try {
           File file = new File(filename);
           if (file.canRead()) url = file.toURI().toURL();
       }
       catch (MalformedURLException e) { e.printStackTrace(); }
       // URL url = StdAudio.class.getResource(filename);
       if (url == null) throw new RuntimeException("audio " + filename + " not found");
       AudioClip clip = Applet.newAudioClip(url);
       clip.play();
   }

   /**
   * Loop a sound file (in .wav, .mid, or .au format) in a background thread.
   */
   public static void loop(String filename) {
       URL url = null;
       try {
           File file = new File(filename);
           if (file.canRead()) url = file.toURI().toURL();
       }
       catch (MalformedURLException e) { e.printStackTrace(); }
       // URL url = StdAudio.class.getResource(filename);
       if (url == null) throw new RuntimeException("audio " + filename + " not found");
       AudioClip clip = Applet.newAudioClip(url);
       clip.loop();
   }


   // return data as a byte array
   private static byte[] readByte(String filename) {
       byte[] data = null;
       AudioInputStream ais = null;
       try {

           // try to read from file
           File file = new File(filename);
           if (file.exists()) {
               ais = AudioSystem.getAudioInputStream(file);
               data = new byte[ais.available()];
               ais.read(data);
           }

           // try to read from URL
           else {
               URL url = StdAudio.class.getResource(filename);
               ais = AudioSystem.getAudioInputStream(url);
               data = new byte[ais.available()];
               ais.read(data);
           }
       }
       catch (Exception e) {
           System.out.println(e.getMessage());
           throw new RuntimeException("Could not read " + filename);
       }

       return data;
   }

   /**
   * Save the double array as a sound file (using .wav or .au format).
   */
   public static void save(String filename, double[] input) {

       // assumes 44,100 samples per second
       // use 16-bit audio, mono, signed PCM, little Endian
       AudioFormat format = new AudioFormat(SAMPLE_RATE, 16, 1, true, false);
       byte[] data = new byte[2 * input.length];
       for (int i = 0; i < input.length; i++) {
           int temp = (short) (input[i] * MAX_16_BIT);
           data[2*i + 0] = (byte) temp;
           data[2*i + 1] = (byte) (temp >> 8);
       }

       // now save the file
       try {
           ByteArrayInputStream bais = new ByteArrayInputStream(data);
           AudioInputStream ais = new AudioInputStream(bais, format, input.length);
           if (filename.endsWith(".wav") || filename.endsWith(".WAV")) {
               AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File(filename));
           }
           else if (filename.endsWith(".au") || filename.endsWith(".AU")) {
               AudioSystem.write(ais, AudioFileFormat.Type.AU, new File(filename));
           }
           else {
               throw new RuntimeException("File format not supported: " + filename);
           }
       }
       catch (Exception e) {
           System.out.println(e);
           System.exit(1);
       }
   }


   /* *********************************************************************
   * sample test client
   ***********************************************************************/

   // create a note (sine wave) of the given frequency (Hz), for the given
   // duration (seconds) scaled to the given volume (amplitude)
   private static double[] note(double hz, double duration, double amplitude) {
       int N = (int) (StdAudio.SAMPLE_RATE * duration);
       double[] a = new double[N+1];
       for (int i = 0; i <= N; i++)
           a[i] = amplitude * Math.sin(2 * Math.PI * i * hz / StdAudio.SAMPLE_RATE);
       return a;
   }

   /**
   * Test client - play an A major scale to standard audio.
   */
   public static void main(String[] args) {

       // 440 Hz for 1 sec
       double freq = 440.0;
       for (int i = 0; i <= StdAudio.SAMPLE_RATE; i++) {
           StdAudio.play(0.5 * Math.sin(2*Math.PI * freq * i / StdAudio.SAMPLE_RATE));
       }

       // scale increments
       int[] steps = { 0, 2, 4, 5, 7, 9, 11, 12 };
       for (int i = 0; i < steps.length; i++) {
           double hz = 440.0 * Math.pow(2, steps[i] / 12.0);
           StdAudio.play(note(hz, 1.0, 0.5));
       }


       // need to call this in non-interactive stuff so the program doesn't terminate
       // until all the sound leaves the speaker.
       StdAudio.close();

       // need to terminate a Java program with sound
       System.exit(0);
   }
}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote