diff options
-rw-r--r-- | opl/examples/droplay.c | 4 | ||||
-rw-r--r-- | opl/opl.c | 10 | ||||
-rw-r--r-- | opl/opl.h | 16 | ||||
-rw-r--r-- | opl/opl_internal.h | 2 | ||||
-rw-r--r-- | opl/opl_queue.c | 12 | ||||
-rw-r--r-- | opl/opl_queue.h | 6 | ||||
-rw-r--r-- | opl/opl_sdl.c | 31 | ||||
-rw-r--r-- | opl/opl_timer.c | 30 | ||||
-rw-r--r-- | opl/opl_timer.h | 4 | ||||
-rw-r--r-- | src/i_oplmusic.c | 15 |
10 files changed, 69 insertions, 61 deletions
diff --git a/opl/examples/droplay.c b/opl/examples/droplay.c index 99456050..7b20e03d 100644 --- a/opl/examples/droplay.c +++ b/opl/examples/droplay.c @@ -139,7 +139,7 @@ void TimerCallback(void *data) // Schedule the next timer callback. - OPL_SetCallback(delay, TimerCallback, timer_data); + OPL_SetCallback(delay * OPL_MS, TimerCallback, timer_data); } void PlayFile(char *filename) @@ -183,7 +183,7 @@ void PlayFile(char *filename) running = timer_data.running; OPL_Unlock(); - SDL_Delay(100); + SDL_Delay(100 * OPL_MS); } while (running); fclose(timer_data.fstream); @@ -295,7 +295,7 @@ int OPL_Detect(void) OPL_ReadStatus(); } - OPL_Delay(1); + OPL_Delay(1 * OPL_MS); // Read status result2 = OPL_ReadStatus(); @@ -357,11 +357,11 @@ void OPL_InitRegisters(void) // Timer functions. // -void OPL_SetCallback(unsigned int ms, opl_callback_t callback, void *data) +void OPL_SetCallback(unsigned int us, opl_callback_t callback, void *data) { if (driver != NULL) { - driver->set_callback_func(ms, callback, data); + driver->set_callback_func(us, callback, data); } } @@ -409,7 +409,7 @@ static void DelayCallback(void *_delay_data) SDL_UnlockMutex(delay_data->mutex); } -void OPL_Delay(unsigned int ms) +void OPL_Delay(unsigned int us) { delay_data_t delay_data; @@ -425,7 +425,7 @@ void OPL_Delay(unsigned int ms) delay_data.mutex = SDL_CreateMutex(); delay_data.cond = SDL_CreateCond(); - OPL_SetCallback(ms, DelayCallback, &delay_data); + OPL_SetCallback(us, DelayCallback, &delay_data); // Wait until the callback is invoked. @@ -19,6 +19,8 @@ #ifndef OPL_OPL_H #define OPL_OPL_H +#include <inttypes.h> + typedef void (*opl_callback_t)(void *data); typedef enum @@ -50,6 +52,12 @@ typedef enum #define OPL_REGS_FREQ_2 0xB0 #define OPL_REGS_FEEDBACK 0xC0 +// Times + +#define OPL_SECOND ((uint64_t) 1000 * 1000) +#define OPL_MS ((uint64_t) 1000) +#define OPL_US ((uint64_t) 1) + // // Low-level functions. // @@ -99,10 +107,10 @@ void OPL_InitRegisters(void); // Timer callback functions. // -// Set a timer callback. After the specified number of milliseconds +// Set a timer callback. After the specified number of microseconds // have elapsed, the callback will be invoked. -void OPL_SetCallback(unsigned int ms, opl_callback_t callback, void *data); +void OPL_SetCallback(unsigned int us, opl_callback_t callback, void *data); // Adjust callback times by the specified factor. For example, a value of // 0.5 will halve all remaining times. @@ -122,9 +130,9 @@ void OPL_Lock(void); void OPL_Unlock(void); -// Block until the specified number of milliseconds have elapsed. +// Block until the specified number of microseconds have elapsed. -void OPL_Delay(unsigned int ms); +void OPL_Delay(unsigned int us); // Pause the OPL callbacks. diff --git a/opl/opl_internal.h b/opl/opl_internal.h index 24e79644..2d027ad8 100644 --- a/opl/opl_internal.h +++ b/opl/opl_internal.h @@ -25,7 +25,7 @@ typedef int (*opl_init_func)(unsigned int port_base); typedef void (*opl_shutdown_func)(void); typedef unsigned int (*opl_read_port_func)(opl_port_t port); typedef void (*opl_write_port_func)(opl_port_t port, unsigned int value); -typedef void (*opl_set_callback_func)(unsigned int ms, +typedef void (*opl_set_callback_func)(unsigned int us, opl_callback_t callback, void *data); typedef void (*opl_clear_callbacks_func)(void); diff --git a/opl/opl_queue.c b/opl/opl_queue.c index ee87a19b..4b4e4e38 100644 --- a/opl/opl_queue.c +++ b/opl/opl_queue.c @@ -28,7 +28,7 @@ typedef struct { opl_callback_t callback; void *data; - unsigned int time; + uint64_t time; } opl_queue_entry_t; struct opl_callback_queue_s @@ -64,7 +64,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; @@ -189,7 +189,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) { @@ -202,15 +202,15 @@ unsigned int OPL_Queue_Peek(opl_callback_queue_t *queue) } void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue, - unsigned int time, float factor) + uint64_t time, float factor) { - int offset; + int64_t offset; int i; for (i = 0; i < queue->num_entries; ++i) { offset = queue->entries[i].time - time; - queue->entries[i].time = time + (int) (offset * factor); + queue->entries[i].time = time + (uint64_t) (offset * factor); } } diff --git a/opl/opl_queue.h b/opl/opl_queue.h index 20ddeda9..8b4f0dbe 100644 --- a/opl/opl_queue.h +++ b/opl/opl_queue.h @@ -28,12 +28,12 @@ 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, - unsigned int time, float factor); + uint64_t time, float factor); #endif /* #ifndef OPL_QUEUE_H */ diff --git a/opl/opl_sdl.c b/opl/opl_sdl.c index 3ed7f784..fa9f047a 100644 --- a/opl/opl_sdl.c +++ b/opl/opl_sdl.c @@ -39,7 +39,7 @@ 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; // When the callback mutex is locked using OPL_Lock, callback functions @@ -55,18 +55,18 @@ static opl_callback_queue_t *callback_queue; static SDL_mutex *callback_queue_mutex = NULL; -// Current time, in number of samples since startup: +// Current time, in us since startup: -static int current_time; +static uint64_t current_time; // If non-zero, playback is currently paused. static int opl_sdl_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. @@ -106,20 +106,22 @@ static void AdvanceTime(unsigned int nsamples) { opl_callback_t callback; void *callback_data; + uint64_t us; SDL_LockMutex(callback_queue_mutex); // Advance time. - current_time += nsamples; + us = ((uint64_t) nsamples * OPL_SECOND) / mixing_freq; + current_time += us; if (opl_sdl_paused) { - pause_offset += nsamples; + pause_offset += us; } // Are there callbacks to invoke now? Keep invoking them - // until there are none more left. + // until there are no more left. while (!OPL_Queue_IsEmpty(callback_queue) && current_time >= OPL_Queue_Peek(callback_queue) + pause_offset) @@ -193,8 +195,8 @@ static void OPL_Mix_Callback(void *udata, while (filled < buffer_len) { - unsigned int next_callback_time; - unsigned int nsamples; + uint64_t next_callback_time; + uint64_t nsamples; SDL_LockMutex(callback_queue_mutex); @@ -210,7 +212,8 @@ static void OPL_Mix_Callback(void *udata, { next_callback_time = OPL_Queue_Peek(callback_queue) + pause_offset; - nsamples = next_callback_time - current_time; + nsamples = (next_callback_time - current_time) * mixing_freq; + nsamples = (nsamples + OPL_SECOND - 1) / OPL_SECOND; if (nsamples > buffer_len - filled) { @@ -395,7 +398,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; } } @@ -454,13 +457,13 @@ static void OPL_SDL_PortWrite(opl_port_t port, unsigned int value) } } -static void OPL_SDL_SetCallback(unsigned int ms, +static void OPL_SDL_SetCallback(unsigned int us, opl_callback_t callback, void *data) { SDL_LockMutex(callback_queue_mutex); OPL_Queue_Push(callback_queue, callback, data, - current_time - pause_offset + (ms * mixing_freq) / 1000); + current_time - pause_offset + us); SDL_UnlockMutex(callback_queue_mutex); } diff --git a/opl/opl_timer.c b/opl/opl_timer.c index bab15687..312fe7fa 100644 --- a/opl/opl_timer.c +++ b/opl/opl_timer.c @@ -31,16 +31,16 @@ typedef enum static SDL_Thread *timer_thread = NULL; static thread_state_t timer_thread_state; -static int current_time; +static uint64_t current_time; // If non-zero, callbacks are currently paused. static int opl_timer_paused; -// Offset in milliseconds to adjust time due to the fact that playback +// Offset in microseconds to adjust time due to the fact that playback // was paused. -static unsigned int pause_offset = 0; +static uint64_t pause_offset = 0; // Queue of callbacks waiting to be invoked. // The callback queue mutex is held while the callback queue structure @@ -58,7 +58,7 @@ static SDL_mutex *timer_mutex; // to be invoked. Otherwise, next_time is set to the time when the // timer thread must wake up again to check. -static int CallbackWaiting(unsigned int *next_time) +static int CallbackWaiting(uint64_t *next_time) { // If paused, just wait in 50ms increments until unpaused. // Update pause_offset so after we unpause, the callback @@ -66,8 +66,8 @@ static int CallbackWaiting(unsigned int *next_time) if (opl_timer_paused) { - *next_time = current_time + 50; - pause_offset += 50; + *next_time = current_time + 50 * OPL_MS; + pause_offset += 50 * OPL_MS; return 0; } @@ -76,7 +76,7 @@ static int CallbackWaiting(unsigned int *next_time) if (OPL_Queue_IsEmpty(callback_queue)) { - *next_time = current_time + 50; + *next_time = current_time + 50 * OPL_MS; return 0; } @@ -89,11 +89,11 @@ static int CallbackWaiting(unsigned int *next_time) return *next_time <= current_time; } -static unsigned int GetNextTime(void) +static uint64_t GetNextTime(void) { opl_callback_t callback; void *callback_data; - unsigned int next_time; + uint64_t next_time; int have_callback; // Keep running through callbacks until there are none ready to @@ -131,8 +131,8 @@ static unsigned int GetNextTime(void) static int ThreadFunction(void *unused) { - unsigned int next_time; - unsigned int now; + uint64_t next_time; + uint64_t now; // Keep running until OPL_Timer_StopThread is called. @@ -142,11 +142,11 @@ static int ThreadFunction(void *unused) // wait until that time. next_time = GetNextTime(); - now = SDL_GetTicks(); + now = SDL_GetTicks() * OPL_MS; if (next_time > now) { - SDL_Delay(next_time - now); + SDL_Delay((next_time - now) / OPL_MS); } // Update the current time. @@ -209,11 +209,11 @@ void OPL_Timer_StopThread(void) FreeResources(); } -void OPL_Timer_SetCallback(unsigned int ms, opl_callback_t callback, void *data) +void OPL_Timer_SetCallback(uint64_t us, opl_callback_t callback, void *data) { SDL_LockMutex(callback_queue_mutex); OPL_Queue_Push(callback_queue, callback, data, - current_time + ms - pause_offset); + current_time + us - pause_offset); SDL_UnlockMutex(callback_queue_mutex); } diff --git a/opl/opl_timer.h b/opl/opl_timer.h index 73544013..adf81503 100644 --- a/opl/opl_timer.h +++ b/opl/opl_timer.h @@ -22,9 +22,7 @@ int OPL_Timer_StartThread(void); void OPL_Timer_StopThread(void); -void OPL_Timer_SetCallback(unsigned int ms, - opl_callback_t callback, - void *data); +void OPL_Timer_SetCallback(uint64_t us, opl_callback_t callback, void *data); void OPL_Timer_ClearCallbacks(void); void OPL_Timer_Lock(void); void OPL_Timer_Unlock(void); diff --git a/src/i_oplmusic.c b/src/i_oplmusic.c index 489b6d55..5f9ab462 100644 --- a/src/i_oplmusic.c +++ b/src/i_oplmusic.c @@ -47,7 +47,7 @@ #define PERCUSSION_LOG_LEN 16 // TODO: Figure out why this is needed. -#define TEMPO_FUDGE_FACTOR 0.26 +#define TEMPO_FUDGE_FACTOR 260 typedef struct { @@ -1160,7 +1160,7 @@ static void TrackTimerCallback(void *arg) if (running_tracks <= 0 && song_looping) { - OPL_SetCallback(5, RestartSong, NULL); + OPL_SetCallback(5000, RestartSong, NULL); } return; @@ -1174,19 +1174,18 @@ static void TrackTimerCallback(void *arg) static void ScheduleTrack(opl_track_data_t *track) { unsigned int nticks; - uint64_t ms; + uint64_t us; - // Get the number of milliseconds until the next event. + // Get the number of microseconds until the next event. nticks = MIDI_GetDeltaTime(track->iter); - ms = nticks; - ms *= us_per_beat * TEMPO_FUDGE_FACTOR; - ms /= ticks_per_beat; + us = ((uint64_t) nticks * us_per_beat * TEMPO_FUDGE_FACTOR) + / ticks_per_beat; // Set a timer to be invoked when the next event is // ready to play. - OPL_SetCallback((unsigned int) ms, TrackTimerCallback, track); + OPL_SetCallback(us, TrackTimerCallback, track); } // Initialize a channel. |