From 4ddfc3e9d971418a0c537c4eb53c5277a147d111 Mon Sep 17 00:00:00 2001 From: terminx Date: Wed, 9 Jul 2008 23:25:38 +0000 Subject: [PATCH] Comment out and refactor some unnecessary (IMO) console startup messages... seems to improve win32 startup times, possibly due to less scrolling of the startup window text buffer. git-svn-id: https://svn.eduke32.com/eduke32@848 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/build/src/baselayer.c | 16 +- polymer/build/src/winlayer.c | 41 +- polymer/eduke32/eduke32.vcproj | 4 + polymer/eduke32/source/astub.c | 2 +- polymer/eduke32/source/config.c | 10 +- polymer/eduke32/source/config.h | 2 +- polymer/eduke32/source/game.c | 12 +- polymer/eduke32/source/jaudiolib/dsl.c | 2 +- polymer/eduke32/source/jaudiolib/dsoundout.c | 1270 +++--- polymer/eduke32/source/jaudiolib/midi.c | 4140 +++++++++--------- polymer/eduke32/source/jaudiolib/multivoc.c | 24 +- polymer/eduke32/source/jaudiolib/music.c | 26 +- polymer/eduke32/source/jaudiolib/openal.c | 8 +- polymer/eduke32/source/jaudiolib/pitch.c | 398 +- polymer/eduke32/source/jmact/control.c | 2 + polymer/eduke32/source/menus.c | 22 +- polymer/eduke32/source/osdcmds.c | 4 +- polymer/eduke32/source/rts.c | 4 +- 18 files changed, 3002 insertions(+), 2985 deletions(-) diff --git a/polymer/build/src/baselayer.c b/polymer/build/src/baselayer.c index 3df876eca..4c7095f7f 100644 --- a/polymer/build/src/baselayer.c +++ b/polymer/build/src/baselayer.c @@ -56,7 +56,7 @@ static int osdfunc_setrendermode(const osdfuncparm_t *parm) char *modestrs[] = { - "classic software", "polygonal flat-shaded software", + "classic software", "completely broken polygonal flat-shaded software", "polygonal textured software", "polygonal OpenGL", "great justice" }; @@ -106,8 +106,15 @@ int osdcmd_glinfo(const osdfuncparm_t *parm) initprintf("OpenGL Information:\n" " Version: %s\n" " Vendor: %s\n" - " Renderer: %s\n" - " Maximum anisotropy: %.1f%s\n" + " Renderer: %s\n", + glinfo.version, + glinfo.vendor, + glinfo.renderer); + + if (!glinfo.dumped) + return OSDCMD_OK; + + initprintf(" Maximum anisotropy: %.1f%s\n" " BGRA textures: %s\n" " Non-x^2 textures: %s\n" " Texure compression: %s\n" @@ -123,9 +130,6 @@ int osdcmd_glinfo(const osdfuncparm_t *parm) " env_combine: %s\n" " Vertex Buffer Objects: %s\n" " Extensions:\n", - glinfo.version, - glinfo.vendor, - glinfo.renderer, glinfo.maxanisotropy, glinfo.maxanisotropy>1.0?"":" (no anisotropic filtering)", glinfo.bgra ? "supported": "not supported", glinfo.texnpot ? "supported": "not supported", diff --git a/polymer/build/src/winlayer.c b/polymer/build/src/winlayer.c index 479ad2cc4..19c7cc7fe 100644 --- a/polymer/build/src/winlayer.c +++ b/polymer/build/src/winlayer.c @@ -522,7 +522,7 @@ int initsystem(void) { DEVMODE desktopmode; - initprintf("Initializing Windows DirectX/GDI system interface\n"); +// initprintf("Initializing Windows DirectX/GDI system interface\n"); // get the desktop dimensions before anything changes them ZeroMemory(&desktopmode, sizeof(DEVMODE)); @@ -873,9 +873,9 @@ void uninitmouse(void) grabmouse(0); moustat=mousegrab=0; SetEvent(inputevt[MOUSE]); - if (WaitForSingleObject(mousethread, 300) == WAIT_OBJECT_0) - initprintf("DirectInput: Mouse thread has exited\n"); - else + if (WaitForSingleObject(mousethread, 300) != WAIT_OBJECT_0) +// initprintf("DirectInput: Mouse thread has exited\n"); +// else initprintf("DirectInput: Mouse thread failed to exit!\n"); } @@ -1194,7 +1194,7 @@ static BOOL InitDirectInput(void) // load up the DirectInput DLL if (!hDInputDLL) { - initprintf(" - Loading DINPUT.DLL\n"); +// initprintf(" - Loading DINPUT.DLL\n"); hDInputDLL = LoadLibrary("DINPUT.DLL"); if (!hDInputDLL) { @@ -1208,7 +1208,7 @@ static BOOL InitDirectInput(void) if (!aDirectInputCreateA) ShowErrorBox("Error fetching DirectInputCreateA()"); // create a new DirectInput object - initprintf(" - Creating DirectInput object\n"); +// initprintf(" - Creating DirectInput object\n"); result = aDirectInputCreateA(hInstance, DIRECTINPUT_VERSION, &lpDI, NULL); if FAILED(result) { HorribleDInputDeath("DirectInputCreateA() failed", result); } else if (result != DI_OK) initprintf(" Created DirectInput object with warning: %s\n",GetDInputError(result)); @@ -1234,7 +1234,7 @@ static BOOL InitDirectInput(void) if ((inputdevices & (1< + + diff --git a/polymer/eduke32/source/astub.c b/polymer/eduke32/source/astub.c index 2f96532a5..5dbd332a9 100644 --- a/polymer/eduke32/source/astub.c +++ b/polymer/eduke32/source/astub.c @@ -1874,7 +1874,7 @@ static void ReadPaletteTable() return; } } - initprintf("Loading palette lookups... "); +// initprintf("Loading palette lookups... "); kread(fp,&num_tables,1); for (j=0;j= '0' && *t <= '9')) - x += 8*z/65536; - // else x += tilesizx[ac]*z/65536;//(tilesizx[ac]>>small); + x += 8*z/65536; + // else x += tilesizx[ac]*z/65536;//(tilesizx[ac]>>small); if (t-oldt >= (signed)TEXTWRAPLEN-!small) oldt = (char *)t, x = oldx, y+=8*z/65536; t++; } @@ -9832,11 +9832,11 @@ static void Startup(void) inittimer(TICRATE); //initprintf("* Hold Esc to Abort. *\n"); - initprintf("Loading art header...\n"); +// initprintf("Loading art header...\n"); if (loadpics("tiles000.art",MAXCACHE1DSIZE) < 0) gameexit("Failed loading art."); - initprintf("Loading palette/lookups...\n"); +// initprintf("Loading palette/lookups...\n"); genspriteremaps(); readsavenames(); @@ -10517,9 +10517,9 @@ void app_main(int argc,const char **argv) ud.config.ScreenBPP = bpp[i]; } - initprintf("Checking music inits...\n"); + initprintf("Initializing music...\n"); MusicStartup(); - initprintf("Checking sound inits...\n"); + initprintf("Initializing sound...\n"); SoundStartup(); loadtmb(); diff --git a/polymer/eduke32/source/jaudiolib/dsl.c b/polymer/eduke32/source/jaudiolib/dsl.c index 0402bdec7..672fc6847 100755 --- a/polymer/eduke32/source/jaudiolib/dsl.c +++ b/polymer/eduke32/source/jaudiolib/dsl.c @@ -275,7 +275,7 @@ int RestoreInterrupts(int flags) UNREFERENCED_PARAMETER(flags); if (--interrupts_disabled) return 0; - // interrupts_disabled = 0; +// interrupts_disabled = 0; SDL_UnlockAudio(); return(0); } diff --git a/polymer/eduke32/source/jaudiolib/dsoundout.c b/polymer/eduke32/source/jaudiolib/dsoundout.c index d191a01f9..f7da5afb4 100644 --- a/polymer/eduke32/source/jaudiolib/dsoundout.c +++ b/polymer/eduke32/source/jaudiolib/dsoundout.c @@ -1,634 +1,636 @@ -/* - * DirectSound output code for MultiVoc - * by Jonathon Fowler (jonof@edgenetwk.com) - */ -//------------------------------------------------------------------------- -/* -Duke Nukem Copyright (C) 1996, 2003 3D Realms Entertainment - -This file is part of Duke Nukem 3D version 1.5 - Atomic Edition - -Duke Nukem 3D is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -//------------------------------------------------------------------------- - -#include "dsoundout.h" - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include "dsound.h" -#ifdef USE_OPENAL -#include "openal.h" -#endif -#include "compat.h" -#include "winlayer.h" - -#if defined(__WATCOMC__) || defined(_MSC_VER) -#include -#endif - - -#ifndef RENDERTYPEWIN -#error The DirectSound output module for AudioLib only works with the Windows interface. -#endif - -static CRITICAL_SECTION mutex; -static int _DSOUND_CriticalSectionAlloced = FALSE; -static HANDLE isrthread = NULL; -static HANDLE isrfinish = NULL; - -static HMODULE hDSoundDLL = NULL; -static LPDIRECTSOUND lpDS = NULL; -static LPDIRECTSOUNDBUFFER lpDSBPrimary = NULL; -static LPDIRECTSOUNDBUFFER lpDSBSecondary = NULL; -static LPDIRECTSOUNDNOTIFY lpDSNotify = NULL; -static HANDLE *hPosNotify = NULL; - -static int(*_DSOUND_CallBack)(int) = NULL; -static int _DSOUND_BufferLength = 0; -static int _DSOUND_NumBuffers = 0; -static char *_DSOUND_MixBuffer = NULL; - -static int DSOUND_Installed = FALSE; - -int DSOUND_ErrorCode = DSOUND_Ok; - -#define DSOUND_SetErrorCode( status ) \ - DSOUND_ErrorCode = ( status ); - - - -/* - * DisableInterrupts - * Enter the critical section. - */ -int DisableInterrupts(void) -{ - if (!_DSOUND_CriticalSectionAlloced) return -1; - - EnterCriticalSection(&mutex); - - return 0; -} - - -/* - * RestoreInterrupts - * Leave the critical section. - */ -int RestoreInterrupts(int a) -{ - if (!_DSOUND_CriticalSectionAlloced) return -1; - - LeaveCriticalSection(&mutex); - - return 0; - a=a; -} - - -/* - * DSOUND_ErrorString - * Returns a description of an error code. - */ -char *DSOUND_ErrorString(int errorcode) -{ - switch (errorcode) - { - case DSOUND_Warning: - case DSOUND_Error: - return DSOUND_ErrorString(DSOUND_ErrorCode); - - case DSOUND_Ok: - return "DirectSound ok."; - - case DSOUND_NoDLL: - return "Failed loading DSOUND.DLL."; - - case DSOUND_NoDirectSoundCreate: - return "Failed getting DirectSoundCreate entry point."; - - case DSOUND_FailedDSC: - return "DirectSoundCreate failed."; - - case DSOUND_FailedSetCoopLevel: - return "Failed setting cooperative level."; - - case DSOUND_FailedCreatePrimary: - return "Failed creating primary buffer."; - - case DSOUND_FailedSetFormat: - return "Failed setting primary buffer format."; - - case DSOUND_FailedCreateSecondary: - return "Failed creating secondary buffer."; - - case DSOUND_FailedCreateNotifyEvent: - return "Failed creating notification event object."; - - case DSOUND_FailedQueryNotify: - return "Failed querying notification interface."; - - case DSOUND_FailedSetNotify: - return "Failed setting notification positions."; - - case DSOUND_FailedCreateFinishEvent: - return "Failed creating finish event object."; - - case DSOUND_FailedCreateThread: - return "Failed creating playback thread."; - - case DSOUND_FailedPlaySecondary: - return "Failed playing secondary buffer."; - - case DSOUND_FailedGetExitCode: - return "GetExitCodeThread failed."; - - default: - return "Unknown DirectSound error code."; - } -} - - -/* - * DSOUND_Init - * Initializes the DirectSound objects. - */ -int DSOUND_Init(int soundcard, int mixrate, int numchannels, int samplebits, int buffersize) -{ - HRESULT(WINAPI *aDirectSoundCreate)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN); - HRESULT hr; - DSBUFFERDESC dsbuf; - WAVEFORMATEX wfex; - DSBPOSITIONNOTIFY posn; - - UNREFERENCED_PARAMETER(soundcard); - - if (DSOUND_Installed) - { - DSOUND_Shutdown(); - } - - initprintf("Initializing DirectSound...\n"); - - if (!_DSOUND_CriticalSectionAlloced) - { - // initialize the critical section object we'll use to - // simulate (dis|en)abling interrupts - InitializeCriticalSection(&mutex); - _DSOUND_CriticalSectionAlloced = TRUE; - } - - initprintf(" - Loading DSOUND.DLL\n"); - hDSoundDLL = LoadLibrary("DSOUND.DLL"); - if (!hDSoundDLL) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_NoDLL); - return DSOUND_Error; - } - - aDirectSoundCreate = (void *)GetProcAddress(hDSoundDLL, "DirectSoundCreate"); - if (!aDirectSoundCreate) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_NoDirectSoundCreate); - return DSOUND_Error; - } - - initprintf(" - Creating DirectSound object\n"); - hr = aDirectSoundCreate(NULL, &lpDS, NULL); - if (hr != DS_OK) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_FailedDSC); - return DSOUND_Error; - } - - hr = IDirectSound_SetCooperativeLevel(lpDS, (HWND)win_gethwnd(), DSSCL_EXCLUSIVE); - if (hr != DS_OK) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_FailedSetCoopLevel); - return DSOUND_Error; - } - - initprintf(" - Creating primary buffer\n"); - ZeroMemory(&dsbuf, sizeof(dsbuf)); - dsbuf.dwSize = sizeof(DSBUFFERDESC); - dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER; - hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpDSBPrimary, NULL); - if (hr != DS_OK) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_FailedCreatePrimary); - return DSOUND_Error; - } - - initprintf(" - Setting primary buffer format\n" - " Channels: %d\n" - " Sample rate: %dHz\n" - " Sample size: %d bits\n", - numchannels, mixrate, samplebits); - ZeroMemory(&wfex, sizeof(wfex)); - wfex.wFormatTag = WAVE_FORMAT_PCM; - wfex.nChannels = numchannels; - wfex.nSamplesPerSec = mixrate; - wfex.wBitsPerSample = samplebits; - wfex.nBlockAlign = (wfex.wBitsPerSample / 8) * wfex.nChannels; - wfex.nAvgBytesPerSec = wfex.nBlockAlign * wfex.nSamplesPerSec; - hr = IDirectSoundBuffer_SetFormat(lpDSBPrimary, &wfex); - if (hr != DS_OK) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_FailedSetFormat); - return DSOUND_Error; - } - - initprintf(" - Creating secondary buffer\n"); - ZeroMemory(&dsbuf, sizeof(dsbuf)); - dsbuf.dwSize = sizeof(DSBUFFERDESC); - dsbuf.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE; - dsbuf.dwBufferBytes = buffersize; - dsbuf.lpwfxFormat = &wfex; - hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpDSBSecondary, NULL); - if (hr != DS_OK) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_FailedCreateSecondary); - return DSOUND_Error; - } - - hr = IDirectSoundBuffer_QueryInterface(lpDSBSecondary, &IID_IDirectSoundNotify, (LPVOID *)&lpDSNotify); - if (hr != DS_OK) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_FailedQueryNotify); - return DSOUND_Error; - } - - hPosNotify = (HANDLE *)malloc(sizeof(HANDLE)); - if (!hPosNotify) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_FailedSetNotify); - return DSOUND_Error; - } - - hPosNotify[0] = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!hPosNotify) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_FailedCreateNotifyEvent); - return DSOUND_Error; - } - - _DSOUND_BufferLength = 0; - _DSOUND_NumBuffers = 1; - posn.dwOffset = 0; - posn.hEventNotify = hPosNotify[0]; - - hr = IDirectSoundNotify_SetNotificationPositions(lpDSNotify, 1, &posn); - if (hr != DS_OK) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_FailedSetNotify); - return DSOUND_Error; - } - - DSOUND_Installed = TRUE; - - DSOUND_SetErrorCode(DSOUND_Ok); - return DSOUND_Ok; -} - - -/* - * DSOUND_Shutdown - * Shuts down DirectSound and it's associates. - */ -int DSOUND_Shutdown(void) -{ - int i; - - if (DSOUND_Installed) initprintf("Uninitializing DirectSound...\n"); - - DSOUND_Installed = FALSE; - - DSOUND_StopPlayback(); - - if (lpDSNotify) - { - IDirectSoundNotify_Release(lpDSNotify); - lpDSNotify = NULL; - } - - if (hPosNotify) - { - for (i=0; i<_DSOUND_NumBuffers; i++) - { - if (hPosNotify[i]) CloseHandle(hPosNotify[i]); - } - free(hPosNotify); - hPosNotify = NULL; - } - - if (lpDSBSecondary) - { - initprintf(" - Releasing secondary buffer\n"); - IDirectSoundBuffer_Stop(lpDSBSecondary); - IDirectSoundBuffer_Release(lpDSBSecondary); - lpDSBSecondary = NULL; - } - - if (lpDSBPrimary) - { - initprintf(" - Releasing primary buffer\n"); - IDirectSoundBuffer_Release(lpDSBPrimary); - lpDSBPrimary = NULL; - } - - if (lpDS) - { - initprintf(" - Releasing DirectSound object\n"); - IDirectSound_Release(lpDS); - lpDS = NULL; - } - - if (hDSoundDLL) - { - initprintf(" - Unloading DSOUND.DLL\n"); - FreeLibrary(hDSoundDLL); - hDSoundDLL = NULL; - } - - DSOUND_SetErrorCode(DSOUND_Ok); - return DSOUND_Ok; -} - - -/* - * DSOUND_SetMixMode - * Bit of filler for the future. - */ -int DSOUND_SetMixMode(int mode) -{ - return mode; -} - - -//#define DEBUGAUDIO - -#ifdef DEBUGAUDIO -#include -#endif -static DWORD WINAPI isr(LPVOID parm) -{ - HANDLE *handles; - HRESULT hr; - int rv; -#ifdef DEBUGAUDIO - int h; -#endif - int p; - LPVOID lockptr; DWORD lockbytes; - LPVOID lockptr2; DWORD lockbytes2; - - UNREFERENCED_PARAMETER(parm); - - handles = (HANDLE *)malloc(sizeof(HANDLE)*(1+_DSOUND_NumBuffers)); - if (!handles) return 1; - - handles[0] = isrfinish; - for (p=0; p<_DSOUND_NumBuffers; p++) - handles[p+1] = hPosNotify[p]; - -#ifdef DEBUGAUDIO - h = creat("audio.raw",S_IREAD|S_IWRITE); -#endif - - while (1) - { -#ifdef USE_OPENAL - AL_Update(); -#endif - rv = WaitForMultipleObjects(1+_DSOUND_NumBuffers, handles, FALSE, INFINITE); - - if (!(rv >= WAIT_OBJECT_0 && rv <= WAIT_OBJECT_0+1+_DSOUND_NumBuffers)) return -1; - - if (rv == WAIT_OBJECT_0) - { - // we've been asked to finish up - break; - } - - // otherwise we just service the interrupt - if (_DSOUND_CallBack) - { - DisableInterrupts(); - - p = _DSOUND_CallBack(rv-WAIT_OBJECT_0-1); -#ifdef DEBUGAUDIO - write(h, _DSOUND_MixBuffer + p*_DSOUND_BufferLength, _DSOUND_BufferLength); -#endif - - hr = IDirectSoundBuffer_Lock(lpDSBSecondary, p*_DSOUND_BufferLength, _DSOUND_BufferLength, - &lockptr, &lockbytes, &lockptr2, &lockbytes2, 0); - if (hr == DSERR_BUFFERLOST) - { - hr = IDirectSoundBuffer_Restore(lpDSBSecondary); - } - if (hr == DS_OK) - { - /* - #define copybuf(S,D,c) \ - ({ void *__S=(S), *__D=(D); int __c=(c); \ - __asm__ __volatile__ ("rep; movsl" \ - : "+S" (__S), "+D" (__D), "+c" (__c) : : "memory", "cc"); \ - 0; }) - */ - //copybuf(_DSOUND_MixBuffer + p * _DSOUND_BufferLength, lockptr, _DSOUND_BufferLength >> 2); - memcpy(lockptr, _DSOUND_MixBuffer + p * _DSOUND_BufferLength, _DSOUND_BufferLength); - IDirectSoundBuffer_Unlock(lpDSBSecondary, lockptr, lockbytes, lockptr2, lockbytes2); - } - - RestoreInterrupts(0); - } - } - -#ifdef DEBUGAUDIO - close(h); -#endif - - return 0; -} - - -/* - * DSOUND_BeginBufferedPlayback - * Spins off a thread that behaves somewhat like the SoundBlaster DMA ISR did. - */ -int DSOUND_BeginBufferedPlayback(char *BufferStart, int(*CallBackFunc)(int), int buffersize, int numdivisions) -{ - DWORD threadid; - HRESULT hr; - DSBPOSITIONNOTIFY *posns; - int i; - - _DSOUND_CallBack = CallBackFunc; - _DSOUND_MixBuffer = BufferStart; - - if (!lpDSBSecondary) return DSOUND_Error; - - if (isrthread) - { - DSOUND_StopPlayback(); - } - - isrfinish = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!isrfinish) - { - DSOUND_SetErrorCode(DSOUND_FailedCreateFinishEvent); - return DSOUND_Error; - } - - isrthread = CreateThread(NULL, 0, isr, NULL, CREATE_SUSPENDED, &threadid); - if (!isrthread) - { - DSOUND_SetErrorCode(DSOUND_FailedCreateThread); - return DSOUND_Error; - } - - hPosNotify = (HANDLE *)malloc(sizeof(HANDLE)*numdivisions); - if (!hPosNotify) - { - DSOUND_Shutdown(); - DSOUND_SetErrorCode(DSOUND_FailedSetNotify); - return DSOUND_Error; - } - - memset(hPosNotify, 0, sizeof(HANDLE)*numdivisions); - for (i=0; i +#include +#include +#include +#include "dsound.h" +#ifdef USE_OPENAL +#include "openal.h" +#endif +#include "compat.h" +#include "winlayer.h" + +#if defined(__WATCOMC__) || defined(_MSC_VER) +#include +#endif + + +#ifndef RENDERTYPEWIN +#error The DirectSound output module for AudioLib only works with the Windows interface. +#endif + +static CRITICAL_SECTION mutex; +static int _DSOUND_CriticalSectionAlloced = FALSE; +static HANDLE isrthread = NULL; +static HANDLE isrfinish = NULL; + +static HMODULE hDSoundDLL = NULL; +static LPDIRECTSOUND lpDS = NULL; +static LPDIRECTSOUNDBUFFER lpDSBPrimary = NULL; +static LPDIRECTSOUNDBUFFER lpDSBSecondary = NULL; +static LPDIRECTSOUNDNOTIFY lpDSNotify = NULL; +static HANDLE *hPosNotify = NULL; + +static int(*_DSOUND_CallBack)(int) = NULL; +static int _DSOUND_BufferLength = 0; +static int _DSOUND_NumBuffers = 0; +static char *_DSOUND_MixBuffer = NULL; + +static int DSOUND_Installed = FALSE; + +int DSOUND_ErrorCode = DSOUND_Ok; + +#define DSOUND_SetErrorCode( status ) \ + DSOUND_ErrorCode = ( status ); + + + +/* + * DisableInterrupts + * Enter the critical section. + */ +int DisableInterrupts(void) +{ + if (!_DSOUND_CriticalSectionAlloced) return -1; + + EnterCriticalSection(&mutex); + + return 0; +} + + +/* + * RestoreInterrupts + * Leave the critical section. + */ +int RestoreInterrupts(int a) +{ + if (!_DSOUND_CriticalSectionAlloced) return -1; + + LeaveCriticalSection(&mutex); + + return 0; + a=a; +} + + +/* + * DSOUND_ErrorString + * Returns a description of an error code. + */ +char *DSOUND_ErrorString(int errorcode) +{ + switch (errorcode) + { + case DSOUND_Warning: + case DSOUND_Error: + return DSOUND_ErrorString(DSOUND_ErrorCode); + + case DSOUND_Ok: + return "DirectSound ok."; + + case DSOUND_NoDLL: + return "Failed loading DSOUND.DLL."; + + case DSOUND_NoDirectSoundCreate: + return "Failed getting DirectSoundCreate entry point."; + + case DSOUND_FailedDSC: + return "DirectSoundCreate failed."; + + case DSOUND_FailedSetCoopLevel: + return "Failed setting cooperative level."; + + case DSOUND_FailedCreatePrimary: + return "Failed creating primary buffer."; + + case DSOUND_FailedSetFormat: + return "Failed setting primary buffer format."; + + case DSOUND_FailedCreateSecondary: + return "Failed creating secondary buffer."; + + case DSOUND_FailedCreateNotifyEvent: + return "Failed creating notification event object."; + + case DSOUND_FailedQueryNotify: + return "Failed querying notification interface."; + + case DSOUND_FailedSetNotify: + return "Failed setting notification positions."; + + case DSOUND_FailedCreateFinishEvent: + return "Failed creating finish event object."; + + case DSOUND_FailedCreateThread: + return "Failed creating playback thread."; + + case DSOUND_FailedPlaySecondary: + return "Failed playing secondary buffer."; + + case DSOUND_FailedGetExitCode: + return "GetExitCodeThread failed."; + + default: + return "Unknown DirectSound error code."; + } +} + + +/* + * DSOUND_Init + * Initializes the DirectSound objects. + */ +int DSOUND_Init(int soundcard, int mixrate, int numchannels, int samplebits, int buffersize) +{ + HRESULT(WINAPI *aDirectSoundCreate)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN); + HRESULT hr; + DSBUFFERDESC dsbuf; + WAVEFORMATEX wfex; + DSBPOSITIONNOTIFY posn; + + UNREFERENCED_PARAMETER(soundcard); + + if (DSOUND_Installed) + { + DSOUND_Shutdown(); + } + + initprintf("Initializing DirectSound...\n"); + + if (!_DSOUND_CriticalSectionAlloced) + { + // initialize the critical section object we'll use to + // simulate (dis|en)abling interrupts + InitializeCriticalSection(&mutex); + _DSOUND_CriticalSectionAlloced = TRUE; + } + +// initprintf(" - Loading DSOUND.DLL\n"); + hDSoundDLL = LoadLibrary("DSOUND.DLL"); + if (!hDSoundDLL) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_NoDLL); + return DSOUND_Error; + } + + aDirectSoundCreate = (void *)GetProcAddress(hDSoundDLL, "DirectSoundCreate"); + if (!aDirectSoundCreate) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_NoDirectSoundCreate); + return DSOUND_Error; + } + +// initprintf(" - Creating DirectSound object\n"); + hr = aDirectSoundCreate(NULL, &lpDS, NULL); + if (hr != DS_OK) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_FailedDSC); + return DSOUND_Error; + } + + hr = IDirectSound_SetCooperativeLevel(lpDS, (HWND)win_gethwnd(), DSSCL_EXCLUSIVE); + if (hr != DS_OK) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_FailedSetCoopLevel); + return DSOUND_Error; + } + +// initprintf(" - Creating primary buffer\n"); + ZeroMemory(&dsbuf, sizeof(dsbuf)); + dsbuf.dwSize = sizeof(DSBUFFERDESC); + dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER; + hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpDSBPrimary, NULL); + if (hr != DS_OK) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_FailedCreatePrimary); + return DSOUND_Error; + } + + initprintf(" - Setting primary buffer format\n" + " Channels: %d\n" + " Sample rate: %dHz\n" + " Sample size: %d bits\n", + numchannels, mixrate, samplebits); + ZeroMemory(&wfex, sizeof(wfex)); + wfex.wFormatTag = WAVE_FORMAT_PCM; + wfex.nChannels = numchannels; + wfex.nSamplesPerSec = mixrate; + wfex.wBitsPerSample = samplebits; + wfex.nBlockAlign = (wfex.wBitsPerSample / 8) * wfex.nChannels; + wfex.nAvgBytesPerSec = wfex.nBlockAlign * wfex.nSamplesPerSec; + hr = IDirectSoundBuffer_SetFormat(lpDSBPrimary, &wfex); + if (hr != DS_OK) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_FailedSetFormat); + return DSOUND_Error; + } + + initprintf(" - Creating secondary buffer\n"); + ZeroMemory(&dsbuf, sizeof(dsbuf)); + dsbuf.dwSize = sizeof(DSBUFFERDESC); + dsbuf.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE; + dsbuf.dwBufferBytes = buffersize; + dsbuf.lpwfxFormat = &wfex; + hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpDSBSecondary, NULL); + if (hr != DS_OK) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_FailedCreateSecondary); + return DSOUND_Error; + } + + hr = IDirectSoundBuffer_QueryInterface(lpDSBSecondary, &IID_IDirectSoundNotify, (LPVOID *)&lpDSNotify); + if (hr != DS_OK) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_FailedQueryNotify); + return DSOUND_Error; + } + + hPosNotify = (HANDLE *)malloc(sizeof(HANDLE)); + if (!hPosNotify) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_FailedSetNotify); + return DSOUND_Error; + } + + hPosNotify[0] = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!hPosNotify) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_FailedCreateNotifyEvent); + return DSOUND_Error; + } + + _DSOUND_BufferLength = 0; + _DSOUND_NumBuffers = 1; + posn.dwOffset = 0; + posn.hEventNotify = hPosNotify[0]; + + hr = IDirectSoundNotify_SetNotificationPositions(lpDSNotify, 1, &posn); + if (hr != DS_OK) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_FailedSetNotify); + return DSOUND_Error; + } + + DSOUND_Installed = TRUE; + + DSOUND_SetErrorCode(DSOUND_Ok); + return DSOUND_Ok; +} + + +/* + * DSOUND_Shutdown + * Shuts down DirectSound and it's associates. + */ +int DSOUND_Shutdown(void) +{ + int i; + + if (DSOUND_Installed) initprintf("Uninitializing DirectSound...\n"); + + DSOUND_Installed = FALSE; + + DSOUND_StopPlayback(); + + if (lpDSNotify) + { + IDirectSoundNotify_Release(lpDSNotify); + lpDSNotify = NULL; + } + + if (hPosNotify) + { + for (i=0; i<_DSOUND_NumBuffers; i++) + { + if (hPosNotify[i]) CloseHandle(hPosNotify[i]); + } + free(hPosNotify); + hPosNotify = NULL; + } + + if (lpDSBSecondary) + { +// initprintf(" - Releasing secondary buffer\n"); + IDirectSoundBuffer_Stop(lpDSBSecondary); + IDirectSoundBuffer_Release(lpDSBSecondary); + lpDSBSecondary = NULL; + } + + if (lpDSBPrimary) + { +// initprintf(" - Releasing primary buffer\n"); + IDirectSoundBuffer_Release(lpDSBPrimary); + lpDSBPrimary = NULL; + } + + if (lpDS) + { +// initprintf(" - Releasing DirectSound object\n"); + IDirectSound_Release(lpDS); + lpDS = NULL; + } + + if (hDSoundDLL) + { +// initprintf(" - Unloading DSOUND.DLL\n"); + FreeLibrary(hDSoundDLL); + hDSoundDLL = NULL; + } + + DSOUND_SetErrorCode(DSOUND_Ok); + return DSOUND_Ok; +} + + +/* + * DSOUND_SetMixMode + * Bit of filler for the future. + */ +int DSOUND_SetMixMode(int mode) +{ + return mode; +} + + +//#define DEBUGAUDIO + +#ifdef DEBUGAUDIO +#include +#endif +static DWORD WINAPI isr(LPVOID parm) +{ + HANDLE *handles; + HRESULT hr; + int rv; +#ifdef DEBUGAUDIO + int h; +#endif + int p; + LPVOID lockptr; DWORD lockbytes; + LPVOID lockptr2; DWORD lockbytes2; + + UNREFERENCED_PARAMETER(parm); + + handles = (HANDLE *)malloc(sizeof(HANDLE)*(1+_DSOUND_NumBuffers)); + if (!handles) return 1; + + handles[0] = isrfinish; + for (p=0; p<_DSOUND_NumBuffers; p++) + handles[p+1] = hPosNotify[p]; + +#ifdef DEBUGAUDIO + h = creat("audio.raw",S_IREAD|S_IWRITE); +#endif + + while (1) + { +#ifdef USE_OPENAL + AL_Update(); +#endif + rv = WaitForMultipleObjects(1+_DSOUND_NumBuffers, handles, FALSE, INFINITE); + + if (!(rv >= WAIT_OBJECT_0 && rv <= WAIT_OBJECT_0+1+_DSOUND_NumBuffers)) return -1; + + if (rv == WAIT_OBJECT_0) + { + // we've been asked to finish up + break; + } + + // otherwise we just service the interrupt + if (_DSOUND_CallBack) + { + DisableInterrupts(); + + p = _DSOUND_CallBack(rv-WAIT_OBJECT_0-1); +#ifdef DEBUGAUDIO + write(h, _DSOUND_MixBuffer + p*_DSOUND_BufferLength, _DSOUND_BufferLength); +#endif + + hr = IDirectSoundBuffer_Lock(lpDSBSecondary, p*_DSOUND_BufferLength, _DSOUND_BufferLength, + &lockptr, &lockbytes, &lockptr2, &lockbytes2, 0); + if (hr == DSERR_BUFFERLOST) + { + hr = IDirectSoundBuffer_Restore(lpDSBSecondary); + } + if (hr == DS_OK) + { + /* + #define copybuf(S,D,c) \ + ({ void *__S=(S), *__D=(D); int __c=(c); \ + __asm__ __volatile__ ("rep; movsl" \ + : "+S" (__S), "+D" (__D), "+c" (__c) : : "memory", "cc"); \ + 0; }) + */ + //copybuf(_DSOUND_MixBuffer + p * _DSOUND_BufferLength, lockptr, _DSOUND_BufferLength >> 2); + memcpy(lockptr, _DSOUND_MixBuffer + p * _DSOUND_BufferLength, _DSOUND_BufferLength); + IDirectSoundBuffer_Unlock(lpDSBSecondary, lockptr, lockbytes, lockptr2, lockbytes2); + } + + RestoreInterrupts(0); + } + } + +#ifdef DEBUGAUDIO + close(h); +#endif + + return 0; +} + + +/* + * DSOUND_BeginBufferedPlayback + * Spins off a thread that behaves somewhat like the SoundBlaster DMA ISR did. + */ +int DSOUND_BeginBufferedPlayback(char *BufferStart, int(*CallBackFunc)(int), int buffersize, int numdivisions) +{ + DWORD threadid; + HRESULT hr; + DSBPOSITIONNOTIFY *posns; + int i; + + _DSOUND_CallBack = CallBackFunc; + _DSOUND_MixBuffer = BufferStart; + + if (!lpDSBSecondary) return DSOUND_Error; + + if (isrthread) + { + DSOUND_StopPlayback(); + } + + isrfinish = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!isrfinish) + { + DSOUND_SetErrorCode(DSOUND_FailedCreateFinishEvent); + return DSOUND_Error; + } + + isrthread = CreateThread(NULL, 0, isr, NULL, CREATE_SUSPENDED, &threadid); + if (!isrthread) + { + DSOUND_SetErrorCode(DSOUND_FailedCreateThread); + return DSOUND_Error; + } + + hPosNotify = (HANDLE *)malloc(sizeof(HANDLE)*numdivisions); + if (!hPosNotify) + { + DSOUND_Shutdown(); + DSOUND_SetErrorCode(DSOUND_FailedSetNotify); + return DSOUND_Error; + } + + memset(hPosNotify, 0, sizeof(HANDLE)*numdivisions); + for (i=0; i -#include -#include "standard.h" -#include "usrhooks.h" -#include "music.h" -#include "_midi.h" -#include "midi.h" -#include "mpu401.h" - -#define WIN32_LEAN_AND_MEAN -#include - -extern int MUSIC_SoundDevice; - -static const int _MIDI_CommandLengths[ NUM_MIDI_CHANNELS ] = - { - 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0 - }; - -static int(*_MIDI_RerouteFunctions[ NUM_MIDI_CHANNELS ]) -( - int event, - int c1, - int c2 -) = - { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL - }; - -static track *_MIDI_TrackPtr = NULL; -static int _MIDI_TrackMemSize; -static int _MIDI_NumTracks; - -static int _MIDI_SongActive = FALSE; -static int _MIDI_SongLoaded = FALSE; -static int _MIDI_Loop = FALSE; - -static int _MIDI_Division; -static int _MIDI_Tick = 0; -static int _MIDI_Beat = 1; -static int _MIDI_Measure = 1; -static unsigned _MIDI_Time; -static int _MIDI_BeatsPerMeasure; -static int _MIDI_TicksPerBeat; -static int _MIDI_TimeBase; -static int _MIDI_FPSecondsPerTick; -static unsigned _MIDI_TotalTime; -static int _MIDI_TotalTicks; -static int _MIDI_TotalBeats; -static int _MIDI_TotalMeasures; - -unsigned int _MIDI_PositionInTicks; -unsigned int _MIDI_GlobalPositionInTicks; - -static int _MIDI_Context; - -static int _MIDI_ActiveTracks; -static int _MIDI_TotalVolume = MIDI_MaxVolume; - -static int _MIDI_ChannelVolume[ NUM_MIDI_CHANNELS ]; -static int _MIDI_UserChannelVolume[ NUM_MIDI_CHANNELS ] = - { - 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256 - }; - -static midifuncs *_MIDI_Funcs = NULL; - -static int Reset = FALSE; - -int MIDI_Tempo = 120; - -char MIDI_PatchMap[ 128 ]; - - -/********************************************************************** - - Memory locked functions: - -**********************************************************************/ - - -/*--------------------------------------------------------------------- - Function: _MIDI_ReadNumber - - Reads a variable length number from a MIDI track. ----------------------------------------------------------------------*/ - -static int _MIDI_ReadNumber -( - void *from, - size_t size -) - -{ - unsigned char *FromPtr; - int value; - - if (size > 4) - { - size = 4; - } - - FromPtr = (unsigned char *)from; - - value = 0; - while (size--) - { - value <<= 8; - value += *FromPtr++; - } - - return(value); -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_ReadDelta - - Reads a variable length encoded delta delay time from the MIDI data. ----------------------------------------------------------------------*/ - -static int _MIDI_ReadDelta -( - track *ptr -) - -{ - int value; - unsigned char c; - - GET_NEXT_EVENT(ptr, value); - - if (value & 0x80) - { - value &= 0x7f; - do - { - GET_NEXT_EVENT(ptr, c); - value = (value << 7) + (c & 0x7f); - } - while (c & 0x80); - } - - return(value); -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_ResetTracks - - Sets the track pointers to the beginning of the song. ----------------------------------------------------------------------*/ - -static void _MIDI_ResetTracks -( - void -) - -{ - int i; - track *ptr; - - _MIDI_Tick = 0; - _MIDI_Beat = 1; - _MIDI_Measure = 1; - _MIDI_Time = 0; - _MIDI_BeatsPerMeasure = 4; - _MIDI_TicksPerBeat = _MIDI_Division; - _MIDI_TimeBase = 4; - - _MIDI_PositionInTicks = 0; - //_MIDI_GlobalPositionInTicks = 0; - _MIDI_ActiveTracks = 0; - _MIDI_Context = 0; - - ptr = _MIDI_TrackPtr; - for (i = 0; i < _MIDI_NumTracks; i++) - { - ptr->pos = ptr->start; - ptr->delay = _MIDI_ReadDelta(ptr); - ptr->active = ptr->EMIDI_IncludeTrack; - ptr->RunningStatus = 0; - ptr->currentcontext = 0; - ptr->context[ 0 ].loopstart = ptr->start; - ptr->context[ 0 ].loopcount = 0; - - if (ptr->active) - { - _MIDI_ActiveTracks++; - } - - ptr++; - } -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_AdvanceTick - - Increment tick counters. ----------------------------------------------------------------------*/ - -static void _MIDI_AdvanceTick -( - void -) - -{ - _MIDI_PositionInTicks++; - _MIDI_Time += _MIDI_FPSecondsPerTick; - - _MIDI_Tick++; - while (_MIDI_Tick > _MIDI_TicksPerBeat) - { - _MIDI_Tick -= _MIDI_TicksPerBeat; - _MIDI_Beat++; - } - while (_MIDI_Beat > _MIDI_BeatsPerMeasure) - { - _MIDI_Beat -= _MIDI_BeatsPerMeasure; - _MIDI_Measure++; - } -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_SysEx - - Interpret SysEx Event. ----------------------------------------------------------------------*/ - -static void _MIDI_SysEx -( - track *Track -) - -{ - int length; - - length = _MIDI_ReadDelta(Track); - Track->pos += length; -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_MetaEvent - - Interpret Meta Event. ----------------------------------------------------------------------*/ - -static void _MIDI_MetaEvent -( - track *Track -) - -{ - int command; - int length; - int denominator; - int tempo; - - GET_NEXT_EVENT(Track, command); - GET_NEXT_EVENT(Track, length); - - switch (command) - { - case MIDI_END_OF_TRACK : - Track->active = FALSE; - - _MIDI_ActiveTracks--; - break; - - case MIDI_TEMPO_CHANGE : - tempo = 60000000L / _MIDI_ReadNumber(Track->pos, 3); - MIDI_SetTempo(tempo); - break; - - case MIDI_TIME_SIGNATURE : - if ((_MIDI_Tick > 0) || (_MIDI_Beat > 1)) - { - _MIDI_Measure++; - } - - _MIDI_Tick = 0; - _MIDI_Beat = 1; - - _MIDI_BeatsPerMeasure = (int)*Track->pos; - denominator = (int)*(Track->pos + 1); - _MIDI_TimeBase = 1; - while (denominator > 0) - { - _MIDI_TimeBase += _MIDI_TimeBase; - denominator--; - } - _MIDI_TicksPerBeat = (_MIDI_Division * 4) / _MIDI_TimeBase; - break; - } - - Track->pos += length; -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_InterpretControllerInfo - - Interprets the MIDI controller info. ----------------------------------------------------------------------*/ - -static int _MIDI_InterpretControllerInfo -( - track *Track, - int TimeSet, - int channel, - int c1, - int c2 -) - -{ - track *trackptr; - int tracknum; - int loopcount; - - switch (c1) - { - case MIDI_MONO_MODE_ON : - Track->pos++; - break; - - case MIDI_VOLUME : - if (!Track->EMIDI_VolumeChange) - { - _MIDI_SetChannelVolume(channel, c2); - } - break; - - case EMIDI_INCLUDE_TRACK : - case EMIDI_EXCLUDE_TRACK : - break; - - case EMIDI_PROGRAM_CHANGE : - if (Track->EMIDI_ProgramChange) - { - _MIDI_Funcs->ProgramChange(channel, MIDI_PatchMap[ c2 & 0x7f ]); - } - break; - - case EMIDI_VOLUME_CHANGE : - if (Track->EMIDI_VolumeChange) - { - _MIDI_SetChannelVolume(channel, c2); - } - break; - - case EMIDI_CONTEXT_START : - break; - - case EMIDI_CONTEXT_END : - if ((Track->currentcontext == _MIDI_Context) || - (_MIDI_Context < 0) || - (Track->context[ _MIDI_Context ].pos == NULL)) - { - break; - } - - Track->currentcontext = _MIDI_Context; - Track->context[ 0 ].loopstart = Track->context[ _MIDI_Context ].loopstart; - Track->context[ 0 ].loopcount = Track->context[ _MIDI_Context ].loopcount; - Track->pos = Track->context[ _MIDI_Context ].pos; - Track->RunningStatus = Track->context[ _MIDI_Context ].RunningStatus; - - if (TimeSet) - { - break; - } - - _MIDI_Time = Track->context[ _MIDI_Context ].time; - _MIDI_FPSecondsPerTick = Track->context[ _MIDI_Context ].FPSecondsPerTick; - _MIDI_Tick = Track->context[ _MIDI_Context ].tick; - _MIDI_Beat = Track->context[ _MIDI_Context ].beat; - _MIDI_Measure = Track->context[ _MIDI_Context ].measure; - _MIDI_BeatsPerMeasure = Track->context[ _MIDI_Context ].BeatsPerMeasure; - _MIDI_TicksPerBeat = Track->context[ _MIDI_Context ].TicksPerBeat; - _MIDI_TimeBase = Track->context[ _MIDI_Context ].TimeBase; - TimeSet = TRUE; - break; - - case EMIDI_LOOP_START : - case EMIDI_SONG_LOOP_START : - if (c2 == 0) - { - loopcount = EMIDI_INFINITE; - } - else - { - loopcount = c2; - } - - if (c1 == EMIDI_SONG_LOOP_START) - { - trackptr = _MIDI_TrackPtr; - tracknum = _MIDI_NumTracks; - } - else - { - trackptr = Track; - tracknum = 1; - } - - while (tracknum > 0) - { - trackptr->context[ 0 ].loopcount = loopcount; - trackptr->context[ 0 ].pos = trackptr->pos; - trackptr->context[ 0 ].loopstart = trackptr->pos; - trackptr->context[ 0 ].RunningStatus = trackptr->RunningStatus; - trackptr->context[ 0 ].active = trackptr->active; - trackptr->context[ 0 ].delay = trackptr->delay; - trackptr->context[ 0 ].time = _MIDI_Time; - trackptr->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; - trackptr->context[ 0 ].tick = _MIDI_Tick; - trackptr->context[ 0 ].beat = _MIDI_Beat; - trackptr->context[ 0 ].measure = _MIDI_Measure; - trackptr->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; - trackptr->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat; - trackptr->context[ 0 ].TimeBase = _MIDI_TimeBase; - trackptr++; - tracknum--; - } - break; - - case EMIDI_LOOP_END : - case EMIDI_SONG_LOOP_END : - if ((c2 != EMIDI_END_LOOP_VALUE) || - (Track->context[ 0 ].loopstart == NULL) || - (Track->context[ 0 ].loopcount == 0)) - { - break; - } - - if (c1 == EMIDI_SONG_LOOP_END) - { - trackptr = _MIDI_TrackPtr; - tracknum = _MIDI_NumTracks; - _MIDI_ActiveTracks = 0; - } - else - { - trackptr = Track; - tracknum = 1; - _MIDI_ActiveTracks--; - } - - while (tracknum > 0) - { - if (trackptr->context[ 0 ].loopcount != EMIDI_INFINITE) - { - trackptr->context[ 0 ].loopcount--; - } - - trackptr->pos = trackptr->context[ 0 ].loopstart; - trackptr->RunningStatus = trackptr->context[ 0 ].RunningStatus; - trackptr->delay = trackptr->context[ 0 ].delay; - trackptr->active = trackptr->context[ 0 ].active; - if (trackptr->active) - { - _MIDI_ActiveTracks++; - } - - if (!TimeSet) - { - _MIDI_Time = trackptr->context[ 0 ].time; - _MIDI_FPSecondsPerTick = trackptr->context[ 0 ].FPSecondsPerTick; - _MIDI_Tick = trackptr->context[ 0 ].tick; - _MIDI_Beat = trackptr->context[ 0 ].beat; - _MIDI_Measure = trackptr->context[ 0 ].measure; - _MIDI_BeatsPerMeasure = trackptr->context[ 0 ].BeatsPerMeasure; - _MIDI_TicksPerBeat = trackptr->context[ 0 ].TicksPerBeat; - _MIDI_TimeBase = trackptr->context[ 0 ].TimeBase; - TimeSet = TRUE; - } - - trackptr++; - tracknum--; - } - break; - - default : - if (_MIDI_Funcs->ControlChange) - { - _MIDI_Funcs->ControlChange(channel, c1, c2); - } - } - - return TimeSet; -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_ServiceRoutine - - Task that interperates the MIDI data. ----------------------------------------------------------------------*/ - -static int _MIDI_ServiceRoutine(void) -{ - int event; - int channel; - int command; - track *Track; - int tracknum; - int status; - int c1 = 0; - int c2 = 0; - int TimeSet = FALSE; - - if (_MIDI_SongActive) - { - Track = _MIDI_TrackPtr; - tracknum = 0; - while (tracknum < _MIDI_NumTracks) - { - while ((Track->active) && (Track->delay == 0)) - { - GET_NEXT_EVENT(Track, event); - - if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) - { - switch (event) - { - case MIDI_SYSEX : - case MIDI_SYSEX_CONTINUE : - _MIDI_SysEx(Track); - break; - - case MIDI_META_EVENT : - _MIDI_MetaEvent(Track); - break; - } - - if (Track->active) - { - Track->delay = _MIDI_ReadDelta(Track); - } - continue; - } - - if (event & MIDI_RUNNING_STATUS) - { - Track->RunningStatus = event; - } - else - { - event = Track->RunningStatus; - Track->pos--; - } - - channel = GET_MIDI_CHANNEL(event); - command = GET_MIDI_COMMAND(event); - - if (_MIDI_CommandLengths[ command ] > 0) - { - GET_NEXT_EVENT(Track, c1); - if (_MIDI_CommandLengths[ command ] > 1) - { - GET_NEXT_EVENT(Track, c2); - } - } - - if (_MIDI_RerouteFunctions[ channel ] != NULL) - { - status = _MIDI_RerouteFunctions[ channel ](event, c1, c2); - - if (status == MIDI_DONT_PLAY) - { - Track->delay = _MIDI_ReadDelta(Track); - continue; - } - } - - switch (command) - { - case MIDI_NOTE_OFF : - if (_MIDI_Funcs->NoteOff) - { - _MIDI_Funcs->NoteOff(channel, c1, c2); - } - break; - - case MIDI_NOTE_ON : - if (_MIDI_Funcs->NoteOn) - { - _MIDI_Funcs->NoteOn(channel, c1, c2); - } - break; - - case MIDI_POLY_AFTER_TCH : - if (_MIDI_Funcs->PolyAftertouch) - { - _MIDI_Funcs->PolyAftertouch(channel, c1, c2); - } - break; - - case MIDI_CONTROL_CHANGE : - TimeSet = _MIDI_InterpretControllerInfo(Track, TimeSet, channel, c1, c2); - break; - - case MIDI_PROGRAM_CHANGE : - if ((_MIDI_Funcs->ProgramChange) && (!Track->EMIDI_ProgramChange)) - { - _MIDI_Funcs->ProgramChange(channel, MIDI_PatchMap[ c1 & 0x7f ]); - } - break; - - case MIDI_AFTER_TOUCH : - if (_MIDI_Funcs->ChannelAftertouch) - { - _MIDI_Funcs->ChannelAftertouch(channel, c1); - } - break; - - case MIDI_PITCH_BEND : - if (_MIDI_Funcs->PitchBend) - { - _MIDI_Funcs->PitchBend(channel, c1, c2); - } - break; - - default : - break; - } - - Track->delay = _MIDI_ReadDelta(Track); - } - - Track->delay--; - Track++; - tracknum++; - - if (_MIDI_ActiveTracks == 0) - { - _MIDI_ResetTracks(); - if (_MIDI_Loop) - { - tracknum = 0; - Track = _MIDI_TrackPtr; - } - else - { - _MIDI_SongActive = FALSE; - break; - } - } - } - - _MIDI_AdvanceTick(); - _MIDI_GlobalPositionInTicks++; - } - return 0; -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_SendControlChange - - Sends a control change to the proper device ----------------------------------------------------------------------*/ - -static int _MIDI_SendControlChange -( - int channel, - int c1, - int c2 -) - -{ - int status; - - if (_MIDI_RerouteFunctions[ channel ] != NULL) - { - status = _MIDI_RerouteFunctions[ channel ](0xB0 + channel, - c1, c2); - if (status == MIDI_DONT_PLAY) - { - return(MIDI_Ok); - } - } - - if (_MIDI_Funcs == NULL) - { - return(MIDI_Error); - } - - if (_MIDI_Funcs->ControlChange == NULL) - { - return(MIDI_Error); - } - - _MIDI_Funcs->ControlChange(channel, c1, c2); - - return(MIDI_Ok); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_RerouteMidiChannel - - Sets callback function to reroute MIDI commands from specified - function. ----------------------------------------------------------------------*/ - -void MIDI_RerouteMidiChannel -( - int channel, - int(*function)(int event, int c1, int c2) -) - -{ - if ((channel >= 1) && (channel <= 16)) - { - _MIDI_RerouteFunctions[ channel - 1 ] = function; - } -} - - -/*--------------------------------------------------------------------- - Function: MIDI_AllNotesOff - - Sends all notes off commands on all midi channels. ----------------------------------------------------------------------*/ - -int MIDI_AllNotesOff -( - void -) - -{ - int channel; - - for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) - { - _MIDI_SendControlChange(channel, 0x40, 0); - _MIDI_SendControlChange(channel, MIDI_ALL_NOTES_OFF, 0); - _MIDI_SendControlChange(channel, 0x78, 0); - } - - return(MIDI_Ok); -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_SetChannelVolume - - Sets the volume of the specified midi channel. ----------------------------------------------------------------------*/ - -static void _MIDI_SetChannelVolume -( - int channel, - int volume -) - -{ - int status; - int remotevolume; - - _MIDI_ChannelVolume[ channel ] = volume; - - if (_MIDI_RerouteFunctions[ channel ] != NULL) - { - remotevolume = volume * _MIDI_TotalVolume; - remotevolume *= _MIDI_UserChannelVolume[ channel ]; - remotevolume /= MIDI_MaxVolume; - remotevolume >>= 8; - - status = _MIDI_RerouteFunctions[ channel ](0xB0 + channel, - MIDI_VOLUME, remotevolume); - if (status == MIDI_DONT_PLAY) - { - return; - } - } - - if (_MIDI_Funcs == NULL) - { - return; - } - - if (_MIDI_Funcs->ControlChange == NULL) - { - return; - } - - // For user volume - volume *= _MIDI_UserChannelVolume[ channel ]; - - if (_MIDI_Funcs->SetVolume == NULL) - { - volume *= _MIDI_TotalVolume; - volume /= MIDI_MaxVolume; - } - - // For user volume - volume >>= 8; - - _MIDI_Funcs->ControlChange(channel, MIDI_VOLUME, volume); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_SetUserChannelVolume - - Sets the volume of the specified midi channel. ----------------------------------------------------------------------*/ - -void MIDI_SetUserChannelVolume -( - int channel, - int volume -) - -{ - // Convert channel from 1-16 to 0-15 - channel--; - - volume = max(0, volume); - volume = min(volume, 256); - - if ((channel >= 0) && (channel < NUM_MIDI_CHANNELS)) - { - _MIDI_UserChannelVolume[ channel ] = volume; - _MIDI_SetChannelVolume(channel, _MIDI_ChannelVolume[ channel ]); - } -} - - -/*--------------------------------------------------------------------- - Function: MIDI_ResetUserChannelVolume - - Sets the volume of the specified midi channel. ----------------------------------------------------------------------*/ - -void MIDI_ResetUserChannelVolume -( - void -) - -{ - int channel; - - for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) - { - _MIDI_UserChannelVolume[ channel ] = 256; - } - - _MIDI_SendChannelVolumes(); -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_SendChannelVolumes - - Sets the volume on all the midi channels. ----------------------------------------------------------------------*/ - -static void _MIDI_SendChannelVolumes -( - void -) - -{ - int channel; - - for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) - { - _MIDI_SetChannelVolume(channel, _MIDI_ChannelVolume[ channel ]); - } -} - - -/*--------------------------------------------------------------------- - Function: MIDI_Reset - - Resets the MIDI device to General Midi defaults. ----------------------------------------------------------------------*/ - -int MIDI_Reset -( - void -) - -{ - int channel; - - MIDI_AllNotesOff(); - - for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) - { - _MIDI_SendControlChange(channel, MIDI_RESET_ALL_CONTROLLERS, 0); - _MIDI_SendControlChange(channel, MIDI_RPN_MSB, MIDI_PITCHBEND_MSB); - _MIDI_SendControlChange(channel, MIDI_RPN_LSB, MIDI_PITCHBEND_LSB); - _MIDI_SendControlChange(channel, MIDI_DATAENTRY_MSB, 2); /* Pitch Bend Sensitivity MSB */ - _MIDI_SendControlChange(channel, MIDI_DATAENTRY_LSB, 0); /* Pitch Bend Sensitivity LSB */ - _MIDI_ChannelVolume[ channel ] = GENMIDI_DefaultVolume; - } - - _MIDI_SendChannelVolumes(); - - Reset = TRUE; - - return(MIDI_Ok); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_SetVolume - - Sets the total volume of the music. ----------------------------------------------------------------------*/ - -int MIDI_SetVolume -( - int volume -) - -{ - int i; - - if (_MIDI_Funcs == NULL) - { - return(MIDI_NullMidiModule); - } - - volume = min(MIDI_MaxVolume, volume); - volume = max(0, volume); - - _MIDI_TotalVolume = volume; - - if (_MIDI_Funcs->SetVolume) - { - _MIDI_Funcs->SetVolume(volume); - - for (i = 0; i < NUM_MIDI_CHANNELS; i++) - { - if (_MIDI_RerouteFunctions[ i ] != NULL) - { - _MIDI_SetChannelVolume(i, _MIDI_ChannelVolume[ i ]); - } - } - } - else - { - _MIDI_SendChannelVolumes(); - } - - return(MIDI_Ok); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_GetVolume - - Returns the total volume of the music. ----------------------------------------------------------------------*/ - -int MIDI_GetVolume -( - void -) - -{ - int volume; - - if (_MIDI_Funcs == NULL) - { - return(MIDI_NullMidiModule); - } - - if (_MIDI_Funcs->GetVolume) - { - volume = _MIDI_Funcs->GetVolume(); - } - else - { - volume = _MIDI_TotalVolume; - } - - return(volume); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_SetContext - - Sets the song context. ----------------------------------------------------------------------*/ - -void MIDI_SetContext -( - int context -) - -{ - if ((context > 0) && (context < EMIDI_NUM_CONTEXTS)) - { - _MIDI_Context = context; - } -} - - -/*--------------------------------------------------------------------- - Function: MIDI_GetContext - - Returns the current song context. ----------------------------------------------------------------------*/ - -int MIDI_GetContext -( - void -) - -{ - return _MIDI_Context; -} - - -/*--------------------------------------------------------------------- - Function: MIDI_SetLoopFlag - - Sets whether the song should loop when finished or not. ----------------------------------------------------------------------*/ - -void MIDI_SetLoopFlag -( - int loopflag -) - -{ - _MIDI_Loop = loopflag; -} - - -/*--------------------------------------------------------------------- - Function: MIDI_ContinueSong - - Continues playback of a paused song. ----------------------------------------------------------------------*/ - -void MIDI_ContinueSong -( - void -) - -{ - if (_MIDI_SongLoaded) - { - _MIDI_SongActive = TRUE; - MPU_Unpause(); - } -} - - -/*--------------------------------------------------------------------- - Function: MIDI_PauseSong - - Pauses playback of the current song. ----------------------------------------------------------------------*/ - -void MIDI_PauseSong -( - void -) - -{ - if (_MIDI_SongLoaded) - { - _MIDI_SongActive = FALSE; - MIDI_AllNotesOff(); - MPU_Pause(); - } -} - - -/*--------------------------------------------------------------------- - Function: MIDI_SongPlaying - - Returns whether a song is playing or not. ----------------------------------------------------------------------*/ - -int MIDI_SongPlaying -( - void -) - -{ - return(_MIDI_SongActive); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_SetMidiFuncs - - Selects the routines that send the MIDI data to the music device. ----------------------------------------------------------------------*/ - -void MIDI_SetMidiFuncs -( - midifuncs *funcs -) - -{ - _MIDI_Funcs = funcs; -} - - -/*--------------------------------------------------------------------- - Function: MIDI_StopSong - - Stops playback of the currently playing song. ----------------------------------------------------------------------*/ - -void MIDI_StopSong -( - void -) - -{ - if (_MIDI_SongLoaded) - { - _MIDI_SongActive = FALSE; - _MIDI_SongLoaded = FALSE; - - MIDI_Reset(); - _MIDI_ResetTracks(); - - if (_MIDI_Funcs->ReleasePatches) - { - _MIDI_Funcs->ReleasePatches(); - } - - USRHOOKS_FreeMem(_MIDI_TrackPtr); - - _MIDI_TrackPtr = NULL; - _MIDI_NumTracks = 0; - _MIDI_TrackMemSize = 0; - - _MIDI_TotalTime = 0; - _MIDI_TotalTicks = 0; - _MIDI_TotalBeats = 0; - _MIDI_TotalMeasures = 0; - - MPU_Reset(); - } -} - - -/*--------------------------------------------------------------------- - Function: MIDI_PlaySong - - Begins playback of a MIDI song. ----------------------------------------------------------------------*/ - -int MIDI_PlaySong -( - unsigned char *song, - int loopflag -) - -{ - int numtracks; - int format; - int headersize; - int tracklength; - track *CurrentTrack; - unsigned char *ptr; - int status; - - if (_MIDI_SongLoaded) - { - MIDI_StopSong(); - } - - MPU_Init(MUSIC_SoundDevice); - - _MIDI_Loop = loopflag; - - if (_MIDI_Funcs == NULL) - { - return(MIDI_NullMidiModule); - } - - if (*(unsigned int *)song != MIDI_HEADER_SIGNATURE) - { - return(MIDI_InvalidMidiFile); - } - - song += 4; - - headersize = _MIDI_ReadNumber(song, 4); - song += 4; - format = _MIDI_ReadNumber(song, 2); - _MIDI_NumTracks = _MIDI_ReadNumber(song + 2, 2); - _MIDI_Division = _MIDI_ReadNumber(song + 4, 2); - if (_MIDI_Division < 0) - { - // If a SMPTE time division is given, just set to 96 so no errors occur - _MIDI_Division = 96; - } - - if (format > MAX_FORMAT) - { - return(MIDI_UnknownMidiFormat); - } - - ptr = song + headersize; - - if (_MIDI_NumTracks == 0) - { - return(MIDI_NoTracks); - } - - _MIDI_TrackMemSize = _MIDI_NumTracks * sizeof(track); - status = USRHOOKS_GetMem((void**)&_MIDI_TrackPtr, _MIDI_TrackMemSize); - if (status != USRHOOKS_Ok) - { - return(MIDI_NoMemory); - } - - CurrentTrack = _MIDI_TrackPtr; - numtracks = _MIDI_NumTracks; - while (numtracks--) - { - if (*(unsigned int *)ptr != MIDI_TRACK_SIGNATURE) - { - USRHOOKS_FreeMem(_MIDI_TrackPtr); - - _MIDI_TrackPtr = NULL; - _MIDI_TrackMemSize = 0; - - return(MIDI_InvalidTrack); - } - - tracklength = _MIDI_ReadNumber(ptr + 4, 4); - ptr += 8; - CurrentTrack->start = ptr; - ptr += tracklength; - CurrentTrack++; - } - - if (_MIDI_Funcs->GetVolume != NULL) - { - _MIDI_TotalVolume = _MIDI_Funcs->GetVolume(); - } - - _MIDI_InitEMIDI(); - - if (_MIDI_Funcs->LoadPatch) - { - MIDI_LoadTimbres(); - } - - _MIDI_ResetTracks(); - - if (!Reset) - { - MIDI_Reset(); - } - - Reset = FALSE; - - MIDI_SetDivision(_MIDI_Division); - //MIDI_SetTempo( 120 ); - - _MIDI_SongLoaded = TRUE; - _MIDI_SongActive = TRUE; - - while (_MPU_BuffersWaiting < 4) _MIDI_ServiceRoutine(); - MPU_BeginPlayback(); - - return(MIDI_Ok); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_SetTempo - - Sets the song tempo. ----------------------------------------------------------------------*/ - -void MIDI_SetTempo -( - int tempo -) - -{ - int tickspersecond; - - MIDI_Tempo = tempo; - tickspersecond = ((tempo) * _MIDI_Division) / 60; - _MIDI_FPSecondsPerTick = (1 << TIME_PRECISION) / tickspersecond; - MPU_SetTempo(tempo); -} - -void MIDI_SetDivision(int division) -{ - MPU_SetDivision(division); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_GetTempo - - Returns the song tempo. ----------------------------------------------------------------------*/ - -int MIDI_GetTempo -( - void -) - -{ - return(MIDI_Tempo); -} - - -/*--------------------------------------------------------------------- - Function: _MIDI_ProcessNextTick - - Sets the position of the song pointer. ----------------------------------------------------------------------*/ - -static int _MIDI_ProcessNextTick -( - void -) - -{ - int event; - int channel; - int command; - track *Track; - int tracknum; - int status; - int c1 = 0; - int c2 = 0; - int TimeSet = FALSE; - - Track = _MIDI_TrackPtr; - tracknum = 0; - while ((tracknum < _MIDI_NumTracks) && (Track != NULL)) - { - while ((Track->active) && (Track->delay == 0)) - { - GET_NEXT_EVENT(Track, event); - - if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) - { - switch (event) - { - case MIDI_SYSEX : - case MIDI_SYSEX_CONTINUE : - _MIDI_SysEx(Track); - break; - - case MIDI_META_EVENT : - _MIDI_MetaEvent(Track); - break; - } - - if (Track->active) - { - Track->delay = _MIDI_ReadDelta(Track); - } - - continue; - } - - if (event & MIDI_RUNNING_STATUS) - { - Track->RunningStatus = event; - } - else - { - event = Track->RunningStatus; - Track->pos--; - } - - channel = GET_MIDI_CHANNEL(event); - command = GET_MIDI_COMMAND(event); - - if (_MIDI_CommandLengths[ command ] > 0) - { - GET_NEXT_EVENT(Track, c1); - if (_MIDI_CommandLengths[ command ] > 1) - { - GET_NEXT_EVENT(Track, c2); - } - } - - if (_MIDI_RerouteFunctions[ channel ] != NULL) - { - status = _MIDI_RerouteFunctions[ channel ](event, c1, c2); - - if (status == MIDI_DONT_PLAY) - { - Track->delay = _MIDI_ReadDelta(Track); - continue; - } - } - - switch (command) - { - case MIDI_NOTE_OFF : - break; - - case MIDI_NOTE_ON : - break; - - case MIDI_POLY_AFTER_TCH : - if (_MIDI_Funcs->PolyAftertouch) - { - _MIDI_Funcs->PolyAftertouch(channel, c1, c2); - } - break; - - case MIDI_CONTROL_CHANGE : - TimeSet = _MIDI_InterpretControllerInfo(Track, TimeSet, - channel, c1, c2); - break; - - case MIDI_PROGRAM_CHANGE : - if ((_MIDI_Funcs->ProgramChange) && - (!Track->EMIDI_ProgramChange)) - { - _MIDI_Funcs->ProgramChange(channel, c1); - } - break; - - case MIDI_AFTER_TOUCH : - if (_MIDI_Funcs->ChannelAftertouch) - { - _MIDI_Funcs->ChannelAftertouch(channel, c1); - } - break; - - case MIDI_PITCH_BEND : - if (_MIDI_Funcs->PitchBend) - { - _MIDI_Funcs->PitchBend(channel, c1, c2); - } - break; - - default : - break; - } - - Track->delay = _MIDI_ReadDelta(Track); - } - - Track->delay--; - Track++; - tracknum++; - - if (_MIDI_ActiveTracks == 0) - { - break; - } - } - - _MIDI_AdvanceTick(); - - return(TimeSet); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_SetSongTick - - Sets the position of the song pointer. ----------------------------------------------------------------------*/ - -void MIDI_SetSongTick -( - unsigned int PositionInTicks -) - -{ - if (!_MIDI_SongLoaded) - { - return; - } - - MIDI_PauseSong(); - - if (PositionInTicks < _MIDI_PositionInTicks) - { - _MIDI_ResetTracks(); - MIDI_Reset(); - } - - while (_MIDI_PositionInTicks < PositionInTicks) - { - if (_MIDI_ProcessNextTick()) - { - break; - } - if (_MIDI_ActiveTracks == 0) - { - _MIDI_ResetTracks(); - if (!_MIDI_Loop) - { - return; - } - break; - } - } - - MIDI_SetVolume(_MIDI_TotalVolume); - MIDI_ContinueSong(); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_SetSongTime - - Sets the position of the song pointer. ----------------------------------------------------------------------*/ - -void MIDI_SetSongTime -( - unsigned int milliseconds -) - -{ - unsigned int mil; - unsigned int sec; - unsigned int newtime; - - if (!_MIDI_SongLoaded) - { - return; - } - - MIDI_PauseSong(); - - mil = ((milliseconds % 1000) << TIME_PRECISION) / 1000; - sec = (milliseconds / 1000) << TIME_PRECISION; - newtime = sec + mil; - - if (newtime < _MIDI_Time) - { - _MIDI_ResetTracks(); - MIDI_Reset(); - } - - while (_MIDI_Time < newtime) - { - if (_MIDI_ProcessNextTick()) - { - break; - } - if (_MIDI_ActiveTracks == 0) - { - _MIDI_ResetTracks(); - if (!_MIDI_Loop) - { - return; - } - break; - } - } - - MIDI_SetVolume(_MIDI_TotalVolume); - MIDI_ContinueSong(); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_SetSongPosition - - Sets the position of the song pointer. ----------------------------------------------------------------------*/ - -void MIDI_SetSongPosition -( - int measure, - int beat, - int tick -) - -{ - unsigned int pos; - - if (!_MIDI_SongLoaded) - { - return; - } - - MIDI_PauseSong(); - - pos = RELATIVE_BEAT(measure, beat, tick); - - if (pos < (unsigned int)RELATIVE_BEAT(_MIDI_Measure, _MIDI_Beat, _MIDI_Tick)) - { - _MIDI_ResetTracks(); - MIDI_Reset(); - } - - while ((unsigned int)RELATIVE_BEAT(_MIDI_Measure, _MIDI_Beat, _MIDI_Tick) < pos) - { - if (_MIDI_ProcessNextTick()) - { - break; - } - if (_MIDI_ActiveTracks == 0) - { - _MIDI_ResetTracks(); - if (!_MIDI_Loop) - { - return; - } - break; - } - } - - MIDI_SetVolume(_MIDI_TotalVolume); - MIDI_ContinueSong(); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_GetSongPosition - - Returns the position of the song pointer in Measures, beats, ticks. ----------------------------------------------------------------------*/ - -void MIDI_GetSongPosition -( - songposition *pos -) - -{ - unsigned int mil; - unsigned int sec; - - mil = (_MIDI_Time & ((1 << TIME_PRECISION) - 1)) * 1000; - sec = _MIDI_Time >> TIME_PRECISION; - pos->milliseconds = (mil >> TIME_PRECISION) + (sec * 1000); - pos->tickposition = _MIDI_PositionInTicks; - pos->measure = _MIDI_Measure; - pos->beat = _MIDI_Beat; - pos->tick = _MIDI_Tick; -} - - -/*--------------------------------------------------------------------- - Function: MIDI_GetSongLength - - Returns the length of the song. ----------------------------------------------------------------------*/ - -void MIDI_GetSongLength -( - songposition *pos -) - -{ - unsigned int mil; - unsigned int sec; - - mil = (_MIDI_TotalTime & ((1 << TIME_PRECISION) - 1)) * 1000; - sec = _MIDI_TotalTime >> TIME_PRECISION; - - pos->milliseconds = (mil >> TIME_PRECISION) + (sec * 1000); - pos->measure = _MIDI_TotalMeasures; - pos->beat = _MIDI_TotalBeats; - pos->tick = _MIDI_TotalTicks; - pos->tickposition = 0; -} - - -/*--------------------------------------------------------------------- - Function: MIDI_InitEMIDI - - Sets up the EMIDI ----------------------------------------------------------------------*/ - -static void _MIDI_InitEMIDI -( - void -) - -{ - int event; - int command; - int channel; - int length; - int IncludeFound; - track *Track; - int tracknum; - int type; - int c1; - int c2; - - type = EMIDI_GeneralMIDI; - - _MIDI_ResetTracks(); - - _MIDI_TotalTime = 0; - _MIDI_TotalTicks = 0; - _MIDI_TotalBeats = 0; - _MIDI_TotalMeasures = 0; - - Track = _MIDI_TrackPtr; - tracknum = 0; - while ((tracknum < _MIDI_NumTracks) && (Track != NULL)) - { - _MIDI_Tick = 0; - _MIDI_Beat = 1; - _MIDI_Measure = 1; - _MIDI_Time = 0; - _MIDI_BeatsPerMeasure = 4; - _MIDI_TicksPerBeat = _MIDI_Division; - _MIDI_TimeBase = 4; - - _MIDI_PositionInTicks = 0; - _MIDI_ActiveTracks = 0; - _MIDI_Context = -1; - - Track->RunningStatus = 0; - Track->active = TRUE; - - Track->EMIDI_ProgramChange = FALSE; - Track->EMIDI_VolumeChange = FALSE; - Track->EMIDI_IncludeTrack = TRUE; - - memset(Track->context, 0, sizeof(Track->context)); - - while (Track->delay > 0) - { - _MIDI_AdvanceTick(); - Track->delay--; - } - - IncludeFound = FALSE; - while (Track->active) - { - GET_NEXT_EVENT(Track, event); - - if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) - { - switch (event) - { - case MIDI_SYSEX : - case MIDI_SYSEX_CONTINUE : - _MIDI_SysEx(Track); - break; - - case MIDI_META_EVENT : - _MIDI_MetaEvent(Track); - break; - } - - if (Track->active) - { - Track->delay = _MIDI_ReadDelta(Track); - while (Track->delay > 0) - { - _MIDI_AdvanceTick(); - Track->delay--; - } - } - - continue; - } - - if (event & MIDI_RUNNING_STATUS) - { - Track->RunningStatus = event; - } - else - { - event = Track->RunningStatus; - Track->pos--; - } - - channel = GET_MIDI_CHANNEL(event); - command = GET_MIDI_COMMAND(event); - length = _MIDI_CommandLengths[ command ]; - - if (command == MIDI_CONTROL_CHANGE) - { - if (*Track->pos == MIDI_MONO_MODE_ON) - { - length++; - } - GET_NEXT_EVENT(Track, c1); - GET_NEXT_EVENT(Track, c2); - length -= 2; - - switch (c1) - { - case EMIDI_LOOP_START : - case EMIDI_SONG_LOOP_START : - if (c2 == 0) - { - Track->context[ 0 ].loopcount = EMIDI_INFINITE; - } - else - { - Track->context[ 0 ].loopcount = c2; - } - - Track->context[ 0 ].pos = Track->pos; - Track->context[ 0 ].loopstart = Track->pos; - Track->context[ 0 ].RunningStatus = Track->RunningStatus; - Track->context[ 0 ].time = _MIDI_Time; - Track->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; - Track->context[ 0 ].tick = _MIDI_Tick; - Track->context[ 0 ].beat = _MIDI_Beat; - Track->context[ 0 ].measure = _MIDI_Measure; - Track->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; - Track->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat; - Track->context[ 0 ].TimeBase = _MIDI_TimeBase; - break; - - case EMIDI_LOOP_END : - case EMIDI_SONG_LOOP_END : - if (c2 == EMIDI_END_LOOP_VALUE) - { - Track->context[ 0 ].loopstart = NULL; - Track->context[ 0 ].loopcount = 0; - } - break; - - case EMIDI_INCLUDE_TRACK : - if (EMIDI_AffectsCurrentCard(c2, type)) - { - //printf( "Include track %d on card %d\n", tracknum, c2 ); - IncludeFound = TRUE; - Track->EMIDI_IncludeTrack = TRUE; - } - else if (!IncludeFound) - { - //printf( "Track excluded %d on card %d\n", tracknum, c2 ); - IncludeFound = TRUE; - Track->EMIDI_IncludeTrack = FALSE; - } - break; - - case EMIDI_EXCLUDE_TRACK : - if (EMIDI_AffectsCurrentCard(c2, type)) - { - //printf( "Exclude track %d on card %d\n", tracknum, c2 ); - Track->EMIDI_IncludeTrack = FALSE; - } - break; - - case EMIDI_PROGRAM_CHANGE : - if (!Track->EMIDI_ProgramChange) - //printf( "Program change on track %d\n", tracknum ); - Track->EMIDI_ProgramChange = TRUE; - break; - - case EMIDI_VOLUME_CHANGE : - if (!Track->EMIDI_VolumeChange) - //printf( "Volume change on track %d\n", tracknum ); - Track->EMIDI_VolumeChange = TRUE; - break; - - case EMIDI_CONTEXT_START : - if ((c2 > 0) && (c2 < EMIDI_NUM_CONTEXTS)) - { - Track->context[ c2 ].pos = Track->pos; - Track->context[ c2 ].loopstart = Track->context[ 0 ].loopstart; - Track->context[ c2 ].loopcount = Track->context[ 0 ].loopcount; - Track->context[ c2 ].RunningStatus = Track->RunningStatus; - Track->context[ c2 ].time = _MIDI_Time; - Track->context[ c2 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; - Track->context[ c2 ].tick = _MIDI_Tick; - Track->context[ c2 ].beat = _MIDI_Beat; - Track->context[ c2 ].measure = _MIDI_Measure; - Track->context[ c2 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; - Track->context[ c2 ].TicksPerBeat = _MIDI_TicksPerBeat; - Track->context[ c2 ].TimeBase = _MIDI_TimeBase; - } - break; - - case EMIDI_CONTEXT_END : - break; - } - } - - Track->pos += length; - Track->delay = _MIDI_ReadDelta(Track); - - while (Track->delay > 0) - { - _MIDI_AdvanceTick(); - Track->delay--; - } - } - - _MIDI_TotalTime = max(_MIDI_TotalTime, _MIDI_Time); - if (RELATIVE_BEAT(_MIDI_Measure, _MIDI_Beat, _MIDI_Tick) > - RELATIVE_BEAT(_MIDI_TotalMeasures, _MIDI_TotalBeats, - _MIDI_TotalTicks)) - { - _MIDI_TotalTicks = _MIDI_Tick; - _MIDI_TotalBeats = _MIDI_Beat; - _MIDI_TotalMeasures = _MIDI_Measure; - } - - Track++; - tracknum++; - } - - _MIDI_ResetTracks(); -} - - -/*--------------------------------------------------------------------- - Function: MIDI_LoadTimbres - - Preloads the timbres on cards that use patch-caching. ----------------------------------------------------------------------*/ - -void MIDI_LoadTimbres -( - void -) - -{ - int event; - int command; - int channel; - int length; - int Finished; - track *Track; - int tracknum; - - Track = _MIDI_TrackPtr; - tracknum = 0; - while ((tracknum < _MIDI_NumTracks) && (Track != NULL)) - { - Finished = FALSE; - while (!Finished) - { - GET_NEXT_EVENT(Track, event); - - if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) - { - switch (event) - { - case MIDI_SYSEX : - case MIDI_SYSEX_CONTINUE : - length = _MIDI_ReadDelta(Track); - Track->pos += length; - break; - - case MIDI_META_EVENT : - GET_NEXT_EVENT(Track, command); - GET_NEXT_EVENT(Track, length); - - if (command == MIDI_END_OF_TRACK) - { - Finished = TRUE; - } - - Track->pos += length; - break; - } - - if (!Finished) - { - _MIDI_ReadDelta(Track); - } - - continue; - } - - if (event & MIDI_RUNNING_STATUS) - { - Track->RunningStatus = event; - } - else - { - event = Track->RunningStatus; - Track->pos--; - } - - channel = GET_MIDI_CHANNEL(event); - command = GET_MIDI_COMMAND(event); - length = _MIDI_CommandLengths[ command ]; - - if (command == MIDI_CONTROL_CHANGE) - { - if (*Track->pos == MIDI_MONO_MODE_ON) - { - length++; - } - - if (*Track->pos == EMIDI_PROGRAM_CHANGE) - { - _MIDI_Funcs->LoadPatch(*(Track->pos + 1)); - } - } - - if (channel == MIDI_RHYTHM_CHANNEL) - { - if (command == MIDI_NOTE_ON) - { - _MIDI_Funcs->LoadPatch(128 + *Track->pos); - } - } - else - { - if (command == MIDI_PROGRAM_CHANGE) - { - _MIDI_Funcs->LoadPatch(*Track->pos); - } - } - Track->pos += length; - _MIDI_ReadDelta(Track); - } - Track++; - tracknum++; - } - - _MIDI_ResetTracks(); -} - - -void MIDI_UpdateMusic(void) -{ - if (!_MIDI_SongLoaded || !_MIDI_SongActive) return; - while (_MPU_BuffersWaiting < 4) _MIDI_ServiceRoutine(); -} - +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Modifications for JonoF's port by Jonathon Fowler (jonof@edgenetwk.com) +*/ +/********************************************************************** + module: MIDI.C + + author: James R. Dose + date: May 25, 1994 + + Midi song file playback routines. + + (c) Copyright 1994 James R. Dose. All Rights Reserved. +**********************************************************************/ + +#include +#include +#include "standard.h" +#include "usrhooks.h" +#include "music.h" +#include "_midi.h" +#include "midi.h" +#include "mpu401.h" + +#define WIN32_LEAN_AND_MEAN +#include + +extern int MUSIC_SoundDevice; + +static const int _MIDI_CommandLengths[ NUM_MIDI_CHANNELS ] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0 +}; + +static int(*_MIDI_RerouteFunctions[ NUM_MIDI_CHANNELS ]) +( + int event, + int c1, + int c2 +) = +{ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static track *_MIDI_TrackPtr = NULL; +static int _MIDI_TrackMemSize; +static int _MIDI_NumTracks; + +static int _MIDI_SongActive = FALSE; +static int _MIDI_SongLoaded = FALSE; +static int _MIDI_Loop = FALSE; + +static int _MIDI_Division; +static int _MIDI_Tick = 0; +static int _MIDI_Beat = 1; +static int _MIDI_Measure = 1; +static unsigned _MIDI_Time; +static int _MIDI_BeatsPerMeasure; +static int _MIDI_TicksPerBeat; +static int _MIDI_TimeBase; +static int _MIDI_FPSecondsPerTick; +static unsigned _MIDI_TotalTime; +static int _MIDI_TotalTicks; +static int _MIDI_TotalBeats; +static int _MIDI_TotalMeasures; + +unsigned int _MIDI_PositionInTicks; +unsigned int _MIDI_GlobalPositionInTicks; + +static int _MIDI_Context; + +static int _MIDI_ActiveTracks; +static int _MIDI_TotalVolume = MIDI_MaxVolume; + +static int _MIDI_ChannelVolume[ NUM_MIDI_CHANNELS ]; +static int _MIDI_UserChannelVolume[ NUM_MIDI_CHANNELS ] = +{ + 256, 256, 256, 256, 256, 256, 256, 256, + 256, 256, 256, 256, 256, 256, 256, 256 +}; + +static midifuncs *_MIDI_Funcs = NULL; + +static int Reset = FALSE; + +int MIDI_Tempo = 120; + +char MIDI_PatchMap[ 128 ]; + + +/********************************************************************** + + Memory locked functions: + +**********************************************************************/ + + +/*--------------------------------------------------------------------- + Function: _MIDI_ReadNumber + + Reads a variable length number from a MIDI track. +---------------------------------------------------------------------*/ + +static int _MIDI_ReadNumber +( + void *from, + size_t size +) + +{ + unsigned char *FromPtr; + int value; + + if (size > 4) + { + size = 4; + } + + FromPtr = (unsigned char *)from; + + value = 0; + while (size--) + { + value <<= 8; + value += *FromPtr++; + } + + return(value); +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_ReadDelta + + Reads a variable length encoded delta delay time from the MIDI data. +---------------------------------------------------------------------*/ + +static int _MIDI_ReadDelta +( + track *ptr +) + +{ + int value; + unsigned char c; + + GET_NEXT_EVENT(ptr, value); + + if (value & 0x80) + { + value &= 0x7f; + do + { + GET_NEXT_EVENT(ptr, c); + value = (value << 7) + (c & 0x7f); + } + while (c & 0x80); + } + + return(value); +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_ResetTracks + + Sets the track pointers to the beginning of the song. +---------------------------------------------------------------------*/ + +static void _MIDI_ResetTracks +( + void +) + +{ + int i; + track *ptr; + + _MIDI_Tick = 0; + _MIDI_Beat = 1; + _MIDI_Measure = 1; + _MIDI_Time = 0; + _MIDI_BeatsPerMeasure = 4; + _MIDI_TicksPerBeat = _MIDI_Division; + _MIDI_TimeBase = 4; + + _MIDI_PositionInTicks = 0; + //_MIDI_GlobalPositionInTicks = 0; + _MIDI_ActiveTracks = 0; + _MIDI_Context = 0; + + ptr = _MIDI_TrackPtr; + for (i = 0; i < _MIDI_NumTracks; i++) + { + ptr->pos = ptr->start; + ptr->delay = _MIDI_ReadDelta(ptr); + ptr->active = ptr->EMIDI_IncludeTrack; + ptr->RunningStatus = 0; + ptr->currentcontext = 0; + ptr->context[ 0 ].loopstart = ptr->start; + ptr->context[ 0 ].loopcount = 0; + + if (ptr->active) + { + _MIDI_ActiveTracks++; + } + + ptr++; + } +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_AdvanceTick + + Increment tick counters. +---------------------------------------------------------------------*/ + +static void _MIDI_AdvanceTick +( + void +) + +{ + _MIDI_PositionInTicks++; + _MIDI_Time += _MIDI_FPSecondsPerTick; + + _MIDI_Tick++; + while (_MIDI_Tick > _MIDI_TicksPerBeat) + { + _MIDI_Tick -= _MIDI_TicksPerBeat; + _MIDI_Beat++; + } + while (_MIDI_Beat > _MIDI_BeatsPerMeasure) + { + _MIDI_Beat -= _MIDI_BeatsPerMeasure; + _MIDI_Measure++; + } +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_SysEx + + Interpret SysEx Event. +---------------------------------------------------------------------*/ + +static void _MIDI_SysEx +( + track *Track +) + +{ + int length; + + length = _MIDI_ReadDelta(Track); + Track->pos += length; +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_MetaEvent + + Interpret Meta Event. +---------------------------------------------------------------------*/ + +static void _MIDI_MetaEvent +( + track *Track +) + +{ + int command; + int length; + int denominator; + int tempo; + + GET_NEXT_EVENT(Track, command); + GET_NEXT_EVENT(Track, length); + + switch (command) + { + case MIDI_END_OF_TRACK : + Track->active = FALSE; + + _MIDI_ActiveTracks--; + break; + + case MIDI_TEMPO_CHANGE : + tempo = 60000000L / _MIDI_ReadNumber(Track->pos, 3); + MIDI_SetTempo(tempo); + break; + + case MIDI_TIME_SIGNATURE : + if ((_MIDI_Tick > 0) || (_MIDI_Beat > 1)) + { + _MIDI_Measure++; + } + + _MIDI_Tick = 0; + _MIDI_Beat = 1; + + _MIDI_BeatsPerMeasure = (int)*Track->pos; + denominator = (int)*(Track->pos + 1); + _MIDI_TimeBase = 1; + while (denominator > 0) + { + _MIDI_TimeBase += _MIDI_TimeBase; + denominator--; + } + _MIDI_TicksPerBeat = (_MIDI_Division * 4) / _MIDI_TimeBase; + break; + } + + Track->pos += length; +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_InterpretControllerInfo + + Interprets the MIDI controller info. +---------------------------------------------------------------------*/ + +static int _MIDI_InterpretControllerInfo +( + track *Track, + int TimeSet, + int channel, + int c1, + int c2 +) + +{ + track *trackptr; + int tracknum; + int loopcount; + + switch (c1) + { + case MIDI_MONO_MODE_ON : + Track->pos++; + break; + + case MIDI_VOLUME : + if (!Track->EMIDI_VolumeChange) + { + _MIDI_SetChannelVolume(channel, c2); + } + break; + + case EMIDI_INCLUDE_TRACK : + case EMIDI_EXCLUDE_TRACK : + break; + + case EMIDI_PROGRAM_CHANGE : + if (Track->EMIDI_ProgramChange) + { + _MIDI_Funcs->ProgramChange(channel, MIDI_PatchMap[ c2 & 0x7f ]); + } + break; + + case EMIDI_VOLUME_CHANGE : + if (Track->EMIDI_VolumeChange) + { + _MIDI_SetChannelVolume(channel, c2); + } + break; + + case EMIDI_CONTEXT_START : + break; + + case EMIDI_CONTEXT_END : + if ((Track->currentcontext == _MIDI_Context) || + (_MIDI_Context < 0) || + (Track->context[ _MIDI_Context ].pos == NULL)) + { + break; + } + + Track->currentcontext = _MIDI_Context; + Track->context[ 0 ].loopstart = Track->context[ _MIDI_Context ].loopstart; + Track->context[ 0 ].loopcount = Track->context[ _MIDI_Context ].loopcount; + Track->pos = Track->context[ _MIDI_Context ].pos; + Track->RunningStatus = Track->context[ _MIDI_Context ].RunningStatus; + + if (TimeSet) + { + break; + } + + _MIDI_Time = Track->context[ _MIDI_Context ].time; + _MIDI_FPSecondsPerTick = Track->context[ _MIDI_Context ].FPSecondsPerTick; + _MIDI_Tick = Track->context[ _MIDI_Context ].tick; + _MIDI_Beat = Track->context[ _MIDI_Context ].beat; + _MIDI_Measure = Track->context[ _MIDI_Context ].measure; + _MIDI_BeatsPerMeasure = Track->context[ _MIDI_Context ].BeatsPerMeasure; + _MIDI_TicksPerBeat = Track->context[ _MIDI_Context ].TicksPerBeat; + _MIDI_TimeBase = Track->context[ _MIDI_Context ].TimeBase; + TimeSet = TRUE; + break; + + case EMIDI_LOOP_START : + case EMIDI_SONG_LOOP_START : + if (c2 == 0) + { + loopcount = EMIDI_INFINITE; + } + else + { + loopcount = c2; + } + + if (c1 == EMIDI_SONG_LOOP_START) + { + trackptr = _MIDI_TrackPtr; + tracknum = _MIDI_NumTracks; + } + else + { + trackptr = Track; + tracknum = 1; + } + + while (tracknum > 0) + { + trackptr->context[ 0 ].loopcount = loopcount; + trackptr->context[ 0 ].pos = trackptr->pos; + trackptr->context[ 0 ].loopstart = trackptr->pos; + trackptr->context[ 0 ].RunningStatus = trackptr->RunningStatus; + trackptr->context[ 0 ].active = trackptr->active; + trackptr->context[ 0 ].delay = trackptr->delay; + trackptr->context[ 0 ].time = _MIDI_Time; + trackptr->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; + trackptr->context[ 0 ].tick = _MIDI_Tick; + trackptr->context[ 0 ].beat = _MIDI_Beat; + trackptr->context[ 0 ].measure = _MIDI_Measure; + trackptr->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; + trackptr->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat; + trackptr->context[ 0 ].TimeBase = _MIDI_TimeBase; + trackptr++; + tracknum--; + } + break; + + case EMIDI_LOOP_END : + case EMIDI_SONG_LOOP_END : + if ((c2 != EMIDI_END_LOOP_VALUE) || + (Track->context[ 0 ].loopstart == NULL) || + (Track->context[ 0 ].loopcount == 0)) + { + break; + } + + if (c1 == EMIDI_SONG_LOOP_END) + { + trackptr = _MIDI_TrackPtr; + tracknum = _MIDI_NumTracks; + _MIDI_ActiveTracks = 0; + } + else + { + trackptr = Track; + tracknum = 1; + _MIDI_ActiveTracks--; + } + + while (tracknum > 0) + { + if (trackptr->context[ 0 ].loopcount != EMIDI_INFINITE) + { + trackptr->context[ 0 ].loopcount--; + } + + trackptr->pos = trackptr->context[ 0 ].loopstart; + trackptr->RunningStatus = trackptr->context[ 0 ].RunningStatus; + trackptr->delay = trackptr->context[ 0 ].delay; + trackptr->active = trackptr->context[ 0 ].active; + if (trackptr->active) + { + _MIDI_ActiveTracks++; + } + + if (!TimeSet) + { + _MIDI_Time = trackptr->context[ 0 ].time; + _MIDI_FPSecondsPerTick = trackptr->context[ 0 ].FPSecondsPerTick; + _MIDI_Tick = trackptr->context[ 0 ].tick; + _MIDI_Beat = trackptr->context[ 0 ].beat; + _MIDI_Measure = trackptr->context[ 0 ].measure; + _MIDI_BeatsPerMeasure = trackptr->context[ 0 ].BeatsPerMeasure; + _MIDI_TicksPerBeat = trackptr->context[ 0 ].TicksPerBeat; + _MIDI_TimeBase = trackptr->context[ 0 ].TimeBase; + TimeSet = TRUE; + } + + trackptr++; + tracknum--; + } + break; + + default : + if (_MIDI_Funcs->ControlChange) + { + _MIDI_Funcs->ControlChange(channel, c1, c2); + } + } + + return TimeSet; +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_ServiceRoutine + + Task that interperates the MIDI data. +---------------------------------------------------------------------*/ + +static int _MIDI_ServiceRoutine(void) +{ + int event; + int channel; + int command; + track *Track; + int tracknum; + int status; + int c1 = 0; + int c2 = 0; + int TimeSet = FALSE; + + if (_MIDI_SongActive) + { + Track = _MIDI_TrackPtr; + tracknum = 0; + while (tracknum < _MIDI_NumTracks) + { + while ((Track->active) && (Track->delay == 0)) + { + GET_NEXT_EVENT(Track, event); + + if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) + { + switch (event) + { + case MIDI_SYSEX : + case MIDI_SYSEX_CONTINUE : + _MIDI_SysEx(Track); + break; + + case MIDI_META_EVENT : + _MIDI_MetaEvent(Track); + break; + } + + if (Track->active) + { + Track->delay = _MIDI_ReadDelta(Track); + } + continue; + } + + if (event & MIDI_RUNNING_STATUS) + { + Track->RunningStatus = event; + } + else + { + event = Track->RunningStatus; + Track->pos--; + } + + channel = GET_MIDI_CHANNEL(event); + command = GET_MIDI_COMMAND(event); + + if (_MIDI_CommandLengths[ command ] > 0) + { + GET_NEXT_EVENT(Track, c1); + if (_MIDI_CommandLengths[ command ] > 1) + { + GET_NEXT_EVENT(Track, c2); + } + } + + if (_MIDI_RerouteFunctions[ channel ] != NULL) + { + status = _MIDI_RerouteFunctions[ channel ](event, c1, c2); + + if (status == MIDI_DONT_PLAY) + { + Track->delay = _MIDI_ReadDelta(Track); + continue; + } + } + + switch (command) + { + case MIDI_NOTE_OFF : + if (_MIDI_Funcs->NoteOff) + { + _MIDI_Funcs->NoteOff(channel, c1, c2); + } + break; + + case MIDI_NOTE_ON : + if (_MIDI_Funcs->NoteOn) + { + _MIDI_Funcs->NoteOn(channel, c1, c2); + } + break; + + case MIDI_POLY_AFTER_TCH : + if (_MIDI_Funcs->PolyAftertouch) + { + _MIDI_Funcs->PolyAftertouch(channel, c1, c2); + } + break; + + case MIDI_CONTROL_CHANGE : + TimeSet = _MIDI_InterpretControllerInfo(Track, TimeSet, channel, c1, c2); + break; + + case MIDI_PROGRAM_CHANGE : + if ((_MIDI_Funcs->ProgramChange) && (!Track->EMIDI_ProgramChange)) + { + _MIDI_Funcs->ProgramChange(channel, MIDI_PatchMap[ c1 & 0x7f ]); + } + break; + + case MIDI_AFTER_TOUCH : + if (_MIDI_Funcs->ChannelAftertouch) + { + _MIDI_Funcs->ChannelAftertouch(channel, c1); + } + break; + + case MIDI_PITCH_BEND : + if (_MIDI_Funcs->PitchBend) + { + _MIDI_Funcs->PitchBend(channel, c1, c2); + } + break; + + default : + break; + } + + Track->delay = _MIDI_ReadDelta(Track); + } + + Track->delay--; + Track++; + tracknum++; + + if (_MIDI_ActiveTracks == 0) + { + _MIDI_ResetTracks(); + if (_MIDI_Loop) + { + tracknum = 0; + Track = _MIDI_TrackPtr; + } + else + { + _MIDI_SongActive = FALSE; + break; + } + } + } + + _MIDI_AdvanceTick(); + _MIDI_GlobalPositionInTicks++; + } + return 0; +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_SendControlChange + + Sends a control change to the proper device +---------------------------------------------------------------------*/ + +static int _MIDI_SendControlChange +( + int channel, + int c1, + int c2 +) + +{ + int status; + + if (_MIDI_RerouteFunctions[ channel ] != NULL) + { + status = _MIDI_RerouteFunctions[ channel ](0xB0 + channel, + c1, c2); + if (status == MIDI_DONT_PLAY) + { + return(MIDI_Ok); + } + } + + if (_MIDI_Funcs == NULL) + { + return(MIDI_Error); + } + + if (_MIDI_Funcs->ControlChange == NULL) + { + return(MIDI_Error); + } + + _MIDI_Funcs->ControlChange(channel, c1, c2); + + return(MIDI_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_RerouteMidiChannel + + Sets callback function to reroute MIDI commands from specified + function. +---------------------------------------------------------------------*/ + +void MIDI_RerouteMidiChannel +( + int channel, + int(*function)(int event, int c1, int c2) +) + +{ + if ((channel >= 1) && (channel <= 16)) + { + _MIDI_RerouteFunctions[ channel - 1 ] = function; + } +} + + +/*--------------------------------------------------------------------- + Function: MIDI_AllNotesOff + + Sends all notes off commands on all midi channels. +---------------------------------------------------------------------*/ + +int MIDI_AllNotesOff +( + void +) + +{ + int channel; + + for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) + { + _MIDI_SendControlChange(channel, 0x40, 0); + _MIDI_SendControlChange(channel, MIDI_ALL_NOTES_OFF, 0); + _MIDI_SendControlChange(channel, 0x78, 0); + } + + return(MIDI_Ok); +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_SetChannelVolume + + Sets the volume of the specified midi channel. +---------------------------------------------------------------------*/ + +static void _MIDI_SetChannelVolume +( + int channel, + int volume +) + +{ + int status; + int remotevolume; + + _MIDI_ChannelVolume[ channel ] = volume; + + if (_MIDI_RerouteFunctions[ channel ] != NULL) + { + remotevolume = volume * _MIDI_TotalVolume; + remotevolume *= _MIDI_UserChannelVolume[ channel ]; + remotevolume /= MIDI_MaxVolume; + remotevolume >>= 8; + + status = _MIDI_RerouteFunctions[ channel ](0xB0 + channel, + MIDI_VOLUME, remotevolume); + if (status == MIDI_DONT_PLAY) + { + return; + } + } + + if (_MIDI_Funcs == NULL) + { + return; + } + + if (_MIDI_Funcs->ControlChange == NULL) + { + return; + } + + // For user volume + volume *= _MIDI_UserChannelVolume[ channel ]; + + if (_MIDI_Funcs->SetVolume == NULL) + { + volume *= _MIDI_TotalVolume; + volume /= MIDI_MaxVolume; + } + + // For user volume + volume >>= 8; + + _MIDI_Funcs->ControlChange(channel, MIDI_VOLUME, volume); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_SetUserChannelVolume + + Sets the volume of the specified midi channel. +---------------------------------------------------------------------*/ + +void MIDI_SetUserChannelVolume +( + int channel, + int volume +) + +{ + // Convert channel from 1-16 to 0-15 + channel--; + + volume = max(0, volume); + volume = min(volume, 256); + + if ((channel >= 0) && (channel < NUM_MIDI_CHANNELS)) + { + _MIDI_UserChannelVolume[ channel ] = volume; + _MIDI_SetChannelVolume(channel, _MIDI_ChannelVolume[ channel ]); + } +} + + +/*--------------------------------------------------------------------- + Function: MIDI_ResetUserChannelVolume + + Sets the volume of the specified midi channel. +---------------------------------------------------------------------*/ + +void MIDI_ResetUserChannelVolume +( + void +) + +{ + int channel; + + for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) + { + _MIDI_UserChannelVolume[ channel ] = 256; + } + + _MIDI_SendChannelVolumes(); +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_SendChannelVolumes + + Sets the volume on all the midi channels. +---------------------------------------------------------------------*/ + +static void _MIDI_SendChannelVolumes +( + void +) + +{ + int channel; + + for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) + { + _MIDI_SetChannelVolume(channel, _MIDI_ChannelVolume[ channel ]); + } +} + + +/*--------------------------------------------------------------------- + Function: MIDI_Reset + + Resets the MIDI device to General Midi defaults. +---------------------------------------------------------------------*/ + +int MIDI_Reset +( + void +) + +{ + int channel; + + MIDI_AllNotesOff(); + + for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) + { + _MIDI_SendControlChange(channel, MIDI_RESET_ALL_CONTROLLERS, 0); + _MIDI_SendControlChange(channel, MIDI_RPN_MSB, MIDI_PITCHBEND_MSB); + _MIDI_SendControlChange(channel, MIDI_RPN_LSB, MIDI_PITCHBEND_LSB); + _MIDI_SendControlChange(channel, MIDI_DATAENTRY_MSB, 2); /* Pitch Bend Sensitivity MSB */ + _MIDI_SendControlChange(channel, MIDI_DATAENTRY_LSB, 0); /* Pitch Bend Sensitivity LSB */ + _MIDI_ChannelVolume[ channel ] = GENMIDI_DefaultVolume; + } + + _MIDI_SendChannelVolumes(); + + Reset = TRUE; + + return(MIDI_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_SetVolume + + Sets the total volume of the music. +---------------------------------------------------------------------*/ + +int MIDI_SetVolume +( + int volume +) + +{ + int i; + + if (_MIDI_Funcs == NULL) + { + return(MIDI_NullMidiModule); + } + + volume = min(MIDI_MaxVolume, volume); + volume = max(0, volume); + + _MIDI_TotalVolume = volume; + + if (_MIDI_Funcs->SetVolume) + { + _MIDI_Funcs->SetVolume(volume); + + for (i = 0; i < NUM_MIDI_CHANNELS; i++) + { + if (_MIDI_RerouteFunctions[ i ] != NULL) + { + _MIDI_SetChannelVolume(i, _MIDI_ChannelVolume[ i ]); + } + } + } + else + { + _MIDI_SendChannelVolumes(); + } + + return(MIDI_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_GetVolume + + Returns the total volume of the music. +---------------------------------------------------------------------*/ + +int MIDI_GetVolume +( + void +) + +{ + int volume; + + if (_MIDI_Funcs == NULL) + { + return(MIDI_NullMidiModule); + } + + if (_MIDI_Funcs->GetVolume) + { + volume = _MIDI_Funcs->GetVolume(); + } + else + { + volume = _MIDI_TotalVolume; + } + + return(volume); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_SetContext + + Sets the song context. +---------------------------------------------------------------------*/ + +void MIDI_SetContext +( + int context +) + +{ + if ((context > 0) && (context < EMIDI_NUM_CONTEXTS)) + { + _MIDI_Context = context; + } +} + + +/*--------------------------------------------------------------------- + Function: MIDI_GetContext + + Returns the current song context. +---------------------------------------------------------------------*/ + +int MIDI_GetContext +( + void +) + +{ + return _MIDI_Context; +} + + +/*--------------------------------------------------------------------- + Function: MIDI_SetLoopFlag + + Sets whether the song should loop when finished or not. +---------------------------------------------------------------------*/ + +void MIDI_SetLoopFlag +( + int loopflag +) + +{ + _MIDI_Loop = loopflag; +} + + +/*--------------------------------------------------------------------- + Function: MIDI_ContinueSong + + Continues playback of a paused song. +---------------------------------------------------------------------*/ + +void MIDI_ContinueSong +( + void +) + +{ + if (_MIDI_SongLoaded) + { + _MIDI_SongActive = TRUE; + MPU_Unpause(); + } +} + + +/*--------------------------------------------------------------------- + Function: MIDI_PauseSong + + Pauses playback of the current song. +---------------------------------------------------------------------*/ + +void MIDI_PauseSong +( + void +) + +{ + if (_MIDI_SongLoaded) + { + _MIDI_SongActive = FALSE; + MIDI_AllNotesOff(); + MPU_Pause(); + } +} + + +/*--------------------------------------------------------------------- + Function: MIDI_SongPlaying + + Returns whether a song is playing or not. +---------------------------------------------------------------------*/ + +int MIDI_SongPlaying +( + void +) + +{ + return(_MIDI_SongActive); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_SetMidiFuncs + + Selects the routines that send the MIDI data to the music device. +---------------------------------------------------------------------*/ + +void MIDI_SetMidiFuncs +( + midifuncs *funcs +) + +{ + _MIDI_Funcs = funcs; +} + + +/*--------------------------------------------------------------------- + Function: MIDI_StopSong + + Stops playback of the currently playing song. +---------------------------------------------------------------------*/ + +void MIDI_StopSong +( + void +) + +{ + if (_MIDI_SongLoaded) + { + _MIDI_SongActive = FALSE; + _MIDI_SongLoaded = FALSE; + + MIDI_Reset(); + _MIDI_ResetTracks(); + + if (_MIDI_Funcs->ReleasePatches) + { + _MIDI_Funcs->ReleasePatches(); + } + + USRHOOKS_FreeMem(_MIDI_TrackPtr); + + _MIDI_TrackPtr = NULL; + _MIDI_NumTracks = 0; + _MIDI_TrackMemSize = 0; + + _MIDI_TotalTime = 0; + _MIDI_TotalTicks = 0; + _MIDI_TotalBeats = 0; + _MIDI_TotalMeasures = 0; + + MPU_Reset(); + } +} + + +/*--------------------------------------------------------------------- + Function: MIDI_PlaySong + + Begins playback of a MIDI song. +---------------------------------------------------------------------*/ + +int MIDI_PlaySong +( + unsigned char *song, + int loopflag +) + +{ + int numtracks; + int format; + int headersize; + int tracklength; + track *CurrentTrack; + unsigned char *ptr; + int status; + + if (_MIDI_SongLoaded) + { + MIDI_StopSong(); + } + + MPU_Init(MUSIC_SoundDevice); + + _MIDI_Loop = loopflag; + + if (_MIDI_Funcs == NULL) + { + return(MIDI_NullMidiModule); + } + + if (*(unsigned int *)song != MIDI_HEADER_SIGNATURE) + { + return(MIDI_InvalidMidiFile); + } + + song += 4; + + headersize = _MIDI_ReadNumber(song, 4); + song += 4; + format = _MIDI_ReadNumber(song, 2); + _MIDI_NumTracks = _MIDI_ReadNumber(song + 2, 2); + _MIDI_Division = _MIDI_ReadNumber(song + 4, 2); + if (_MIDI_Division < 0) + { + // If a SMPTE time division is given, just set to 96 so no errors occur + _MIDI_Division = 96; + } + + if (format > MAX_FORMAT) + { + return(MIDI_UnknownMidiFormat); + } + + ptr = song + headersize; + + if (_MIDI_NumTracks == 0) + { + return(MIDI_NoTracks); + } + + _MIDI_TrackMemSize = _MIDI_NumTracks * sizeof(track); + status = USRHOOKS_GetMem((void**)&_MIDI_TrackPtr, _MIDI_TrackMemSize); + if (status != USRHOOKS_Ok) + { + return(MIDI_NoMemory); + } + + CurrentTrack = _MIDI_TrackPtr; + numtracks = _MIDI_NumTracks; + while (numtracks--) + { + if (*(unsigned int *)ptr != MIDI_TRACK_SIGNATURE) + { + USRHOOKS_FreeMem(_MIDI_TrackPtr); + + _MIDI_TrackPtr = NULL; + _MIDI_TrackMemSize = 0; + + return(MIDI_InvalidTrack); + } + + tracklength = _MIDI_ReadNumber(ptr + 4, 4); + ptr += 8; + CurrentTrack->start = ptr; + ptr += tracklength; + CurrentTrack++; + } + + if (_MIDI_Funcs->GetVolume != NULL) + { + _MIDI_TotalVolume = _MIDI_Funcs->GetVolume(); + } + + _MIDI_InitEMIDI(); + + if (_MIDI_Funcs->LoadPatch) + { + MIDI_LoadTimbres(); + } + + _MIDI_ResetTracks(); + + if (!Reset) + { + MIDI_Reset(); + } + + Reset = FALSE; + + MIDI_SetDivision(_MIDI_Division); + //MIDI_SetTempo( 120 ); + + _MIDI_SongLoaded = TRUE; + _MIDI_SongActive = TRUE; + + while (_MPU_BuffersWaiting < 4) _MIDI_ServiceRoutine(); + MPU_BeginPlayback(); + + return(MIDI_Ok); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_SetTempo + + Sets the song tempo. +---------------------------------------------------------------------*/ + +void MIDI_SetTempo +( + int tempo +) + +{ + int tickspersecond; + + MIDI_Tempo = tempo; + tickspersecond = ((tempo) * _MIDI_Division) / 60; + _MIDI_FPSecondsPerTick = (1 << TIME_PRECISION) / tickspersecond; + MPU_SetTempo(tempo); +} + +void MIDI_SetDivision(int division) +{ + MPU_SetDivision(division); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_GetTempo + + Returns the song tempo. +---------------------------------------------------------------------*/ + +int MIDI_GetTempo +( + void +) + +{ + return(MIDI_Tempo); +} + + +/*--------------------------------------------------------------------- + Function: _MIDI_ProcessNextTick + + Sets the position of the song pointer. +---------------------------------------------------------------------*/ + +static int _MIDI_ProcessNextTick +( + void +) + +{ + int event; + int channel; + int command; + track *Track; + int tracknum; + int status; + int c1 = 0; + int c2 = 0; + int TimeSet = FALSE; + + Track = _MIDI_TrackPtr; + tracknum = 0; + while ((tracknum < _MIDI_NumTracks) && (Track != NULL)) + { + while ((Track->active) && (Track->delay == 0)) + { + GET_NEXT_EVENT(Track, event); + + if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) + { + switch (event) + { + case MIDI_SYSEX : + case MIDI_SYSEX_CONTINUE : + _MIDI_SysEx(Track); + break; + + case MIDI_META_EVENT : + _MIDI_MetaEvent(Track); + break; + } + + if (Track->active) + { + Track->delay = _MIDI_ReadDelta(Track); + } + + continue; + } + + if (event & MIDI_RUNNING_STATUS) + { + Track->RunningStatus = event; + } + else + { + event = Track->RunningStatus; + Track->pos--; + } + + channel = GET_MIDI_CHANNEL(event); + command = GET_MIDI_COMMAND(event); + + if (_MIDI_CommandLengths[ command ] > 0) + { + GET_NEXT_EVENT(Track, c1); + if (_MIDI_CommandLengths[ command ] > 1) + { + GET_NEXT_EVENT(Track, c2); + } + } + + if (_MIDI_RerouteFunctions[ channel ] != NULL) + { + status = _MIDI_RerouteFunctions[ channel ](event, c1, c2); + + if (status == MIDI_DONT_PLAY) + { + Track->delay = _MIDI_ReadDelta(Track); + continue; + } + } + + switch (command) + { + case MIDI_NOTE_OFF : + break; + + case MIDI_NOTE_ON : + break; + + case MIDI_POLY_AFTER_TCH : + if (_MIDI_Funcs->PolyAftertouch) + { + _MIDI_Funcs->PolyAftertouch(channel, c1, c2); + } + break; + + case MIDI_CONTROL_CHANGE : + TimeSet = _MIDI_InterpretControllerInfo(Track, TimeSet, + channel, c1, c2); + break; + + case MIDI_PROGRAM_CHANGE : + if ((_MIDI_Funcs->ProgramChange) && + (!Track->EMIDI_ProgramChange)) + { + _MIDI_Funcs->ProgramChange(channel, c1); + } + break; + + case MIDI_AFTER_TOUCH : + if (_MIDI_Funcs->ChannelAftertouch) + { + _MIDI_Funcs->ChannelAftertouch(channel, c1); + } + break; + + case MIDI_PITCH_BEND : + if (_MIDI_Funcs->PitchBend) + { + _MIDI_Funcs->PitchBend(channel, c1, c2); + } + break; + + default : + break; + } + + Track->delay = _MIDI_ReadDelta(Track); + } + + Track->delay--; + Track++; + tracknum++; + + if (_MIDI_ActiveTracks == 0) + { + break; + } + } + + _MIDI_AdvanceTick(); + + return(TimeSet); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_SetSongTick + + Sets the position of the song pointer. +---------------------------------------------------------------------*/ + +void MIDI_SetSongTick +( + unsigned int PositionInTicks +) + +{ + if (!_MIDI_SongLoaded) + { + return; + } + + MIDI_PauseSong(); + + if (PositionInTicks < _MIDI_PositionInTicks) + { + _MIDI_ResetTracks(); + MIDI_Reset(); + } + + while (_MIDI_PositionInTicks < PositionInTicks) + { + if (_MIDI_ProcessNextTick()) + { + break; + } + if (_MIDI_ActiveTracks == 0) + { + _MIDI_ResetTracks(); + if (!_MIDI_Loop) + { + return; + } + break; + } + } + + MIDI_SetVolume(_MIDI_TotalVolume); + MIDI_ContinueSong(); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_SetSongTime + + Sets the position of the song pointer. +---------------------------------------------------------------------*/ + +void MIDI_SetSongTime +( + unsigned int milliseconds +) + +{ + unsigned int mil; + unsigned int sec; + unsigned int newtime; + + if (!_MIDI_SongLoaded) + { + return; + } + + MIDI_PauseSong(); + + mil = ((milliseconds % 1000) << TIME_PRECISION) / 1000; + sec = (milliseconds / 1000) << TIME_PRECISION; + newtime = sec + mil; + + if (newtime < _MIDI_Time) + { + _MIDI_ResetTracks(); + MIDI_Reset(); + } + + while (_MIDI_Time < newtime) + { + if (_MIDI_ProcessNextTick()) + { + break; + } + if (_MIDI_ActiveTracks == 0) + { + _MIDI_ResetTracks(); + if (!_MIDI_Loop) + { + return; + } + break; + } + } + + MIDI_SetVolume(_MIDI_TotalVolume); + MIDI_ContinueSong(); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_SetSongPosition + + Sets the position of the song pointer. +---------------------------------------------------------------------*/ + +void MIDI_SetSongPosition +( + int measure, + int beat, + int tick +) + +{ + unsigned int pos; + + if (!_MIDI_SongLoaded) + { + return; + } + + MIDI_PauseSong(); + + pos = RELATIVE_BEAT(measure, beat, tick); + + if (pos < (unsigned int)RELATIVE_BEAT(_MIDI_Measure, _MIDI_Beat, _MIDI_Tick)) + { + _MIDI_ResetTracks(); + MIDI_Reset(); + } + + while ((unsigned int)RELATIVE_BEAT(_MIDI_Measure, _MIDI_Beat, _MIDI_Tick) < pos) + { + if (_MIDI_ProcessNextTick()) + { + break; + } + if (_MIDI_ActiveTracks == 0) + { + _MIDI_ResetTracks(); + if (!_MIDI_Loop) + { + return; + } + break; + } + } + + MIDI_SetVolume(_MIDI_TotalVolume); + MIDI_ContinueSong(); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_GetSongPosition + + Returns the position of the song pointer in Measures, beats, ticks. +---------------------------------------------------------------------*/ + +void MIDI_GetSongPosition +( + songposition *pos +) + +{ + unsigned int mil; + unsigned int sec; + + mil = (_MIDI_Time & ((1 << TIME_PRECISION) - 1)) * 1000; + sec = _MIDI_Time >> TIME_PRECISION; + pos->milliseconds = (mil >> TIME_PRECISION) + (sec * 1000); + pos->tickposition = _MIDI_PositionInTicks; + pos->measure = _MIDI_Measure; + pos->beat = _MIDI_Beat; + pos->tick = _MIDI_Tick; +} + + +/*--------------------------------------------------------------------- + Function: MIDI_GetSongLength + + Returns the length of the song. +---------------------------------------------------------------------*/ + +void MIDI_GetSongLength +( + songposition *pos +) + +{ + unsigned int mil; + unsigned int sec; + + mil = (_MIDI_TotalTime & ((1 << TIME_PRECISION) - 1)) * 1000; + sec = _MIDI_TotalTime >> TIME_PRECISION; + + pos->milliseconds = (mil >> TIME_PRECISION) + (sec * 1000); + pos->measure = _MIDI_TotalMeasures; + pos->beat = _MIDI_TotalBeats; + pos->tick = _MIDI_TotalTicks; + pos->tickposition = 0; +} + + +/*--------------------------------------------------------------------- + Function: MIDI_InitEMIDI + + Sets up the EMIDI +---------------------------------------------------------------------*/ + +static void _MIDI_InitEMIDI +( + void +) + +{ + int event; + int command; + int channel; + int length; + int IncludeFound; + track *Track; + int tracknum; + int type; + int c1; + int c2; + + type = EMIDI_GeneralMIDI; + + _MIDI_ResetTracks(); + + _MIDI_TotalTime = 0; + _MIDI_TotalTicks = 0; + _MIDI_TotalBeats = 0; + _MIDI_TotalMeasures = 0; + + Track = _MIDI_TrackPtr; + tracknum = 0; + while ((tracknum < _MIDI_NumTracks) && (Track != NULL)) + { + _MIDI_Tick = 0; + _MIDI_Beat = 1; + _MIDI_Measure = 1; + _MIDI_Time = 0; + _MIDI_BeatsPerMeasure = 4; + _MIDI_TicksPerBeat = _MIDI_Division; + _MIDI_TimeBase = 4; + + _MIDI_PositionInTicks = 0; + _MIDI_ActiveTracks = 0; + _MIDI_Context = -1; + + Track->RunningStatus = 0; + Track->active = TRUE; + + Track->EMIDI_ProgramChange = FALSE; + Track->EMIDI_VolumeChange = FALSE; + Track->EMIDI_IncludeTrack = TRUE; + + memset(Track->context, 0, sizeof(Track->context)); + + while (Track->delay > 0) + { + _MIDI_AdvanceTick(); + Track->delay--; + } + + IncludeFound = FALSE; + while (Track->active) + { + GET_NEXT_EVENT(Track, event); + + if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) + { + switch (event) + { + case MIDI_SYSEX : + case MIDI_SYSEX_CONTINUE : + _MIDI_SysEx(Track); + break; + + case MIDI_META_EVENT : + _MIDI_MetaEvent(Track); + break; + } + + if (Track->active) + { + Track->delay = _MIDI_ReadDelta(Track); + while (Track->delay > 0) + { + _MIDI_AdvanceTick(); + Track->delay--; + } + } + + continue; + } + + if (event & MIDI_RUNNING_STATUS) + { + Track->RunningStatus = event; + } + else + { + event = Track->RunningStatus; + Track->pos--; + } + + channel = GET_MIDI_CHANNEL(event); + command = GET_MIDI_COMMAND(event); + length = _MIDI_CommandLengths[ command ]; + + if (command == MIDI_CONTROL_CHANGE) + { + if (*Track->pos == MIDI_MONO_MODE_ON) + { + length++; + } + GET_NEXT_EVENT(Track, c1); + GET_NEXT_EVENT(Track, c2); + length -= 2; + + switch (c1) + { + case EMIDI_LOOP_START : + case EMIDI_SONG_LOOP_START : + if (c2 == 0) + { + Track->context[ 0 ].loopcount = EMIDI_INFINITE; + } + else + { + Track->context[ 0 ].loopcount = c2; + } + + Track->context[ 0 ].pos = Track->pos; + Track->context[ 0 ].loopstart = Track->pos; + Track->context[ 0 ].RunningStatus = Track->RunningStatus; + Track->context[ 0 ].time = _MIDI_Time; + Track->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; + Track->context[ 0 ].tick = _MIDI_Tick; + Track->context[ 0 ].beat = _MIDI_Beat; + Track->context[ 0 ].measure = _MIDI_Measure; + Track->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; + Track->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat; + Track->context[ 0 ].TimeBase = _MIDI_TimeBase; + break; + + case EMIDI_LOOP_END : + case EMIDI_SONG_LOOP_END : + if (c2 == EMIDI_END_LOOP_VALUE) + { + Track->context[ 0 ].loopstart = NULL; + Track->context[ 0 ].loopcount = 0; + } + break; + + case EMIDI_INCLUDE_TRACK : + if (EMIDI_AffectsCurrentCard(c2, type)) + { + //printf( "Include track %d on card %d\n", tracknum, c2 ); + IncludeFound = TRUE; + Track->EMIDI_IncludeTrack = TRUE; + } + else if (!IncludeFound) + { + //printf( "Track excluded %d on card %d\n", tracknum, c2 ); + IncludeFound = TRUE; + Track->EMIDI_IncludeTrack = FALSE; + } + break; + + case EMIDI_EXCLUDE_TRACK : + if (EMIDI_AffectsCurrentCard(c2, type)) + { + //printf( "Exclude track %d on card %d\n", tracknum, c2 ); + Track->EMIDI_IncludeTrack = FALSE; + } + break; + + case EMIDI_PROGRAM_CHANGE : + if (!Track->EMIDI_ProgramChange) + //printf( "Program change on track %d\n", tracknum ); + Track->EMIDI_ProgramChange = TRUE; + break; + + case EMIDI_VOLUME_CHANGE : + if (!Track->EMIDI_VolumeChange) + //printf( "Volume change on track %d\n", tracknum ); + Track->EMIDI_VolumeChange = TRUE; + break; + + case EMIDI_CONTEXT_START : + if ((c2 > 0) && (c2 < EMIDI_NUM_CONTEXTS)) + { + Track->context[ c2 ].pos = Track->pos; + Track->context[ c2 ].loopstart = Track->context[ 0 ].loopstart; + Track->context[ c2 ].loopcount = Track->context[ 0 ].loopcount; + Track->context[ c2 ].RunningStatus = Track->RunningStatus; + Track->context[ c2 ].time = _MIDI_Time; + Track->context[ c2 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; + Track->context[ c2 ].tick = _MIDI_Tick; + Track->context[ c2 ].beat = _MIDI_Beat; + Track->context[ c2 ].measure = _MIDI_Measure; + Track->context[ c2 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; + Track->context[ c2 ].TicksPerBeat = _MIDI_TicksPerBeat; + Track->context[ c2 ].TimeBase = _MIDI_TimeBase; + } + break; + + case EMIDI_CONTEXT_END : + break; + } + } + + Track->pos += length; + Track->delay = _MIDI_ReadDelta(Track); + + while (Track->delay > 0) + { + _MIDI_AdvanceTick(); + Track->delay--; + } + } + + _MIDI_TotalTime = max(_MIDI_TotalTime, _MIDI_Time); + if (RELATIVE_BEAT(_MIDI_Measure, _MIDI_Beat, _MIDI_Tick) > + RELATIVE_BEAT(_MIDI_TotalMeasures, _MIDI_TotalBeats, + _MIDI_TotalTicks)) + { + _MIDI_TotalTicks = _MIDI_Tick; + _MIDI_TotalBeats = _MIDI_Beat; + _MIDI_TotalMeasures = _MIDI_Measure; + } + + Track++; + tracknum++; + } + + _MIDI_ResetTracks(); +} + + +/*--------------------------------------------------------------------- + Function: MIDI_LoadTimbres + + Preloads the timbres on cards that use patch-caching. +---------------------------------------------------------------------*/ + +void MIDI_LoadTimbres +( + void +) + +{ + int event; + int command; + int channel; + int length; + int Finished; + track *Track; + int tracknum; + + Track = _MIDI_TrackPtr; + tracknum = 0; + while ((tracknum < _MIDI_NumTracks) && (Track != NULL)) + { + Finished = FALSE; + while (!Finished) + { + GET_NEXT_EVENT(Track, event); + + if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) + { + switch (event) + { + case MIDI_SYSEX : + case MIDI_SYSEX_CONTINUE : + length = _MIDI_ReadDelta(Track); + Track->pos += length; + break; + + case MIDI_META_EVENT : + GET_NEXT_EVENT(Track, command); + GET_NEXT_EVENT(Track, length); + + if (command == MIDI_END_OF_TRACK) + { + Finished = TRUE; + } + + Track->pos += length; + break; + } + + if (!Finished) + { + _MIDI_ReadDelta(Track); + } + + continue; + } + + if (event & MIDI_RUNNING_STATUS) + { + Track->RunningStatus = event; + } + else + { + event = Track->RunningStatus; + Track->pos--; + } + + channel = GET_MIDI_CHANNEL(event); + command = GET_MIDI_COMMAND(event); + length = _MIDI_CommandLengths[ command ]; + + if (command == MIDI_CONTROL_CHANGE) + { + if (*Track->pos == MIDI_MONO_MODE_ON) + { + length++; + } + + if (*Track->pos == EMIDI_PROGRAM_CHANGE) + { + _MIDI_Funcs->LoadPatch(*(Track->pos + 1)); + } + } + + if (channel == MIDI_RHYTHM_CHANNEL) + { + if (command == MIDI_NOTE_ON) + { + _MIDI_Funcs->LoadPatch(128 + *Track->pos); + } + } + else + { + if (command == MIDI_PROGRAM_CHANGE) + { + _MIDI_Funcs->LoadPatch(*Track->pos); + } + } + Track->pos += length; + _MIDI_ReadDelta(Track); + } + Track++; + tracknum++; + } + + _MIDI_ResetTracks(); +} + + +void MIDI_UpdateMusic(void) +{ + if (!_MIDI_SongLoaded || !_MIDI_SongActive) return; + while (_MPU_BuffersWaiting < 4) _MIDI_ServiceRoutine(); +} + diff --git a/polymer/eduke32/source/jaudiolib/multivoc.c b/polymer/eduke32/source/jaudiolib/multivoc.c index 7c3c7e7ed..ce46e4ee8 100644 --- a/polymer/eduke32/source/jaudiolib/multivoc.c +++ b/polymer/eduke32/source/jaudiolib/multivoc.c @@ -1766,8 +1766,8 @@ size_t ReadOgg(void *ptr, size_t size1, size_t nmemb, void *datasource) { sounddef *d=(sounddef *)datasource; size1*=nmemb; -/* if (d->pos>=d->size) - return 0;*/ + /* if (d->pos>=d->size) + return 0;*/ if (d->pos+size1>=d->size) size1=d->size-d->pos; Bmemcpy(ptr,(d->ptrsnd+d->pos),size1); @@ -1780,19 +1780,19 @@ int SeekOgg(void *datasource,ogg_int64_t offset,int whence) sounddef *d=(sounddef *)datasource; switch (whence) { - case SEEK_SET: + case SEEK_SET: whence=offset; break; - case SEEK_CUR: + case SEEK_CUR: whence=d->pos+offset; break; - case SEEK_END: + case SEEK_END: whence=d->size-offset; break; default: return -1; } -/* if (whence>=(int)d->size||whence<0) - return -1;*/ + /* if (whence>=(int)d->size||whence<0) + return -1;*/ d->pos=whence; return 0; } @@ -2454,11 +2454,11 @@ int MV_PlayLoopedOGG(char *ptr, int loopstart, int loopend, int pitchoffset, int length=ov_pcm_total(&voice->OGGstream.oggStream,-1); if (!length) length=0xffffff; -/* if (length == OV_EINVAL) - { - MV_SetErrorCode(MV_InvalidOGGFile); - return(MV_Error); - }*/ + /* if (length == OV_EINVAL) + { + MV_SetErrorCode(MV_InvalidOGGFile); + return(MV_Error); + }*/ loopend=length=length>>voice->downsample; diff --git a/polymer/eduke32/source/jaudiolib/music.c b/polymer/eduke32/source/jaudiolib/music.c index 288e3ff53..1edb73121 100644 --- a/polymer/eduke32/source/jaudiolib/music.c +++ b/polymer/eduke32/source/jaudiolib/music.c @@ -192,7 +192,7 @@ void MUSIC_SetVolume volume = max(0, volume); volume = min(volume, 255); #ifdef USE_OPENAL - AL_SetMusicVolume(volume); + AL_SetMusicVolume(volume); #endif if (MUSIC_SoundDevice != -1) { @@ -300,7 +300,7 @@ void MUSIC_Continue { #ifdef USE_OPENAL - AL_Continue(); + AL_Continue(); #endif MIDI_ContinueSong(); } @@ -319,7 +319,7 @@ void MUSIC_Pause { #ifdef USE_OPENAL - AL_Pause(); + AL_Pause(); #endif MIDI_PauseSong(); } @@ -338,7 +338,7 @@ int MUSIC_StopSong { #ifdef USE_OPENAL - AL_Stop(); + AL_Stop(); #endif MUSIC_StopFade(); MIDI_StopSong(); @@ -363,19 +363,19 @@ int MUSIC_PlaySong int status; #ifdef USE_OPENAL - AL_PlaySong((char *)song,loopflag); + AL_PlaySong((char *)song,loopflag); - if(AL_isntALmusic()) + if (AL_isntALmusic()) #endif - { - MUSIC_StopSong(); - status = MIDI_PlaySong(song, loopflag); - if (status != MIDI_Ok) { - MUSIC_SetErrorCode(MUSIC_MidiError); - return(MUSIC_Warning); + MUSIC_StopSong(); + status = MIDI_PlaySong(song, loopflag); + if (status != MIDI_Ok) + { + MUSIC_SetErrorCode(MUSIC_MidiError); + return(MUSIC_Warning); + } } - } return(MUSIC_Ok); } diff --git a/polymer/eduke32/source/jaudiolib/openal.c b/polymer/eduke32/source/jaudiolib/openal.c index 2ebb6e97e..9c41bfb2f 100644 --- a/polymer/eduke32/source/jaudiolib/openal.c +++ b/polymer/eduke32/source/jaudiolib/openal.c @@ -403,13 +403,13 @@ int update() case 1: while (processed--) { - ALdoing="update1"; + ALdoing="update1"; balSourceUnqueueBuffers(music.source,1,&buffer); check(1); active=stream(buffer); if (active) { - ALdoing="update2"; + ALdoing="update2"; balSourceQueueBuffers(music.source,1,&buffer); check(1); } @@ -450,7 +450,7 @@ int stream(ALuint buffer) { ALsizei size=0; int section,result; - + while (size -//#include -#include "standard.h" -#include "pitch.h" - -#define MAXDETUNE 25 - -static unsigned int PitchTable[ 12 ][ MAXDETUNE ] = - { - { - 0x10000, 0x10097, 0x1012f, 0x101c7, 0x10260, 0x102f9, 0x10392, 0x1042c, - 0x104c6, 0x10561, 0x105fb, 0x10696, 0x10732, 0x107ce, 0x1086a, 0x10907, - 0x109a4, 0x10a41, 0x10adf, 0x10b7d, 0x10c1b, 0x10cba, 0x10d59, 0x10df8, - 0x10e98 - }, - { 0x10f38, 0x10fd9, 0x1107a, 0x1111b, 0x111bd, 0x1125f, 0x11302, 0x113a5, - 0x11448, 0x114eb, 0x1158f, 0x11634, 0x116d8, 0x1177e, 0x11823, 0x118c9, - 0x1196f, 0x11a16, 0x11abd, 0x11b64, 0x11c0c, 0x11cb4, 0x11d5d, 0x11e06, - 0x11eaf }, - { 0x11f59, 0x12003, 0x120ae, 0x12159, 0x12204, 0x122b0, 0x1235c, 0x12409, - 0x124b6, 0x12563, 0x12611, 0x126bf, 0x1276d, 0x1281c, 0x128cc, 0x1297b, - 0x12a2b, 0x12adc, 0x12b8d, 0x12c3e, 0x12cf0, 0x12da2, 0x12e55, 0x12f08, - 0x12fbc }, - { 0x1306f, 0x13124, 0x131d8, 0x1328d, 0x13343, 0x133f9, 0x134af, 0x13566, - 0x1361d, 0x136d5, 0x1378d, 0x13846, 0x138fe, 0x139b8, 0x13a72, 0x13b2c, - 0x13be6, 0x13ca1, 0x13d5d, 0x13e19, 0x13ed5, 0x13f92, 0x1404f, 0x1410d, - 0x141cb }, - { 0x1428a, 0x14349, 0x14408, 0x144c8, 0x14588, 0x14649, 0x1470a, 0x147cc, - 0x1488e, 0x14951, 0x14a14, 0x14ad7, 0x14b9b, 0x14c5f, 0x14d24, 0x14dea, - 0x14eaf, 0x14f75, 0x1503c, 0x15103, 0x151cb, 0x15293, 0x1535b, 0x15424, - 0x154ee }, - { 0x155b8, 0x15682, 0x1574d, 0x15818, 0x158e4, 0x159b0, 0x15a7d, 0x15b4a, - 0x15c18, 0x15ce6, 0x15db4, 0x15e83, 0x15f53, 0x16023, 0x160f4, 0x161c5, - 0x16296, 0x16368, 0x1643a, 0x1650d, 0x165e1, 0x166b5, 0x16789, 0x1685e, - 0x16934 }, - { 0x16a09, 0x16ae0, 0x16bb7, 0x16c8e, 0x16d66, 0x16e3e, 0x16f17, 0x16ff1, - 0x170ca, 0x171a5, 0x17280, 0x1735b, 0x17437, 0x17513, 0x175f0, 0x176ce, - 0x177ac, 0x1788a, 0x17969, 0x17a49, 0x17b29, 0x17c09, 0x17cea, 0x17dcc, - 0x17eae }, - { 0x17f91, 0x18074, 0x18157, 0x1823c, 0x18320, 0x18406, 0x184eb, 0x185d2, - 0x186b8, 0x187a0, 0x18888, 0x18970, 0x18a59, 0x18b43, 0x18c2d, 0x18d17, - 0x18e02, 0x18eee, 0x18fda, 0x190c7, 0x191b5, 0x192a2, 0x19391, 0x19480, - 0x1956f }, - { 0x1965f, 0x19750, 0x19841, 0x19933, 0x19a25, 0x19b18, 0x19c0c, 0x19d00, - 0x19df4, 0x19ee9, 0x19fdf, 0x1a0d5, 0x1a1cc, 0x1a2c4, 0x1a3bc, 0x1a4b4, - 0x1a5ad, 0x1a6a7, 0x1a7a1, 0x1a89c, 0x1a998, 0x1aa94, 0x1ab90, 0x1ac8d, - 0x1ad8b }, - { 0x1ae89, 0x1af88, 0x1b088, 0x1b188, 0x1b289, 0x1b38a, 0x1b48c, 0x1b58f, - 0x1b692, 0x1b795, 0x1b89a, 0x1b99f, 0x1baa4, 0x1bbaa, 0x1bcb1, 0x1bdb8, - 0x1bec0, 0x1bfc9, 0x1c0d2, 0x1c1dc, 0x1c2e6, 0x1c3f1, 0x1c4fd, 0x1c609, - 0x1c716 }, - { 0x1c823, 0x1c931, 0x1ca40, 0x1cb50, 0x1cc60, 0x1cd70, 0x1ce81, 0x1cf93, - 0x1d0a6, 0x1d1b9, 0x1d2cd, 0x1d3e1, 0x1d4f6, 0x1d60c, 0x1d722, 0x1d839, - 0x1d951, 0x1da69, 0x1db82, 0x1dc9c, 0x1ddb6, 0x1ded1, 0x1dfec, 0x1e109, - 0x1e225 }, - { 0x1e343, 0x1e461, 0x1e580, 0x1e6a0, 0x1e7c0, 0x1e8e0, 0x1ea02, 0x1eb24, - 0x1ec47, 0x1ed6b, 0x1ee8f, 0x1efb4, 0x1f0d9, 0x1f1ff, 0x1f326, 0x1f44e, - 0x1f576, 0x1f69f, 0x1f7c9, 0x1f8f3, 0x1fa1e, 0x1fb4a, 0x1fc76, 0x1fda3, - 0x1fed1 } - }; - - -//static int PITCH_Installed = FALSE; - - -/*--------------------------------------------------------------------- - Function: PITCH_Init - - Initializes pitch table. ----------------------------------------------------------------------*/ -/* -void PITCH_Init - ( - void - ) - - { - int note; - int detune; - - if ( !PITCH_Installed ) - { - for( note = 0; note < 12; note++ ) - { - for( detune = 0; detune < MAXDETUNE; detune++ ) - { - PitchTable[ note ][ detune ] = 0x10000 * - pow( 2, ( note * MAXDETUNE + detune ) / ( 12.0 * MAXDETUNE ) ); - } - } - - PITCH_Installed = TRUE; - } - } -*/ - -/********************************************************************** - - Memory locked functions: - -**********************************************************************/ - - -/*--------------------------------------------------------------------- - Function: PITCH_GetScale - - Returns a fixed-point value to scale number the specified amount. ----------------------------------------------------------------------*/ - -unsigned int PITCH_GetScale -( - int pitchoffset -) - -{ - unsigned int scale; - int octaveshift; - int noteshift; - int note; - int detune; - -// if ( !PITCH_Installed ) -// { -// PITCH_Init(); -// } - - if (pitchoffset == 0) - { - return(PitchTable[ 0 ][ 0 ]); - } - - noteshift = pitchoffset % 1200; - if (noteshift < 0) - { - noteshift += 1200; - } - - note = noteshift / 100; - detune = (noteshift % 100) / (100 / MAXDETUNE); - octaveshift = (pitchoffset - noteshift) / 1200; - - if (detune < 0) - { - detune += (100 / MAXDETUNE); - note--; - if (note < 0) - { - note += 12; - octaveshift--; - } - } - - scale = PitchTable[ note ][ detune ]; - - if (octaveshift < 0) - { - scale >>= -octaveshift; - } - else - { - scale <<= octaveshift; - } - - return(scale); -} - - - +/* +Copyright (C) 1994-1995 Apogee Software, Ltd. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Modifications for JonoF's port by Jonathon Fowler (jonof@edgenetwk.com) +*/ +/********************************************************************** + module: PITCH.C + + author: James R. Dose + date: June 14, 1993 + + Routines for pitch scaling. + + (c) Copyright 1993 James R. Dose. All Rights Reserved. +**********************************************************************/ + +#include +//#include +#include "standard.h" +#include "pitch.h" + +#define MAXDETUNE 25 + +static unsigned int PitchTable[ 12 ][ MAXDETUNE ] = +{ + { + 0x10000, 0x10097, 0x1012f, 0x101c7, 0x10260, 0x102f9, 0x10392, 0x1042c, + 0x104c6, 0x10561, 0x105fb, 0x10696, 0x10732, 0x107ce, 0x1086a, 0x10907, + 0x109a4, 0x10a41, 0x10adf, 0x10b7d, 0x10c1b, 0x10cba, 0x10d59, 0x10df8, + 0x10e98 + }, + { 0x10f38, 0x10fd9, 0x1107a, 0x1111b, 0x111bd, 0x1125f, 0x11302, 0x113a5, + 0x11448, 0x114eb, 0x1158f, 0x11634, 0x116d8, 0x1177e, 0x11823, 0x118c9, + 0x1196f, 0x11a16, 0x11abd, 0x11b64, 0x11c0c, 0x11cb4, 0x11d5d, 0x11e06, + 0x11eaf }, + { 0x11f59, 0x12003, 0x120ae, 0x12159, 0x12204, 0x122b0, 0x1235c, 0x12409, + 0x124b6, 0x12563, 0x12611, 0x126bf, 0x1276d, 0x1281c, 0x128cc, 0x1297b, + 0x12a2b, 0x12adc, 0x12b8d, 0x12c3e, 0x12cf0, 0x12da2, 0x12e55, 0x12f08, + 0x12fbc }, + { 0x1306f, 0x13124, 0x131d8, 0x1328d, 0x13343, 0x133f9, 0x134af, 0x13566, + 0x1361d, 0x136d5, 0x1378d, 0x13846, 0x138fe, 0x139b8, 0x13a72, 0x13b2c, + 0x13be6, 0x13ca1, 0x13d5d, 0x13e19, 0x13ed5, 0x13f92, 0x1404f, 0x1410d, + 0x141cb }, + { 0x1428a, 0x14349, 0x14408, 0x144c8, 0x14588, 0x14649, 0x1470a, 0x147cc, + 0x1488e, 0x14951, 0x14a14, 0x14ad7, 0x14b9b, 0x14c5f, 0x14d24, 0x14dea, + 0x14eaf, 0x14f75, 0x1503c, 0x15103, 0x151cb, 0x15293, 0x1535b, 0x15424, + 0x154ee }, + { 0x155b8, 0x15682, 0x1574d, 0x15818, 0x158e4, 0x159b0, 0x15a7d, 0x15b4a, + 0x15c18, 0x15ce6, 0x15db4, 0x15e83, 0x15f53, 0x16023, 0x160f4, 0x161c5, + 0x16296, 0x16368, 0x1643a, 0x1650d, 0x165e1, 0x166b5, 0x16789, 0x1685e, + 0x16934 }, + { 0x16a09, 0x16ae0, 0x16bb7, 0x16c8e, 0x16d66, 0x16e3e, 0x16f17, 0x16ff1, + 0x170ca, 0x171a5, 0x17280, 0x1735b, 0x17437, 0x17513, 0x175f0, 0x176ce, + 0x177ac, 0x1788a, 0x17969, 0x17a49, 0x17b29, 0x17c09, 0x17cea, 0x17dcc, + 0x17eae }, + { 0x17f91, 0x18074, 0x18157, 0x1823c, 0x18320, 0x18406, 0x184eb, 0x185d2, + 0x186b8, 0x187a0, 0x18888, 0x18970, 0x18a59, 0x18b43, 0x18c2d, 0x18d17, + 0x18e02, 0x18eee, 0x18fda, 0x190c7, 0x191b5, 0x192a2, 0x19391, 0x19480, + 0x1956f }, + { 0x1965f, 0x19750, 0x19841, 0x19933, 0x19a25, 0x19b18, 0x19c0c, 0x19d00, + 0x19df4, 0x19ee9, 0x19fdf, 0x1a0d5, 0x1a1cc, 0x1a2c4, 0x1a3bc, 0x1a4b4, + 0x1a5ad, 0x1a6a7, 0x1a7a1, 0x1a89c, 0x1a998, 0x1aa94, 0x1ab90, 0x1ac8d, + 0x1ad8b }, + { 0x1ae89, 0x1af88, 0x1b088, 0x1b188, 0x1b289, 0x1b38a, 0x1b48c, 0x1b58f, + 0x1b692, 0x1b795, 0x1b89a, 0x1b99f, 0x1baa4, 0x1bbaa, 0x1bcb1, 0x1bdb8, + 0x1bec0, 0x1bfc9, 0x1c0d2, 0x1c1dc, 0x1c2e6, 0x1c3f1, 0x1c4fd, 0x1c609, + 0x1c716 }, + { 0x1c823, 0x1c931, 0x1ca40, 0x1cb50, 0x1cc60, 0x1cd70, 0x1ce81, 0x1cf93, + 0x1d0a6, 0x1d1b9, 0x1d2cd, 0x1d3e1, 0x1d4f6, 0x1d60c, 0x1d722, 0x1d839, + 0x1d951, 0x1da69, 0x1db82, 0x1dc9c, 0x1ddb6, 0x1ded1, 0x1dfec, 0x1e109, + 0x1e225 }, + { 0x1e343, 0x1e461, 0x1e580, 0x1e6a0, 0x1e7c0, 0x1e8e0, 0x1ea02, 0x1eb24, + 0x1ec47, 0x1ed6b, 0x1ee8f, 0x1efb4, 0x1f0d9, 0x1f1ff, 0x1f326, 0x1f44e, + 0x1f576, 0x1f69f, 0x1f7c9, 0x1f8f3, 0x1fa1e, 0x1fb4a, 0x1fc76, 0x1fda3, + 0x1fed1 } +}; + + +//static int PITCH_Installed = FALSE; + + +/*--------------------------------------------------------------------- + Function: PITCH_Init + + Initializes pitch table. +---------------------------------------------------------------------*/ +/* +void PITCH_Init + ( + void + ) + + { + int note; + int detune; + + if ( !PITCH_Installed ) + { + for( note = 0; note < 12; note++ ) + { + for( detune = 0; detune < MAXDETUNE; detune++ ) + { + PitchTable[ note ][ detune ] = 0x10000 * + pow( 2, ( note * MAXDETUNE + detune ) / ( 12.0 * MAXDETUNE ) ); + } + } + + PITCH_Installed = TRUE; + } + } +*/ + +/********************************************************************** + + Memory locked functions: + +**********************************************************************/ + + +/*--------------------------------------------------------------------- + Function: PITCH_GetScale + + Returns a fixed-point value to scale number the specified amount. +---------------------------------------------------------------------*/ + +unsigned int PITCH_GetScale +( + int pitchoffset +) + +{ + unsigned int scale; + int octaveshift; + int noteshift; + int note; + int detune; + +// if ( !PITCH_Installed ) +// { +// PITCH_Init(); +// } + + if (pitchoffset == 0) + { + return(PitchTable[ 0 ][ 0 ]); + } + + noteshift = pitchoffset % 1200; + if (noteshift < 0) + { + noteshift += 1200; + } + + note = noteshift / 100; + detune = (noteshift % 100) / (100 / MAXDETUNE); + octaveshift = (pitchoffset - noteshift) / 1200; + + if (detune < 0) + { + detune += (100 / MAXDETUNE); + note--; + if (note < 0) + { + note += 12; + octaveshift--; + } + } + + scale = PitchTable[ note ][ detune ]; + + if (octaveshift < 0) + { + scale >>= -octaveshift; + } + else + { + scale <<= octaveshift; + } + + return(scale); +} + + + diff --git a/polymer/eduke32/source/jmact/control.c b/polymer/eduke32/source/jmact/control.c index 852f835f2..7420cc6c2 100644 --- a/polymer/eduke32/source/jmact/control.c +++ b/polymer/eduke32/source/jmact/control.c @@ -960,10 +960,12 @@ boolean CONTROL_Startup(controltype which, int32(*TimeFunction)(void), int32 tic // break; //} + /* if (CONTROL_MousePresent) initprintf("CONTROL_Startup: Mouse Present\n"); if (CONTROL_JoyPresent) initprintf("CONTROL_Startup: Joystick Present\n"); + */ CONTROL_ButtonState1 = 0; CONTROL_ButtonState2 = 0; diff --git a/polymer/eduke32/source/menus.c b/polymer/eduke32/source/menus.c index be4dfbbde..6c38f8cc2 100644 --- a/polymer/eduke32/source/menus.c +++ b/polymer/eduke32/source/menus.c @@ -2491,17 +2491,21 @@ cheat_for_port_credits: gametextpal(d,yy, glwidescreen ? "On" : "Off", MENUHIGHLIGHT(io), 0); break; case 1: + { + int dummy = glanisotropy; + modval(0,glinfo.maxanisotropy+1,(int *)&dummy,1,probey==io); + if (dummy > glanisotropy) glanisotropy *= 2; + else if (dummy < glanisotropy) glanisotropy /= 2; if (x==io) - { glanisotropy *= 2; - if (glanisotropy > glinfo.maxanisotropy) glanisotropy = 1; - gltexapplyprops(); - } + if (glanisotropy > glinfo.maxanisotropy) glanisotropy = 1; + else if (glanisotropy < 1) glanisotropy = glinfo.maxanisotropy; + gltexapplyprops(); if (glanisotropy == 1) strcpy(tempbuf,"NONE"); else sprintf(tempbuf,"%dx",glanisotropy); gametextpal(d,yy, tempbuf, MENUHIGHLIGHT(io), 0); break; - + } case 2: if (x==io) usehightile = 1-usehightile; modval(0,1,(int *)&usehightile,1,probey==io); @@ -3231,8 +3235,8 @@ cheat_for_port_credits: (newvidmode==validmodecnt)?ydim:validmode[newvidmode].ydim); gametext(c+154,50-8,tempbuf,MENUHIGHLIGHT(0),2+8+16); - menutext(c,50+16,MENUHIGHLIGHT(1),0,"VIDEO MODE"); - sprintf(tempbuf, "%dbit %s", vidsets[newvidset]&0x0ffff, (vidsets[newvidset]&0x20000)?"Polymost":"Classic"); + menutext(c,50+16,MENUHIGHLIGHT(1),0,"RENDERER"); + sprintf(tempbuf, "%d-bit %s", vidsets[newvidset]&0x0ffff, (vidsets[newvidset]&0x20000)?"OpenGL":"Software"); gametext(c+154,50+16-8,tempbuf,MENUHIGHLIGHT(1),2+8+16); menutext(c,50+16+16,MENUHIGHLIGHT(2),0,"FULLSCREEN"); @@ -3354,7 +3358,7 @@ cheat_for_port_credits: key[0] = ud.config.KeyboardKeys[probey][0]; key[1] = ud.config.KeyboardKeys[probey][1]; ud.config.KeyboardKeys[probey][currentlist] = 0xff; - MapKey(probey, ud.config.KeyboardKeys[probey][0], key[0], ud.config.KeyboardKeys[probey][1], key[1]); + CONFIG_MapKey(probey, ud.config.KeyboardKeys[probey][0], key[0], ud.config.KeyboardKeys[probey][1], key[1]); sound(KICK_HIT); KB_ClearKeyDown(sc_Delete); } @@ -3419,7 +3423,7 @@ cheat_for_port_credits: if (function == gamefunc_Show_Console) OSD_CaptureKey(KB_GetLastScanCode()); else - MapKey(function, ud.config.KeyboardKeys[function][0], key[0], ud.config.KeyboardKeys[function][1], key[1]); + CONFIG_MapKey(function, ud.config.KeyboardKeys[function][0], key[0], ud.config.KeyboardKeys[function][1], key[1]); } cmenu(204); diff --git a/polymer/eduke32/source/osdcmds.c b/polymer/eduke32/source/osdcmds.c index 1d1aa6e34..3129cb6c4 100644 --- a/polymer/eduke32/source/osdcmds.c +++ b/polymer/eduke32/source/osdcmds.c @@ -354,9 +354,9 @@ static int osdcmd_restartsound(const osdfuncparm_t *parm) SoundShutdown(); MusicShutdown(); - initprintf("Checking music inits...\n"); + initprintf("Initializing music...\n"); MusicStartup(); - initprintf("Checking sound inits...\n"); + initprintf("Initializing sound...\n"); SoundStartup(); FX_StopAllSounds(); diff --git a/polymer/eduke32/source/rts.c b/polymer/eduke32/source/rts.c index e049f657f..c46f0f6e6 100644 --- a/polymer/eduke32/source/rts.c +++ b/polymer/eduke32/source/rts.c @@ -78,7 +78,7 @@ int32 RTS_AddFile(const char *filename) startlump = numlumps; // WAD file - initprintf(" Adding %s.\n",filename); +// initprintf(" Adding %s.\n",filename); kread(handle, &header, sizeof(header)); if (strncmp(header.identification,"IWAD",4)) { @@ -146,7 +146,7 @@ void RTS_Init(const char *filename) numlumps = 0; lumpinfo = NULL; // will be realloced as lumps are added - initprintf("RTS Manager Started.\n"); +// initprintf("RTS Manager Started.\n"); if (RTS_AddFile(filename)) return; if (!numlumps) return;