So I have tried the obvious, which is to simply print the current beat without success.
Printing the current beat before or after writing to the audio buffer resulted
the current beat not to change in sync with the sound.
However, thinking a little bit about it, it seemed pretty reasonable because each
time I wrote to the audio buffer I wasn’t writing a single tick but instead a
group of ticks and gaps(silence).
So, the first thing I did was to write only a pair of tick and gap each time to the audio buffer.
Here is the updated code:
public void calcSilence() {
silence = (int) (((60/bpm)*8000)-tick);
// I am calculating audio buffers that contain
// a tick and a silence gap
soundArray = new double[this.tick+this.silence];
msg = new Message();
msg.obj = ""+currentBeat;
}
public void play() {
calcSilence();
double[] tick = audioGenerator.getSineWave(this.tick, 8000
,beatSound);
double[] tock = audioGenerator.getSineWave(this.tick, 8000
,sound);
double silence = 0;
int t = 0,s = 0,b = 0;
do {
for(int i=0;i<soundArray.length&&play;i++) {
if(t<this.tick) {
if(b == 0)
soundArray[i] = tock[t];
else
soundArray[i] = tick[t];
t++;
} else {
soundArray[i] = silence;
s++;
if(s >= this.silence) {
t = 0;
s = 0;
b++;
if(b > (this.beat-1))
b = 0;
}
}
}
msg = new Message();
msg.obj = ""+currentBeat;
// write the current beat right before or after
// writing to the audio buffer
if(bpm < 100)
mHandler.sendMessage(msg);
audioGenerator.writeSound(soundArray);
if(bpm >= 100)
mHandler.sendMessage(msg);
currentBeat++;
if(currentBeat > beat)
currentBeat = 1;
} while(play);
}
As you can see the trick is to calculate the buffer size each time the
beats per minute (bpm) change.
Some times I am printing the current beat number before writing to the audio
buffer and some times after, because the bpm is low or high and the user
has to see the current beat as he is listening to the sound. Doing otherwise
would give a false sense to the user about the number of the current beat.
The number of 100 bpm that I am using to decide whether to print before or
after was picked after some experimentation.
Here is a pic about this in action:
Current beat is the third value.
I have updated BeatKeeper repo so full code about this can be found
here.
The metronome visualization that I have implemented is very simple. If one
implements another one, more eye candy, feel free to leave a comment about it.