I'm developing a sort of music production app, which includes audio playback. I'm currently running into a problem where the playback is not consistent. The timer I use to progress through beats seems to skip or lag on some tick events. You can hear the pauses in the sample video: Video
I implement the timer and its event like so
private void Method()
{
///some other code here
//the math for the timer period is to figure out how many times the timer should tick in 1 minute.
int _period = (int)Math.Round(60000f / (float)NUD_ConfigBPM.Value, MidpointRounding.AwayFromZero)
_threadtimer = new System.Threading.Timer(_ => _threadtimer_Tick(), null, 0, _period);
}
private void _threadtimer_Tick()
{
//vorbis is a List<List<CachedSound>>
//each beat can have several sounds to play at once
foreach (var _sample in vorbis[_playbackbeat]) {
AudioPlaybackEngine.Instance.PlaySound(_sample);
}
//simulating a playhead by highlighting cells of the DataGridView
try {
trackEditor.ClearSelection();
trackEditor.Columns[_playbackbeat - 8].Selected = true;
} catch { }
_playbackbeat++;
//once playback has reached the end of the file, stop it.
if (_playbackbeat >= vorbis.Count) {
_threadtimer.Dispose();
_playing = false;
btnTrackPlayback.ForeColor = Color.Green;
btnTrackPlayback.Image = Properties.Resources.icon_play;
trackEditor.SelectionMode = DataGridViewSelectionMode.CellSelect;
}
}
AudioPlaybackEngine.Instance.PlaySound()
is implemented from this NAudio article "Fire and Forget"
The Underlying Question
Where are these pauses coming from, and are there better timers or methods I could be using to solve this? The entire issue goes away at slower BPM (slower timer tick period).
Instead of a timer problem, could it be an NAudio problem, and the AudioPlaybackEngine is creating the delays?
More Info
I timed the spacing between every tick at 360BPM (_period
is 167). Every tick was consistent in spacing (give or take a couple ms). Even for the beats with large audio delays, the tick event was on time.
I have tried using Multimedia
timer, and the various high resolution timers in this thread. AccurateTimer
and PrecisionRepeatActionOnIntervalAsync
and returned the same result.
I also changed _playbacktimer_Tick()
to be async, and got the same result.