Skip to content

Commit

Permalink
Update to use us instead of ms, adjust tempo
Browse files Browse the repository at this point in the history
  • Loading branch information
rfomin committed Oct 29, 2023
1 parent 5c579f6 commit 1ded4d0
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 27 deletions.
34 changes: 21 additions & 13 deletions prboom2/src/MUSIC/opl.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,21 @@ typedef struct
unsigned int rate; // Number of times the timer is advanced per sec.
unsigned int enabled; // Non-zero if timer is enabled.
unsigned int value; // Last value that was set.
unsigned int expire_time; // Calculated time that timer will expire.
uint64_t expire_time; // Calculated time that timer will expire.
} opl_timer_t;

// Queue of callbacks waiting to be invoked.
static opl_callback_queue_t *callback_queue;

// Current time, in number of samples since startup:
static unsigned int current_time;
// Current time, in us since startup:
static uint64_t current_time;

// If non-zero, playback is currently paused.
static int opl_paused;

// Time offset (in samples) due to the fact that callbacks
// Time offset (in us) due to the fact that callbacks
// were previously paused.
static unsigned int pause_offset;
static uint64_t pause_offset;

// OPL software emulator structure.
static opl3_chip opl_chip;
Expand Down Expand Up @@ -108,12 +108,12 @@ void OPL_Shutdown(void)
}
}

void OPL_SetCallback(unsigned int ms,
void OPL_SetCallback(uint64_t us,
opl_callback_t callback,
void *data)
{
OPL_Queue_Push(callback_queue, callback, data,
current_time - pause_offset + (ms * opl_sample_rate) / 1000);
current_time - pause_offset + us);
}

void OPL_ClearCallbacks(void)
Expand All @@ -131,7 +131,7 @@ static void OPLTimer_CalculateEndTime(opl_timer_t *timer)
{
tics = 0x100 - timer->value;
timer->expire_time = current_time
+ (tics * opl_sample_rate) / timer->rate;
+ ((uint64_t) tics * OPL_SECOND) / timer->rate;
}
}

Expand Down Expand Up @@ -185,13 +185,15 @@ static void OPL_AdvanceTime(unsigned int nsamples)
{
opl_callback_t callback;
void *callback_data;
uint64_t us;

// Advance time.
current_time += nsamples;
us = ((uint64_t) nsamples * OPL_SECOND) / opl_sample_rate;
current_time += us;

if (opl_paused)
{
pause_offset += nsamples;
pause_offset += us;
}

// Are there callbacks to invoke now? Keep invoking them
Expand All @@ -209,6 +211,11 @@ static void OPL_AdvanceTime(unsigned int nsamples)
}
}

void OPL_AdjustCallbacks(float factor)
{
OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor);
}

