• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Is there a way to produce sound with Java?

 
Ranch Hand
Posts: 249
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm in the beginning stages of writing an educational game in Java. I'd like to write the game with the capability of generating noises at different points in the game, maybe a short little melody as a response to a player getting something right, and a long bleep as a response to a player getting something wrong. Up to three players can play, so it would be nice if I could get the melody and bleep to occur at different tones, say the first player at one tone, the second player at a half an octave higher, and the third player half an octave still higher. Is there any way to do that in Java?
 
Marshal
Posts: 79979
397
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Of course there is. Start by looking through the Java™ Tutorials.
 
Sheriff
Posts: 17713
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have found the Princeton utlity library useful. http://introcs.cs.princeton.edu/java/stdlib/

I used the StdAudio and Tone classes to add sound to a Morse code program I wrote earlier this year.
 
Junilu Lacar
Sheriff
Posts: 17713
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
See also this page for frequencies of various musical notes http://www.intmath.com/trigonometric-graphs/music.php
 
Campbell Ritchie
Marshal
Posts: 79979
397
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I like the explanation of equal temperament in that link. J S Bach knew about it and wrote the Tempered Keyboards (German das Wohltemperirte Clavier) to exploit it by using all twenty‑four keys.
 
Ranch Hand
Posts: 171
Hibernate Spring Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Something to play with is here as well -
http://alvinalexander.com/java/java-audio-example-java-au-play-sound
 
Kevin Simonson
Ranch Hand
Posts: 249
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Of course there is. Start by looking through the Java™ Tutorials.


I followed that link, and have been reading page after page about MIDI, channels, instruments, voices, lines, synthesizers, sequencers, etc., etc., and it's driving me crazy. I just want to know how to write some Java code that produces a little melody of just four notes, at three different pitches. Can anyone tell me where in the Java Tutorials it talks about code that produces just a short melody? I don't want to capture the melody and reproduce it; I just want to generate the melody so the user can hear it. Can anybody help me? Are there key words in the Java Tutorial for doing that that I can use to scan through the pages for the Java Tutorial and get the information I need?
 
Saloon Keeper
Posts: 15731
368
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
A melody is basically a Track containing a MidiEvent for each note that starts playing, and one for each note that stops playing.

When you've added all notes to a Track of a Sequence, you should hook up a Sequencer to an output device, and let it start the sequence.
 
Kevin Simonson
Ranch Hand
Posts: 249
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:A melody is basically a Track containing a MidiEvent for each note that starts playing, and one for each note that stops playing.

When you've added all notes to a Track of a Sequence, you should hook up a Sequencer to an output device, and let it start the sequence.


Okay, now as I understand it there are twelve notes in an octave, namely A, A#, B, C, C#, D, D#, E, F, F#, G, and G#. (Correct me if I'm wrong.) Let's say I want a melody consisting of five notes, each lasting .2 seconds, namely C, followed by D, followed by C, followed by B, followed by C. It sounds like what you're saying is that I need to create a {MidiEvent} for each of those five notes. The only constructor for {MidiEvent} takes two arguments, a {MidiMessage} and a {long}. What {MidiMessage} and {long} do I create a {MidiEvent} with to get a C note that lasts .2 seconds?
 
Stephan van Hulst
Saloon Keeper
Posts: 15731
368
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I would first create classes that represent keys, notes, times, fractions and melodies, before you convert them to MidiEvents. For instance, this is what a Note could look like:

And a Melody like this:

This should give you enough of an idea. I wrote this without a compiler, so it may contain errors, and you'll have to add some missing classes (Key and Fraction) and add exception declarations.
 
Stephan van Hulst
Saloon Keeper
Posts: 15731
368
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You could create your melody like this:
 
Kevin Simonson
Ranch Hand
Posts: 249
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:You could create your melody like this:


I translated that to:

What imports do I need to make to get this to compile? In other words, where are {Fraction}, {Note}, {Key}, and {Melody} located? I couldn't find them in "https://docs.oracle.com/javase/8/docs/api". Are they part of Java 9?
 
