The answer to the untrustworthy Thread.sleep () is incorrect: you cannot count on the fact that it will return exactly as much time that you specified. In fact, I'm pretty surprised that your metronome can be used at all, especially when your system is under load. Read the docs for Thread.sleep () for more details. Max Beikirch's answer about MIDI is a good suggestion: MIDI controls timing very well.
But you ask how to do this with sound. The trick is to open the audio stream and fill it with silence between the clicks of the metronome and paste the clicks of the metronome where you want. When you do this, your sound card plays samples (regardless of whether they contain a click or silence) at a constant speed. The key here is to turn off the audio stream and not close it. Thus, a clock is an audio equipment, not a system clock — a subtle but important difference.
So, let's say you generate 16-bit monophonic samples with a frequency of 44100 Hz. Here is a function that will create a click sound at the desired speed. Keep in mind that this click sound is bad for the speakers (and your ears), so if you actually use it, play it at low volume. (Also, this code is not verified - it just demonstrates the concept)
int interval = 44100; // 1 beat per second, by default int count = 0; void setBPM( float bpm ) { interval = ( bpm / 60 ) * 44100 ; } void generateMetronomeSamples( short[] s ) { for( int i=0; i<s.length; ++i ) { s = 0; ++count; if( count == 0 ) { s = Short.MAX_VALUE; } if( count == interval ) { count = 0; } } }
Once you set the tempo using setBPM, you can play the samples generated by calling the generateMetronomeSamples () function again and stream the streams output to your speakers using JavaSound. (see JSResources.org for a good tutorial)
Once you get started, you can replace the sharp click with the sound you get from WAV or AIFF, or a short tone or something else.
source share