void OPL_Render_Samples (void *dest, unsigned buffer_len)
{
unsigned int filled = 0;
Expand All @@ -218,8 +225,8 @@ void OPL_Render_Samples (void *dest, unsigned buffer_len)
// full.
while (filled < buffer_len)
{
unsigned int next_callback_time;
unsigned int nsamples;
uint64_t next_callback_time;
uint64_t nsamples;

// Work out the time until the next callback waiting in
// the callback queue must be invoked. We can then fill the
Expand All @@ -232,7 +239,8 @@ void OPL_Render_Samples (void *dest, unsigned buffer_len)
{
next_callback_time = OPL_Queue_Peek(callback_queue) + pause_offset;

nsamples = next_callback_time - current_time;
nsamples = (next_callback_time - current_time) * opl_sample_rate;
nsamples = (nsamples + OPL_SECOND - 1) / OPL_SECOND;

if (nsamples > buffer_len - filled)
{
Expand Down
4 changes: 3 additions & 1 deletion prboom2/src/MUSIC/opl.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@ extern unsigned int opl_sample_rate;
void OPL_Render_Samples (void *dest, unsigned nsamp);


void OPL_SetCallback(unsigned int ms, opl_callback_t callback, void *data);
void OPL_SetCallback(uint64_t us, opl_callback_t callback, void *data);

void OPL_ClearCallbacks(void);

void OPL_AdjustCallbacks(float tempo);

#endif
21 changes: 17 additions & 4 deletions prboom2/src/MUSIC/opl_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ typedef struct
{
opl_callback_t callback;
void *data;
unsigned int time;
uint64_t time;
} opl_queue_entry_t;

struct opl_callback_queue_s
{
opl_queue_entry_t entries[MAX_OPL_QUEUE];
int num_entries;
unsigned int num_entries;
};

opl_callback_queue_t *OPL_Queue_Create(void)
Expand Down Expand Up @@ -72,7 +72,7 @@ void OPL_Queue_Clear(opl_callback_queue_t *queue)

void OPL_Queue_Push(opl_callback_queue_t *queue,
opl_callback_t callback, void *data,
unsigned int time)
uint64_t time)
{
int entry_id;
int parent_id;
Expand Down Expand Up @@ -197,7 +197,7 @@ int OPL_Queue_Pop(opl_callback_queue_t *queue,
return 1;
}

unsigned int OPL_Queue_Peek(opl_callback_queue_t *queue)
uint64_t OPL_Queue_Peek(opl_callback_queue_t *queue)
{
if (queue->num_entries > 0)
{
Expand All @@ -209,6 +209,19 @@ unsigned int OPL_Queue_Peek(opl_callback_queue_t *queue)
}
}

void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue,
uint64_t time, float factor)
{
int64_t offset;
int i;

for (i = 0; i < queue->num_entries; ++i)
{
offset = queue->entries[i].time - time;
queue->entries[i].time = time + (uint64_t) (offset / factor);
}
}

#ifdef TEST

#include <assert.h>
Expand Down
6 changes: 4 additions & 2 deletions prboom2/src/MUSIC/opl_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ void OPL_Queue_Clear(opl_callback_queue_t *queue);
void OPL_Queue_Destroy(opl_callback_queue_t *queue);
void OPL_Queue_Push(opl_callback_queue_t *queue,
opl_callback_t callback, void *data,
unsigned int time);
uint64_t time);
int OPL_Queue_Pop(opl_callback_queue_t *queue,
opl_callback_t *callback, void **data);
unsigned int OPL_Queue_Peek(opl_callback_queue_t *queue);
uint64_t OPL_Queue_Peek(opl_callback_queue_t *queue);
void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue,
uint64_t time, float factor);

#endif /* #ifndef OPL_QUEUE_H */
14 changes: 7 additions & 7 deletions prboom2/src/MUSIC/oplplayer.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ static dboolean song_looping;
// Tempo control variables

static unsigned int ticks_per_beat;
static unsigned int ms_per_beat;
static unsigned int us_per_beat;

// If true, OPL sound channels are reversed to their correct arrangement
// (as intended by the MIDI standard) rather than the backwards one
Expand Down Expand Up @@ -1276,8 +1276,8 @@ static void PitchBendEvent(opl_track_data_t *track, midi_event_t *event)

static void MetaSetTempo(unsigned int tempo)
{
// OPL_AdjustCallbacks((float) us_per_beat / tempo);
// us_per_beat = tempo;
OPL_AdjustCallbacks((float) us_per_beat / tempo);
us_per_beat = tempo;
}

// Process a meta event.
Expand Down Expand Up @@ -1445,17 +1445,17 @@ static void TrackTimerCallback(void *arg)
static void ScheduleTrack(opl_track_data_t *track)
{
unsigned int nticks;
unsigned int ms;
uint64_t us;

// Get the number of milliseconds until the next event.

nticks = MIDI_GetDeltaTime(track->iter);
ms = (nticks * ms_per_beat) / ticks_per_beat;
us = ((uint64_t) nticks * us_per_beat) / ticks_per_beat;

// Set a timer to be invoked when the next event is
// ready to play.

OPL_SetCallback(ms, TrackTimerCallback, track);
OPL_SetCallback(us, TrackTimerCallback, track);
}

// Initialize a channel.
Expand Down Expand Up @@ -1520,7 +1520,7 @@ static void I_OPL_PlaySong(const void *handle, int looping)
// Default is 120 bpm.
// TODO: this is wrong

ms_per_beat = 500;
us_per_beat = 500 * 1000;

start_music_volume = current_music_volume = snd_MusicVolume * 127 / 15;

Expand Down

0 comments on commit 1ded4d0

Please sign in to comment.