summaryrefslogtreecommitdiff
path: root/opl
diff options
context:
space:
mode:
authorSimon Howard2014-05-10 14:00:41 -0400
committerSimon Howard2014-05-10 14:00:41 -0400
commit495694da29ff736fba2fdc696553ee7197247174 (patch)
tree49c7cb18a42f9d5302aead68572a8deca8d9445a /opl
parent541267071a118fe5cc702632fdba5817e27b6f76 (diff)
downloadchocolate-doom-495694da29ff736fba2fdc696553ee7197247174.tar.gz
chocolate-doom-495694da29ff736fba2fdc696553ee7197247174.tar.bz2
chocolate-doom-495694da29ff736fba2fdc696553ee7197247174.zip
opl: Add API to adjust tempo.
When the tempo is changed, the times on all active timers must be adjusted to match the new timing values. Add an API to do this and invoke it when a tempo change meta event is read.
Diffstat (limited to 'opl')
-rw-r--r--opl/opl.c8
-rw-r--r--opl/opl.h5
-rw-r--r--opl/opl_internal.h2
-rw-r--r--opl/opl_linux.c3
-rw-r--r--opl/opl_obsd.c3
-rw-r--r--opl/opl_queue.c13
-rw-r--r--opl/opl_queue.h2
-rw-r--r--opl/opl_sdl.c10
-rw-r--r--opl/opl_timer.c7
-rw-r--r--opl/opl_timer.h1
-rw-r--r--opl/opl_win32.c3
11 files changed, 53 insertions, 4 deletions
diff --git a/opl/opl.c b/opl/opl.c
index 0666476d..cc5b861d 100644
--- a/opl/opl.c
+++ b/opl/opl.c
@@ -452,3 +452,11 @@ void OPL_SetPaused(int paused)
}
}
+void OPL_AdjustCallbacks(float value)
+{
+ if (driver != NULL)
+ {
+ driver->adjust_callbacks_func(value);
+ }
+}
+
diff --git a/opl/opl.h b/opl/opl.h
index f0879b4d..d6a295b0 100644
--- a/opl/opl.h
+++ b/opl/opl.h
@@ -104,6 +104,11 @@ void OPL_InitRegisters(void);
void OPL_SetCallback(unsigned int ms, 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.
+
+void OPL_AdjustCallbacks(float factor);
+
// Clear all OPL callbacks that have been set.
void OPL_ClearCallbacks(void);
diff --git a/opl/opl_internal.h b/opl/opl_internal.h
index 91a275d5..24e79644 100644
--- a/opl/opl_internal.h
+++ b/opl/opl_internal.h
@@ -32,6 +32,7 @@ typedef void (*opl_clear_callbacks_func)(void);
typedef void (*opl_lock_func)(void);
typedef void (*opl_unlock_func)(void);
typedef void (*opl_set_paused_func)(int paused);
+typedef void (*opl_adjust_callbacks_func)(float value);
typedef struct
{
@@ -46,6 +47,7 @@ typedef struct
opl_lock_func lock_func;
opl_unlock_func unlock_func;
opl_set_paused_func set_paused_func;
+ opl_adjust_callbacks_func adjust_callbacks_func;
} opl_driver_t;
// Sample rate to use when doing software emulation.
diff --git a/opl/opl_linux.c b/opl/opl_linux.c
index 12d21075..5df5d468 100644
--- a/opl/opl_linux.c
+++ b/opl/opl_linux.c
@@ -95,7 +95,8 @@ opl_driver_t opl_linux_driver =
OPL_Timer_ClearCallbacks,
OPL_Timer_Lock,
OPL_Timer_Unlock,
- OPL_Timer_SetPaused
+ OPL_Timer_SetPaused,
+ OPL_Timer_AdjustCallbacks,
};
#endif /* #ifdef HAVE_IOPERM */
diff --git a/opl/opl_obsd.c b/opl/opl_obsd.c
index 3313c1b2..39e0c156 100644
--- a/opl/opl_obsd.c
+++ b/opl/opl_obsd.c
@@ -110,7 +110,8 @@ opl_driver_t opl_openbsd_driver =
OPL_Timer_ClearCallbacks,
OPL_Timer_Lock,
OPL_Timer_Unlock,
- OPL_Timer_SetPaused
+ OPL_Timer_SetPaused,
+ OPL_Timer_AdjustCallbacks,
};
#endif /* #ifndef NO_OBSD_DRIVER */
diff --git a/opl/opl_queue.c b/opl/opl_queue.c
index d05cc6a1..ee87a19b 100644
--- a/opl/opl_queue.c
+++ b/opl/opl_queue.c
@@ -201,6 +201,19 @@ unsigned int OPL_Queue_Peek(opl_callback_queue_t *queue)
}
}
+void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue,
+ unsigned int time, float factor)
+{
+ int 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);
+ }
+}
+
#ifdef TEST
#include <assert.h>
diff --git a/opl/opl_queue.h b/opl/opl_queue.h
index b0f479f4..20ddeda9 100644
--- a/opl/opl_queue.h
+++ b/opl/opl_queue.h
@@ -32,6 +32,8 @@ void OPL_Queue_Push(opl_callback_queue_t *queue,
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);
+void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue,
+ unsigned int time, float factor);
#endif /* #ifndef OPL_QUEUE_H */
diff --git a/opl/opl_sdl.c b/opl/opl_sdl.c
index 4cd3dc7b..3ed7f784 100644
--- a/opl/opl_sdl.c
+++ b/opl/opl_sdl.c
@@ -486,6 +486,13 @@ static void OPL_SDL_SetPaused(int paused)
opl_sdl_paused = paused;
}
+static void OPL_SDL_AdjustCallbacks(float factor)
+{
+ SDL_LockMutex(callback_queue_mutex);
+ OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor);
+ SDL_UnlockMutex(callback_queue_mutex);
+}
+
opl_driver_t opl_sdl_driver =
{
"SDL",
@@ -497,6 +504,7 @@ opl_driver_t opl_sdl_driver =
OPL_SDL_ClearCallbacks,
OPL_SDL_Lock,
OPL_SDL_Unlock,
- OPL_SDL_SetPaused
+ OPL_SDL_SetPaused,
+ OPL_SDL_AdjustCallbacks,
};
diff --git a/opl/opl_timer.c b/opl/opl_timer.c
index 97e5ea8b..bab15687 100644
--- a/opl/opl_timer.c
+++ b/opl/opl_timer.c
@@ -224,6 +224,13 @@ void OPL_Timer_ClearCallbacks(void)
SDL_UnlockMutex(callback_queue_mutex);
}
+void OPL_Timer_AdjustCallbacks(float factor)
+{
+ SDL_LockMutex(callback_queue_mutex);
+ OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor);
+ SDL_UnlockMutex(callback_queue_mutex);
+}
+
void OPL_Timer_Lock(void)
{
SDL_LockMutex(timer_mutex);
diff --git a/opl/opl_timer.h b/opl/opl_timer.h
index 1febcac9..73544013 100644
--- a/opl/opl_timer.h
+++ b/opl/opl_timer.h
@@ -29,6 +29,7 @@ void OPL_Timer_ClearCallbacks(void);
void OPL_Timer_Lock(void);
void OPL_Timer_Unlock(void);
void OPL_Timer_SetPaused(int paused);
+void OPL_Timer_AdjustCallbacks(float factor);
#endif /* #ifndef OPL_TIMER_H */
diff --git a/opl/opl_win32.c b/opl/opl_win32.c
index c6c37803..ea7b9eeb 100644
--- a/opl/opl_win32.c
+++ b/opl/opl_win32.c
@@ -184,7 +184,8 @@ opl_driver_t opl_win32_driver =
OPL_Timer_ClearCallbacks,
OPL_Timer_Lock,
OPL_Timer_Unlock,
- OPL_Timer_SetPaused
+ OPL_Timer_SetPaused,
+ OPL_Timer_AdjustCallbacks,
};
#endif /* #ifdef _WIN32 */