Saloon Keeper
Posts: 10930
87
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Kevin Simonson wrote:What imports do I need to make to get this to compile? In other words, where are {Fraction}, {Note}, {Key}, and {Melody} located? I couldn't find them in "https://docs.oracle.com/javase/8/docs/api". Are they part of Java 9?


See Stephan's other post.
 
Kevin Simonson
Ranch Hand
Posts: 249
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:I would first create classes that represent keys, notes, times, fractions and melodies, before you convert them to MidiEvents. For instance, this is what a Note could look like:
..........snip..........

This should give you enough of an idea. I wrote this without a compiler, so it may contain errors, and you'll have to add some missing classes (Key and Fraction) and add exception declarations.


The only thing these files tell me about class {Fraction} is that it has an {atTicks()} method that takes as parameters an {int} and a {Fraction}. What exactly does {atTicks()} do? Is it a simple multiplication?
 
Kevin Simonson
Ranch Hand
Posts: 249
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Kevin Simonson wrote:
The only thing these files tell me about class {Fraction} is that it has an {atTicks()} method that takes as parameters an {int} and a {Fraction}. What exactly does {atTicks()} do? Is it a simple multiplication?


Typo. Meant to say {asTicks()}.
 
Stephan van Hulst
Saloon Keeper
Posts: 15731
368
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That would be asTicks(int ticksPerQuarterNote). I made a mistake, you don't need the timeSignature parameter. asTicks() converts the duration of a note specified in fractions of a bar, to duration of a note specified in ticks, where a tick is a length of time that depends on the resolution of the sequence.

Imagine that you want to play a note for the duration of a quaver. That's 1/8 of a bar. Let's say that the resolution of the sequence is 96 ticks per quarter note. That means 1/4 of a bar contains 96 ticks. A single quaver would then be 48 ticks. If you want to play a minim, which is 1/2 of a bar, it would have to last for 192 ticks.

Why perform this conversion? MidiEvent uses ticks to specify the time of the event.

What else does Fraction have? For now, it just needs a numerator() and a denominator().
 
Kevin Simonson
Ranch Hand
Posts: 249
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:That would be asTicks(int ticksPerQuarterNote). I made a mistake, you don't need the timeSignature parameter. asTicks() converts the duration of a note specified in fractions of a bar, to duration of a note specified in ticks, where a tick is a length of time that depends on the resolution of the sequence.

Imagine that you want to play a note for the duration of a quaver. That's 1/8 of a bar. Let's say that the resolution of the sequence is 96 ticks per quarter note. That means 1/4 of a bar contains 96 ticks. A single quaver would then be 48 ticks. If you want to play a minim, which is 1/2 of a bar, it would have to last for 192 ticks.

Why perform this conversion? MidiEvent uses ticks to specify the time of the event.

What else does Fraction have? For now, it just needs a numerator() and a denominator().


Then I've decided that my "Fraction.java" will look like this:

How does that look? And then for "Key.java" I've got:

Should that do the trick?
 
