summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opl/examples/droplay.c4
-rw-r--r--opl/opl.c10
-rw-r--r--opl/opl.h16
-rw-r--r--opl/opl_internal.h2
-rw-r--r--opl/opl_queue.c12
-rw-r--r--opl/opl_queue.h6
-rw-r--r--opl/opl_sdl.c31
-rw-r--r--opl/opl_timer.c30
-rw-r--r--opl/opl_timer.h4
-rw-r--r--src/i_oplmusic.c15
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);
diff --git a/opl/opl.c b/opl/opl.c
index cc5b861d..982fb814 100644
--- a/opl/opl.c
+++ b/opl/opl.c
@@ -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.
diff --git a/opl/opl.h b/opl/opl.h
index d6a295b0..0af8bc17 100644
--- a/opl/opl.h
+++ b/opl/opl.h
@@ -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.