0

The premise is that I am inputting music notes and the program plays the according piano notes. The only issue is that the first note works, but the rest of the notes do not play. So, if I input "ABC," note A will play but notes B and C will not. Is it because the file is static?

public class SnapMusic {    

static File file = new File("");

static void setUp() {

    try {

    Clip clip = AudioSystem.getClip();
    clip.open(AudioSystem.getAudioInputStream(file));
    clip.start();
    Thread.sleep(clip.getMicrosecondLength());
         }

    catch (Exception e) {
        System.err.println(e.getMessage());
       }
   }

public static void main (String[] arrgs) {

    Scanner scan = new Scanner(System.in);
    String notes = scan.next();

    for (int i = 0; i < notes.length(); i++) {

        if (notes.charAt(i) == 'A') {
            file = new File("src/musictranslator/MidA.wav");
            setUp();
        }
        else if (notes.charAt(i) == 'B') {
            file = new File("src/musictranslator/MidB.wav");
            setUp(); 
        }

        else if (notes.charAt(i) == 'C') {
            file = new File("src/musictranslator/MidC.wav");
            setUp();
        }
        else if (notes.charAt(i) == 'D') {
            file = new File("src/musictranslator/MidD.wav");
            setUp();
        }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
luckyruby1
  • 51
  • 1
  • 8
  • 2
    Thread.sleep takes milliseconds, not microseconds – Benjamin Urquhart Apr 27 '19 at 00:02
  • Why dont you declare your self Static?? See if that works - i cant reduce your vote even further sorry about that – gpasch Apr 27 '19 at 02:58
  • I tried using milliseconds, but it does not recognize the function (unidentified) @BenjaminUrquhart – luckyruby1 Apr 28 '19 at 02:11
  • 1
    *"I tried using milliseconds, but it does not recognize the function (unidentified)"* Did you try dividing the returned value by 1000? BTW a tip: Add @BenjaminUrquhart (or whoever, the `@` is important) to *notify* the person of a new comment. – Andrew Thompson Apr 28 '19 at 02:35

1 Answers1

1

I recommend the standard debug technique of putting in System.out.println()'s to inspect the value in file prior to each setUp() call, to ensure that you are really getting to each call with a unique file value.

I'm guessing that you never reach the second iteration of the scan-parsing loop due to sleeping a huge amount of time. The value arising from clip.getMicrosecondLength() is going to be three orders of magnitude larger than the number of milliseconds, so you will need to divide it to get the number of milliseconds. But I don't do much file parsing and I haven't tested your code so ensuring the proper calls would be my first step to debugging this.

Lastly, to use Clips more correctly (down the road, I'm assuming this is just a test to get acquainted with Clips), may I suggest making an array called clips of all possible notes, and make the first part of your code load each of the clip files?

Then, when reading the file, call it with a value where the incoming String for the note name is translated to the corresponding clips[] array value. For example, if the "A" audio file is in clips[0], you'd call the following with "0" as the argument.

private void playClip(int idx)
{
    clips[idx].setFramePosition(0);
    clips[idx].play();
    Thread.sleep(clips[idx].getMicrosecondLength()/1000);
}

Clips were designed to be audio that is held in memory and reused. If you prefer to read from files, SourceDataLine is more efficient, as it will start playing as soon as it loads a buffer of data, where Clips won't start to play until the entire file is loaded.

Phil Freihofner
  • 7,645
  • 1
  • 20
  • 41