Kevin Simonson
Ranch Hand
Posts: 249
2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Make that:

 
Stephan van Hulst
Saloon Keeper
Posts: 15731
368
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
  • Make your class final.
  • Make your fields private and final.
  • Normalize your fields in the constructor using BigInteger.gcd().
  • Your compareTo() method does not take overflow into account. You're better off using BigInteger instead of long.
  • If you make a class Comparable, you should override equals() and hashCode() as well.
  • Override the toString() method.
  • Key should start with C, otherwise the noteNumber() formula will not work. I would also write out the sharps:
  •  
    Saloon Keeper
    Posts: 28327
    210
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    OK, I'm late to the party and there's enough already written that I may have missed this part, but it looks like you're all giving advice on how to get Java to do MIDI sound. But this is a video game, so most likely that isn't what Kevin wants.

    MIDI is a digital control protocol. Originally, you'd have used it to play an external musical instrument like a synthesizer. These days, many OS's have internal MIDI client capabilities as well. But that would be overkill for the average videogame.

    The Java sound API also includes the ability to play digital sound samples. For a video game, you'd most commonly keep these samples in .wav files, although Java supports other formats as well.

    I don't have anything lying around handy right now, but basically you'd just load the file into RAM and tell the API to play it.

    You could also synthesize raw waveforms and play them, but it's easier to use pre-recorded samples.
     
    Carey Brown
    Saloon Keeper
    Posts: 10930
    87
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Tim Holloway wrote:OK, I'm late to the party and there's enough already written that I may have missed this part, but it looks like you're all giving advice on how to get Java to do MIDI sound. But this is a video game, so most likely that isn't what Kevin wants.

    MIDI is a digital control protocol. Originally, you'd have used it to play an external musical instrument like a synthesizer. These days, many OS's have internal MIDI client capabilities as well. But that would be overkill for the average videogame.

    The Java sound API also includes the ability to play digital sound samples. For a video game, you'd most commonly keep these samples in .wav files, although Java supports other formats as well.

    I don't have anything lying around handy right now, but basically you'd just load the file into RAM and tell the API to play it.

    You could also synthesize raw waveforms and play them, but it's easier to use pre-recorded samples.


    Agreed.
    If you are looking for royalty free sounds check out http://freesound.org/browse/
     
    Kevin Simonson
    Ranch Hand
    Posts: 249
    2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:

  • Make your class final.
  • Make your fields private and final.
  • Normalize your fields in the constructor using BigInteger.gcd().
  • Your compareTo() method does not take overflow into account. You're better off using BigInteger instead of long.
  • If you make a class Comparable, you should override equals() and hashCode() as well.
  • Override the toString() method.
  • Key should start with C, otherwise the noteNumber() formula will not work. I would also write out the sharps:

  • Okay, now I've got:

    and I've got:

    Does that look like it should work?
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15731
    368
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    It looks like you're doing a lot of juggling between long and BigInteger. Don't you think it's easier to just use BigInteger fields? Make them final while you're at it.

    Use the @Override annotation on equals(), hashCode(), toString() and compareTo(). You would have found that you're not overriding equals() correctly.

    You can implement equals() using compareTo(), and hashCode() using Objects.hash().

    Kevin Simonson wrote:Does that look like it should work?


    You should really write unit tests to test the correctness of your implementation.
     
    Kevin Simonson
    Ranch Hand
    Posts: 249
    2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:

    Kevin Simonson wrote:Does that look like it should work?


    You should really write unit tests to test the correctness of your implementation.


    Well, that's just the thing. For the code to be correct, it would need to actually sound a melody, and it doesn't. I modified "Stephan.java" like so:

    When I run "java Stephan", I get no sound at all. If I run "java Stephan r" I hear a couple of chimes, so I know the computer is capable of generating sound. But the {for} loop is generating no sound. What am I doing wrong? Am I leaving something out?
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15731
    368
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Yes, all this code does is convert notes to Midi events. The events still have to be sequenced and sent to a playback device.

    MidiSystem.getSequencer() returns the system's default sequencer, hooked up to a default playback device. Create a new Sequence, add your Melody to it as a Track, and use Sequencer.setSequence() and Sequencer.start() to sequence your Melody.
     
    Creator of Enthuware JWS+ V6
    Posts: 3412
    320
    Android Eclipse IDE Chrome
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Congratulations Kevin Simonson,

    Your question has made it to our Journal    

    Have a Cow!
     
    Kevin Simonson
    Ranch Hand
    Posts: 249
    2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:Yes, all this code does is convert notes to Midi events. The events still have to be sequenced and sent to a playback device.

    MidiSystem.getSequencer() returns the system's default sequencer, hooked up to a default playback device. Create a new Sequence, add your Melody to it as a Track, and use Sequencer.setSequence() and Sequencer.start() to sequence your Melody.


    Well, the only thing that creates {MidiEvent}s is {addAsTrackToSequence()}. Are you saying that after my program calls {melody.playNote()} five times, I can call {melody.addAsTrackToSequence()} and use that to make my melody sound?
     
    Kevin Simonson
    Ranch Hand
    Posts: 249
    2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:Yes, all this code does is convert notes to Midi events. The events still have to be sequenced and sent to a playback device.

    MidiSystem.getSequencer() returns the system's default sequencer, hooked up to a default playback device. Create a new Sequence, add your Melody to it as a Track, and use Sequencer.setSequence() and Sequencer.start() to sequence your Melody.


    There are two constructors that create {Sequence} objects, namely {Sequence ( float divisionType, int resolution)} and {Sequence ( float divisionType, int resolution, int numTracks)}. I'm guessing I want the first. What exactly do the {divisionType} and {resolution} arguments do, and can anybody give me any idea what values I'd want to set them to in order to generate my little melody?
     
    Kevin Simonson
    Ranch Hand
    Posts: 249
    2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:Create a new Sequence, add your Melody to it as a Track, and use Sequencer.setSequence() and Sequencer.start() to sequence your Melody.


    I know how to create a {Track} object. How do I add that {Track} object to my {Sequence} object? I don't see a {Sequence} method for doing that.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15731
    368
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Kevin Simonson wrote:Well, the only thing that creates {MidiEvent}s is {addAsTrackToSequence()}. Are you saying that after my program calls {melody.playNote()} five times, I can call {melody.addAsTrackToSequence()} and use that to make my melody sound?


    Yes, that method converts the notes to Midi events, and adds those Midi events to a track that it creates itself. The Track is already part of a Sequence.

    There are two constructors that create {Sequence} objects, namely {Sequence ( float divisionType, int resolution)} and {Sequence ( float divisionType, int resolution, int numTracks)}. I'm guessing I want the first. What exactly do the {divisionType} and {resolution} arguments do, and can anybody give me any idea what values I'd want to set them to in order to generate my little melody?


    Division type determines the units that the resolution is given in. The two main kinds are "pulses per quarter", which is used for tempo-based Midi, and "frame rate", which is mostly used when playing Midi for a video. Indeed, we're only interested in tempo-based Midi, so for divisionType you should use Sequence.PPQ.

    The resolution is exactly that: how precise you can time your Midi events. If you only have 2 pulses per quarter, you will only be able to time midi events at two different moments within a quarter. I believe 96 pulses per quarter is a fairly standard amount to use.

    I know how to create a {Track} object. How do I add that {Track} object to my {Sequence} object? I don't see a {Sequence} method for doing that.


    You don't have to. The addAsTrackToSequence() already does that. When it calls sequence.createTrack(), the track that is returned is already part of the sequence.
     
    Kevin Simonson
    Ranch Hand
    Posts: 249
    2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:

    Kevin Simonson wrote:Well, the only thing that creates {MidiEvent}s is {addAsTrackToSequence()}. Are you saying that after my program calls {melody.playNote()} five times, I can call {melody.addAsTrackToSequence()} and use that to make my melody sound?


    Yes, that method converts the notes to Midi events, and adds those Midi events to a track that it creates itself. The Track is already part of a Sequence.

    There are two constructors that create {Sequence} objects, namely {Sequence ( float divisionType, int resolution)} and {Sequence ( float divisionType, int resolution, int numTracks)}. I'm guessing I want the first. What exactly do the {divisionType} and {resolution} arguments do, and can anybody give me any idea what values I'd want to set them to in order to generate my little melody?


    Division type determines the units that the resolution is given in. The two main kinds are "pulses per quarter", which is used for tempo-based Midi, and "frame rate", which is mostly used when playing Midi for a video. Indeed, we're only interested in tempo-based Midi, so for divisionType you should use Sequence.PPQ.

    The resolution is exactly that: how precise you can time your Midi events. If you only have 2 pulses per quarter, you will only be able to time midi events at two different moments within a quarter. I believe 96 pulses per quarter is a fairly standard amount to use.

    I know how to create a {Track} object. How do I add that {Track} object to my {Sequence} object? I don't see a {Sequence} method for doing that.


    You don't have to. The addAsTrackToSequence() already does that. When it calls sequence.createTrack(), the track that is returned is already part of the sequence.


    Okay, I tried incorporating this and got:

    but when I ran it I got messages:

    D:\Langs\Java\Src\Comtutor\Stephan>j8 Stephan
    Jul 02, 2017 12:04:38 PM java.util.prefs.WindowsPreferences <init>
    WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
    Exception in thread "main" java.lang.IllegalStateException: sequencer not open
           at com.sun.media.sound.RealTimeSequencer.start(RealTimeSequencer.java:243)
           at Stephan.main(Stephan.java:29)

    D:\Langs\Java\Src\Comtutor\Stephan>

    It looks like I'm having trouble opening object {sequencer}. Anybody have any idea what I'm doing wrong?
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15731
    368
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    You're almost there! The exception tells you exactly what's wrong. Your sequencer hasn't been opened. So you should try to open it.

    Please note that Sequencer is AutoCloseable, so you should use it in a try-with-resources statement.

    addAsTrackToSequence() also doesn't need the timeSignature parameter, so remove it.
     
    Kevin Simonson
    Ranch Hand
    Posts: 249
    2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:You're almost there!


    I'm glad to hear that!

    Stephan van Hulst wrote:The exception tells you exactly what's wrong. Your sequencer hasn't been opened. So you should try to open it.

    Please note that Sequencer is AutoCloseable, so you should use it in a try-with-resources statement.

    addAsTrackToSequence() also doesn't need the timeSignature parameter, so remove it.


    Okay, so now I have:

    When I ran this I got messages:

    D:\Langs\Java\Src\Comtutor\Stephan>j8 Stephan
    Jul 03, 2017 10:26:47 AM java.util.prefs.WindowsPreferences <init>
    WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.

    D:\Langs\Java\Src\Comtutor\Stephan>

    So even explicitly opening my {Sequencer} object appears to fail to open that object. Any idea what I'm doing wrong?
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15731
    368
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Actually, everything is working fine. The sequencer is now open, and it's sequencing the music. The message you get is just a warning, you can disregard it.

    The final problem you're facing now is that music is sequenced and played asynchronously, and the program terminates before it has a chance to finish playing the music. You need to write some code that blocks until the music has stopped playing. For now, you can use Thread.sleep() after you've started the sequencer to listen if any music is being played. After you've made sure that it does, you can add a MetaEventListener to your sequencer to detect the end of the melody, and use Lock and Condition to block until you've detected the end.

    Note that you don't have to call sequencer.close(). Because you're using try-with-resources, the sequencer is automatically closes as soon as you leave the try statement.
     
    Kevin Simonson
    Ranch Hand
    Posts: 249
    2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:Actually, everything is working fine. The sequencer is now open, and it's sequencing the music. The message you get is just a warning, you can disregard it.

    The final problem you're facing now is that music is sequenced and played asynchronously, and the program terminates before it has a chance to finish playing the music. You need to write some code that blocks until the music has stopped playing. For now, you can use Thread.sleep() after you've started the sequencer to listen if any music is being played. After you've made sure that it does, you can add a MetaEventListener to your sequencer to detect the end of the melody, and use Lock and Condition to block until you've detected the end.

    Note that you don't have to call sequencer.close(). Because you're using try-with-resources, the sequencer is automatically closes as soon as you leave the try statement.


    Wonderful! I got it working the way everybody suggested I do it, but found it was executing too slowly, so I decreased {half} from 1/2 to 1/16, and that gave me:

    That sounded great. But I noticed that the first note seems to last twice as long as any of the other notes. Does anybody know why that might be the case? I'd like to get the melody to play with each note having the same brief duration.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15731
    368
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Kevin Simonson wrote:[...] I decreased {half} from 1/2 to 1/16 [...]


    You should change the variable name to reflect that it's no longer a minim, but a semi-quaver. Anyways, instead of changing the length of your notes, you can also change the tempo of your sequence using setTempoInBPM() or setTempoInMPQ().

    But I noticed that the first note seems to last twice as long as any of the other notes. Does anybody know why that might be the case?


    I'll see if I can debug your application tomorrow.
     
    Kevin Simonson
    Ranch Hand
    Posts: 249
    2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    After I got Stephan's code working, I decided I'd try to simplify it somewhat, and, in case you're interested, here's what I came up with:

    That last comment line is just a suggested list of arguments to call it with. Let me know what you think of this Java class.
     
    Carey Brown
    Saloon Keeper
    Posts: 10930
    87
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    What is an example of command line arguments that you're using?
    Edit: sorry I missed your comment at the end.
     
    Oh. Hi guys! Look at this tiny ad:
    Gift giving made easy with the permaculture playing cards
    https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
    reply
      Bookmark Topic Watch Topic
    • New Topic