THE RESULT OF THIS THREAD: This method gives you 10 ms resolution to ACTUAL MIXER PLAYBACK TIME. That is GOOD ENOUGH. (I’m making a music game, and it is spot on. Seriously, I stress tested it: It looks right on the beat.)
Code to synchronize audio through JOAL, because you can’t get this capability with javasound (because theres an unpredictable delay from javasound to mixer playback.
new Thread(new Runnable(){
public void run(){
while(true){
try {
Thread.sleep(1);
} catch (Exception e){ };
int[] values = new int[1];
al.alGetSourcei(sourceID, AL.AL_BYTE_OFFSET, values,0);
long temp_Position_MS = (int)(1000.0*(totalBytes-BUFFER_SIZE*2+values[0])/ numBytesPerSample/ numChannels / rate);
if (Position_MS == temp_Position_MS) //THIS IS OPTIONAL, ITS JUST SO THAT YOU NEVER "HIT THE SAME TIME" TWICE, because BYTE_OFFSET has 10 ms resolution, slower than our iteration.
Position_MS++;
else
Position_MS = temp_Position_MS;
}
}
}).start();
Somewhere deep in the stream code:
byte[] pcm = new byte[BUFFER_SIZE];
int size = 0;
try {
if ((size = oggDecoder.read(pcm)) <= 0)
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
totalBytes += size;
The tester code:
double gap = .096;
double bpm = 198.757763975155279;
for (int a = 0; a < 400; a++){ //This if a very bad way to do it :p I'll fix it soon.
if (audio.offOf((int)(1000*(gap+a*(60/bpm))))<20){
Trenderer.draw("BAM!", (int)myCharacter.getX(), (int)myCharacter.getY());
}
}
and
public long offOf(int target){
long returnee = Position_MS - target;
return returnee < 0?-returnee:returnee;
}