Long time I was not able to write a precise metronome (a tool for musicians). Playing the beats with SoundPool and a Timer was not accurate at all, because of the timer. Even playing in a own thread was not really precise. Finally I got now a 100% precise solution with the AudioTrack Library. For this code you also need the Threading and the ByteConverter Lib.
The metrum means beats per minute, so the milliseconds you get with 60000 / metrum. With a Sub "BeatShow" you can also show the beat in the UI.
The code writes the beats and the silence between it directly to the soundstream.
B4X:
Sub Process_Globals
Private i_Milliseconds As Int = 500
Private ConverterByte As ByteConverter
Private at_Sound As AudioTrack
Private b_Sounddata(), b_SoundQuietData(200000) As Byte
Private SoundThread As Thread
End Sub
Sub Activity_Create(FirstTime As Boolean)
'The Beatsound should be a short mono Wavefile with normal 16 Bit and Samplerate 44.100
Dim allbytes() As Byte = File.ReadBytes(File.DirAssets, "t2.wav")
Dim iFirstByte As Int = 44 'first byte after wave-header
Dim iAnzBytes As Int = allbytes.Length - iFirstByte
Dim sounddata(iAnzBytes) As Byte
ConverterByte.ArrayCopy(allbytes, iFirstByte, sounddata, 0, iAnzBytes)
b_Sounddata = sounddata
at_Sound.Initialize(at_Sound.Stream_Music, 44100, at_Sound.CH_CONF_MONO, at_Sound.AF_PCM_16, 4410, at_Sound.Mode_Stream)
at_Sound.Play
SoundThread.Start(Me, "SoundThreadSub", Null)
End Sub
Sub SoundThreadSub
Do While i_Milliseconds > 0
'SoundThread.RunOnGuiThread("BeatShow", Null)
Dim iSilinceLen As Int = i_Milliseconds * 2 * 44.1 - b_Sounddata.Length
at_Sound.WriteByte(b_SoundQuietData, 0, iSilinceLen)
at_Sound.WriteByte(b_Sounddata, 0, b_Sounddata.Length)
Loop
End Sub
The metrum means beats per minute, so the milliseconds you get with 60000 / metrum. With a Sub "BeatShow" you can also show the beat in the UI.
The code writes the beats and the silence between it directly to the soundstream.
Last edited: