diff --git a/.gitignore b/.gitignore index 513fac9..bd30b26 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ /bassmididrv_source/Release /bassmididrv_source/Debug /bassmididrv_source/out +/bassmididrv_source/*.dll +/bassmididrv_source/*.exe /drivercfg/*.opensdf /drivercfg/*.sdf /drivercfg/*.vcxproj.user @@ -15,6 +17,8 @@ /drivercfg/ipch /drivercfg/Release /drivercfg/Debug +/drivercfg/*.dll +/drivercfg/*.exe /sfpacker/*.opensdf /sfpacker/*.sdf /sfpacker/*.vcxproj.user @@ -23,6 +27,7 @@ /sfpacker/ipch /sfpacker/Release /sfpacker/Debug -*.dll -*.exe +/sfpacker/*.dll +/sfpacker/*.exe +/output/ git_ver.h diff --git a/CHANGES.txt b/CHANGES.txt index 8c030c5..eb7e620 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +3.8 + winmm driver + * 64-bit support, volume control, and general restructuring by [JAZ] 3.7 winmm driver * fixed volume control diff --git a/bassmididrv.nsi b/bassmididrv.nsi index 331b456..6bb157a 100644 --- a/bassmididrv.nsi +++ b/bassmididrv.nsi @@ -68,13 +68,13 @@ Section "Needed (required)" DetailPrint "Copying driver and synth..." ${If} ${RunningX64} SetOutPath "$WINDIR\SysWow64\bassmididrv" - File bass.dll - File bassflac.dll - File basswv.dll - File bassopus.dll - File bass_mpc.dll - File bassmidi.dll - File bassmididrv.dll + File output\bass.dll + File output\bassflac.dll + File output\basswv.dll + File output\bassopus.dll + File output\bass_mpc.dll + File output\bassmidi.dll + File output\bassmididrv.dll File bassmididrvcfg.exe File sfpacker.exe ;check if already installed @@ -98,13 +98,13 @@ NEXT1: StrCmp $1 "9" 0 LOOP1 ${Else} SetOutPath "$WINDIR\System32\bassmididrv" - File bass.dll - File bassflac.dll - File basswv.dll - File bassopus.dll - File bass_mpc.dll - File bassmidi.dll - File bassmididrv.dll + File output\bass.dll + File output\bassflac.dll + File output\basswv.dll + File output\bassopus.dll + File output\bass_mpc.dll + File output\bassmidi.dll + File output\bassmididrv.dll File bassmididrvcfg.exe File sfpacker.exe ;check if already installed diff --git a/bassmididrv_source/bassmididrv.cpp b/bassmididrv_source/bassmididrv.cpp index 2d92f8a..dbc3e2f 100644 --- a/bassmididrv_source/bassmididrv.cpp +++ b/bassmididrv_source/bassmididrv.cpp @@ -2,12 +2,12 @@ BASSMIDI Driver */ -//#define DEBUG #define STRICT #ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0400 +#define _WIN32_WINNT _WIN32_WINNT_WINXP #endif + #if __DMC__ unsigned long _beginthreadex( void *security, unsigned stack_size, unsigned ( __stdcall *start_address )( void * ), void *arglist, @@ -15,46 +15,57 @@ unsigned long _beginthreadex( void *security, unsigned stack_size, void _endthreadex( unsigned retval ); #endif +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#include #include #include -#include #include -#include "mmddk.h" +#include +#include +#include #include #include -#include #define BASSDEF(f) (WINAPI *f) // define the BASS/BASSMIDI functions as pointers #define BASSMIDIDEF(f) (WINAPI *f) #define LOADBASSFUNCTION(f) *((void**)&f)=GetProcAddress(bass,#f) #define LOADBASSMIDIFUNCTION(f) *((void**)&f)=GetProcAddress(bassmidi,#f) -#include "../bass.h" -#include "../bassmidi.h" +#include +#include #include "sound_out.h" -extern "C" { -BOOL WINAPI DriverCallback( DWORD dwCallBack, DWORD dwFlags, HDRVR hdrvr, DWORD msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2 ); -} #define MAX_DRIVERS 2 #define MAX_CLIENTS 1 // Per driver +/* +#define SAMPLES_PER_FRAME 88 * 2 +#define FRAMES_XAUDIO 30 +#define FRAMES_DSOUND 50 +*/ +#define SAMPLES_PER_FRAME 128 +#define FRAMES_XAUDIO 20 +#define FRAMES_DSOUND 35 +#define SAMPLE_RATE_USED 44100 + + struct Driver_Client { int allocated; - DWORD instance; + DWORD_PTR instance; DWORD flags; DWORD_PTR callback; }; +//Note: drivers[0] is not used (See OnDriverOpen). struct Driver { int open; int clientCount; HDRVR hdrvr; struct Driver_Client clients[MAX_CLIENTS]; -} drivers[MAX_DRIVERS]; +} drivers[MAX_DRIVERS+1]; -int driverCount; +static int driverCount=0; static volatile int OpenCount = 0; static volatile int modm_closed = 1; @@ -78,6 +89,7 @@ static sound_out * sound_driver = NULL; static HINSTANCE bass = 0; // bass handle static HINSTANCE bassmidi = 0; // bassmidi handle +//TODO: Can be done with: HMODULE GetDriverModuleHandle(HDRVR hdrvr); (once DRV_OPEN has been called) static HINSTANCE hinst = NULL; //main DLL handle enum { @@ -92,8 +104,7 @@ static unsigned int synth_mode = synth_mode_gm; static unsigned char gs_part_to_ch[2][16]; static unsigned char drum_channels[32]; -static void DoStartDriver(); -static void DoStopDriver(); +static void DoStopClient(); BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ){ if (fdwReason == DLL_PROCESS_ATTACH){ @@ -101,7 +112,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ){ DisableThreadLibraryCalls(hinstDLL); }else if(fdwReason == DLL_PROCESS_DETACH){ ; - DoStopDriver(); + DoStopClient(); } return TRUE; } @@ -149,7 +160,7 @@ void LoadFonts(const TCHAR * name) font_count = 0; if ( fl ) { - TCHAR path[1024], fontname[1024], temp[1024]; + TCHAR path[MAX_PATH], fontname[MAX_PATH], temp[MAX_PATH]; const TCHAR * filename = _tcsrchr( name, _T('\\') ) + 1; if ( filename == (void*)1 ) filename = _tcsrchr( name, _T(':') ) + 1; if ( filename == (void*)1 ) filename = name; @@ -158,8 +169,8 @@ void LoadFonts(const TCHAR * name) while ( !feof( fl ) ) { TCHAR * cr; - if( !_fgetts( fontname, 1024, fl ) ) break; - fontname[1023] = 0; + if( !_fgetts( fontname, MAX_PATH, fl ) ) break; + fontname[MAX_PATH-1] = 0; cr = _tcsrchr( fontname, _T('\n') ); if ( cr ) *cr = 0; if ( isalpha( fontname[0] ) && fontname[1] == _T(':') ) @@ -182,76 +193,139 @@ void LoadFonts(const TCHAR * name) } } -STDAPI_(LONG) DriverProc(DWORD dwDriverId, HDRVR hdrvr, UINT msg, LONG lParam1, LONG lParam2){ - - switch(msg) { - case DRV_FREE: // XXX never called - return DRV_OK; - case DRV_LOAD: - memset(drivers, 0, sizeof(drivers)); - driverCount = 0; - return DRV_OK; - case DRV_OPEN: - { - int driverNum; - if (driverCount == MAX_DRIVERS) { - return 0; - } else { - for (driverNum = 0; driverNum < MAX_DRIVERS; driverNum++) { - if (!drivers[driverNum].open) { - break; - } - if (driverNum == MAX_DRIVERS) { - return 0; - } - } +LRESULT DoDriverLoad() { + //The DRV_LOAD message is always the first message that a device driver receives. + //Notifies the driver that it has been loaded. The driver should make sure that any hardware and supporting drivers it needs to function properly are present. + //TODO: Check about existence of bass and bassmidi dlls. + memset(drivers, 0, sizeof(drivers)); + driverCount = 0; + return DRV_OK; +} + +LRESULT DoDriverOpen(HDRVR hdrvr, LPCWSTR driverName, LONG lParam) { + +/* +Remarks + +If the driver returns a nonzero value, the system uses that value as the driver identifier (the dwDriverId parameter) +in messages it subsequently sends to the driver instance. The driver can return any type of value as the identifier. +For example, some drivers return memory addresses that point to instance-specific information. Using this method of +specifying identifiers for a driver instance gives the drivers ready access to the information while they are processing messages. +*/ + +/* +When the driver's DriverProc function receives a +DRV_OPEN message, it should: +1. Allocate memory space for a structure instance. +2. Add the structure instance to the linked list. +3. Store instance data in the new list entry. +4. Specify the entry's number or address as the return value for the DriverProc function. +Subsequent calls to DriverProc will include the list entry's identifier as its dwDriverID +argument +*/ + int driverNum; + if (driverCount == MAX_DRIVERS) { + return 0; + } else { + for (driverNum = 1; driverNum < MAX_DRIVERS; driverNum++) { + if (!drivers[driverNum].open) { + break; } - drivers[driverNum].open = 1; - drivers[driverNum].clientCount = 0; - drivers[driverNum].hdrvr = hdrvr; - driverCount++; } - return DRV_OK; - case DRV_CLOSE: // XXX never called - { - int i; - for (i = 0; i < MAX_DRIVERS; i++) { - if (drivers[i].open && drivers[i].hdrvr == hdrvr) { - drivers[i].open = 0; - --driverCount; - return DRV_OK; - } - } + if (driverNum == MAX_DRIVERS) { + return 0; } - return DRV_CANCEL; - case DRV_CONFIGURE: - case DRV_DISABLE: - case DRV_ENABLE: - case DRV_EXITSESSION: - case DRV_REMOVE: + } + drivers[driverNum].open = 1; + drivers[driverNum].clientCount = 0; + drivers[driverNum].hdrvr = hdrvr; + driverCount++; + return driverNum; +} + +LRESULT DoDriverClose(DWORD_PTR dwDriverId, HDRVR hdrvr, LONG lParam1, LONG lParam2) { + int i; + for (i = 0; i < MAX_DRIVERS; i++) { + if (drivers[i].open && drivers[i].hdrvr == hdrvr) { + drivers[i].open = 0; + --driverCount; + return DRV_OK; + } + } + return DRV_CANCEL; +} + +LRESULT DoDriverConfigure(DWORD_PTR dwDriverId, HDRVR hdrvr, HWND parent, DRVCONFIGINFO* configInfo) { + return DRV_CANCEL; +} + +/* INFO Installable Driver Reference: http://msdn.microsoft.com/en-us/library/ms709328%28v=vs.85%29.aspx */ +/* The original header is LONG DriverProc(DWORD dwDriverId, HDRVR hdrvr, UINT msg, LONG lParam1, LONG lParam2); +but that does not support 64bit. See declaration of DefDriverProc to see where the values come from. +*/ +STDAPI_(LRESULT) DriverProc(DWORD_PTR dwDriverId, HDRVR hdrvr, UINT uMsg, LPARAM lParam1, LPARAM lParam2) +{ + switch(uMsg) { +/* Seems this is only for kernel mode drivers case DRV_INSTALL: - case DRV_POWER: + return DoDriverInstall(dwDriverId, hdrvr, static_cast(lParam2)); + case DRV_REMOVE: + DoDriverRemove(dwDriverId, hdrvr); + return DRV_OK; +*/ case DRV_QUERYCONFIGURE: + //TODO: Until it doesn't have a configuration window, it should return 0. + return DRV_CANCEL; + case DRV_CONFIGURE: + return DoDriverConfigure(dwDriverId, hdrvr, reinterpret_cast(lParam1), reinterpret_cast(lParam2)); + +/* TODO: Study this. It has implications: + Calling OpenDriver, described in the Win32 SDK. This function calls SendDriverMessage to + send DRV_LOAD and DRV_ENABLE messages only if the driver has not been previously loaded, + and then to send DRV_OPEN. + · Calling CloseDriver, described in the Win32 SDK. This function calls SendDriverMessage to + send DRV_CLOSE and, if there are no other open instances of the driver, to also send + DRV_DISABLE and DRV_FREE. +*/ + case DRV_LOAD: + return DoDriverLoad(); + case DRV_FREE: + //The DRV_FREE message is always the last message that a device driver receives. + //Notifies the driver that it is being removed from memory. The driver should free any memory and other system resources that it has allocated. return DRV_OK; + case DRV_OPEN: + return DoDriverOpen(hdrvr, reinterpret_cast(lParam1), static_cast(lParam2)); + case DRV_CLOSE: + return DoDriverClose(dwDriverId, hdrvr, static_cast(lParam1), static_cast(lParam2)); + default: + return DefDriverProc(dwDriverId, hdrvr, uMsg, lParam1, lParam2); } - return DRV_OK; } -HRESULT modGetCaps(UINT uDeviceID, PVOID capsPtr, DWORD capsSize) { +HRESULT modGetCaps(UINT uDeviceID, MIDIOUTCAPS* capsPtr, DWORD capsSize) { MIDIOUTCAPSA * myCapsA; MIDIOUTCAPSW * myCapsW; MIDIOUTCAPS2A * myCaps2A; MIDIOUTCAPS2W * myCaps2W; - +#if defined(AMD64) + // WinDDK + CHAR synthName[] = "BASSMIDI Driver 64"; + WCHAR synthNameW[] = L"BASSMIDI Driver 64"; +#elif defined(_WIN64) + //VisualStudio + CHAR synthName[] = "BASSMIDI Driver 64"; + WCHAR synthNameW[] = L"BASSMIDI Driver 64"; +#else CHAR synthName[] = "BASSMIDI Driver"; WCHAR synthNameW[] = L"BASSMIDI Driver"; - +#endif CHAR synthPortA[] = " (port A)\0"; WCHAR synthPortAW[] = L" (port A)\0"; CHAR synthPortB[] = " (port B)\0"; WCHAR synthPortBW[] = L" (port B)\0"; + switch (capsSize) { case (sizeof(MIDIOUTCAPSA)): myCapsA = (MIDIOUTCAPSA *)capsPtr; @@ -259,12 +333,12 @@ HRESULT modGetCaps(UINT uDeviceID, PVOID capsPtr, DWORD capsSize) { myCapsA->wPid = 0xffff; memcpy(myCapsA->szPname, synthName, strlen(synthName)); memcpy(myCapsA->szPname + strlen(synthName), uDeviceID ? synthPortB : synthPortA, sizeof(synthPortA)); - myCapsA->wTechnology = MOD_MIDIPORT; + myCapsA->wTechnology = MOD_SWSYNTH; myCapsA->vDriverVersion = 0x0090; myCapsA->wVoices = 0; myCapsA->wNotes = 0; myCapsA->wChannelMask = 0xffff; - myCapsA->dwSupport = 0; + myCapsA->dwSupport = MIDICAPS_VOLUME; return MMSYSERR_NOERROR; case (sizeof(MIDIOUTCAPSW)): @@ -273,12 +347,12 @@ HRESULT modGetCaps(UINT uDeviceID, PVOID capsPtr, DWORD capsSize) { myCapsW->wPid = 0xffff; memcpy(myCapsW->szPname, synthNameW, wcslen(synthNameW) * sizeof(wchar_t)); memcpy(myCapsW->szPname + wcslen(synthNameW), uDeviceID ? synthPortBW : synthPortAW, sizeof(synthPortAW)); - myCapsW->wTechnology = MOD_MIDIPORT; + myCapsW->wTechnology = MOD_SWSYNTH; myCapsW->vDriverVersion = 0x0090; myCapsW->wVoices = 0; myCapsW->wNotes = 0; myCapsW->wChannelMask = 0xffff; - myCapsW->dwSupport = 0; + myCapsW->dwSupport = MIDICAPS_VOLUME; return MMSYSERR_NOERROR; case (sizeof(MIDIOUTCAPS2A)): @@ -287,12 +361,12 @@ HRESULT modGetCaps(UINT uDeviceID, PVOID capsPtr, DWORD capsSize) { myCaps2A->wPid = 0xffff; memcpy(myCaps2A->szPname, synthName, strlen(synthName)); memcpy(myCaps2A->szPname + strlen(synthName), uDeviceID ? synthPortB : synthPortA, sizeof(synthPortA)); - myCaps2A->wTechnology = MOD_MIDIPORT; + myCaps2A->wTechnology = MOD_SWSYNTH; myCaps2A->vDriverVersion = 0x0090; myCaps2A->wVoices = 0; myCaps2A->wNotes = 0; myCaps2A->wChannelMask = 0xffff; - myCaps2A->dwSupport = 0; + myCaps2A->dwSupport = MIDICAPS_VOLUME; return MMSYSERR_NOERROR; case (sizeof(MIDIOUTCAPS2W)): @@ -301,12 +375,12 @@ HRESULT modGetCaps(UINT uDeviceID, PVOID capsPtr, DWORD capsSize) { myCaps2W->wPid = 0xffff; memcpy(myCaps2W->szPname, synthNameW, wcslen(synthNameW) * sizeof(wchar_t)); memcpy(myCaps2W->szPname + wcslen(synthNameW), uDeviceID ? synthPortBW : synthPortAW, sizeof(synthPortAW)); - myCaps2W->wTechnology = MOD_MIDIPORT; + myCaps2W->wTechnology = MOD_SWSYNTH; myCaps2W->vDriverVersion = 0x0090; myCaps2W->wVoices = 0; myCaps2W->wNotes = 0; myCaps2W->wChannelMask = 0xffff; - myCaps2W->dwSupport = 0; + myCaps2W->dwSupport = MIDICAPS_VOLUME; return MMSYSERR_NOERROR; default: @@ -317,9 +391,9 @@ HRESULT modGetCaps(UINT uDeviceID, PVOID capsPtr, DWORD capsSize) { struct evbuf_t{ UINT uDeviceID; - UINT uMsg; - DWORD dwParam1; - DWORD dwParam2; + UINT uMsg; + DWORD_PTR dwParam1; + DWORD_PTR dwParam2; int exlen; unsigned char *sysexbuffer; }; @@ -379,12 +453,11 @@ void reset_drum_channels() int bmsyn_play_some_data(void){ UINT uDeviceID; UINT uMsg; - DWORD dwParam1; - DWORD dwParam2; + DWORD_PTR dwParam1; + DWORD_PTR dwParam2; DWORD dwChannel; UINT evbpoint; - MIDIHDR *IIMidiHdr; int exlen; unsigned char *sysexbuffer; int played; @@ -490,7 +563,7 @@ int bmsyn_play_some_data(void){ void load_settings() { int config_volume; - HKEY hKey, hSubKey; + HKEY hKey; long lResult; DWORD dwType=REG_DWORD; DWORD dwSize=sizeof(DWORD); @@ -503,7 +576,7 @@ void load_settings() int check_sinc() { int sinc = 0; - HKEY hKey, hSubKey; + HKEY hKey; long lResult; DWORD dwType=REG_DWORD; DWORD dwSize=sizeof(DWORD); @@ -515,15 +588,15 @@ int check_sinc() BOOL load_bassfuncs() { - TCHAR installpath[1024] = {0}; - TCHAR basspath[1024] = {0}; - TCHAR bassmidipath[1024] = {0}; + TCHAR installpath[MAX_PATH] = {0}; + TCHAR basspath[MAX_PATH] = {0}; + TCHAR bassmidipath[MAX_PATH] = {0}; TCHAR pluginpath[MAX_PATH] = {0}; WIN32_FIND_DATA fd; HANDLE fh; int installpathlength; - GetModuleFileName(hinst, installpath, 1024); + GetModuleFileName(hinst, installpath, MAX_PATH); PathRemoveFileSpec(installpath); lstrcat(basspath,installpath); @@ -575,11 +648,9 @@ BOOL load_bassfuncs() unsigned __stdcall threadfunc(LPVOID lpV){ unsigned i; int opend=0; - TCHAR config[1024]; + TCHAR config[MAX_PATH]; BASS_MIDI_FONT * mf; - BASS_INFO info; - BOOL isvista; - ; + while(opend == 0 && stop_thread == 0) { Sleep(100); if (!com_initialized) { @@ -588,11 +659,11 @@ unsigned __stdcall threadfunc(LPVOID lpV){ } if (sound_driver == NULL) { sound_driver = create_sound_out_xaudio2(); - const char * err = sound_driver->open(GetDesktopWindow(), 44100, 2, sound_out_float = TRUE, 88 * 2, 30); + const char * err = sound_driver->open(GetDesktopWindow(), SAMPLE_RATE_USED, 2, (sound_out_float = TRUE) != 0, SAMPLES_PER_FRAME, FRAMES_XAUDIO); if (err) { delete sound_driver; sound_driver = create_sound_out_ds(); - err = sound_driver->open(GetDesktopWindow(), 44100, 2, sound_out_float = FALSE, 88 * 2, 50); + err = sound_driver->open(GetDesktopWindow(), SAMPLE_RATE_USED, 2, (sound_out_float = FALSE) != 0, SAMPLES_PER_FRAME, FRAMES_DSOUND); } if (err) { delete sound_driver; @@ -603,12 +674,12 @@ unsigned __stdcall threadfunc(LPVOID lpV){ load_bassfuncs(); BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 0); BASS_SetConfig(BASS_CONFIG_UPDATETHREADS, 0); - if ( BASS_Init( 0, 44100, 0, GetDesktopWindow(), NULL ) ) { - hStream = BASS_MIDI_StreamCreate( 32, BASS_STREAM_DECODE | ( sound_out_float ? BASS_SAMPLE_FLOAT : 0 ) | (check_sinc()?BASS_MIDI_SINCINTER: 0), 44100 ); + if ( BASS_Init( 0, SAMPLE_RATE_USED, 0, GetDesktopWindow(), NULL ) ) { + hStream = BASS_MIDI_StreamCreate( 32, BASS_STREAM_DECODE | ( sound_out_float ? BASS_SAMPLE_FLOAT : 0 ) | (check_sinc()?BASS_MIDI_SINCINTER: 0), SAMPLE_RATE_USED ); if (!hStream) continue; + BASS_MIDI_StreamEvent( hStream, 0, MIDI_EVENT_SYSTEMEX, MIDI_SYSTEM_GM1 ); load_settings(); - sound_driver->set_volume( sound_out_volume_float ); - if (GetWindowsDirectory(config, 1023 - 16)) + if (GetWindowsDirectory(config, MAX_PATH)) { _tcscat( config, _T("\\bassmidi.sflist") ); } @@ -642,13 +713,13 @@ unsigned __stdcall threadfunc(LPVOID lpV){ } bmsyn_play_some_data(); if (sound_out_float) { - float sound_buffer[88*2]; - int decoded = BASS_ChannelGetData( hStream, sound_buffer, BASS_DATA_FLOAT + 88 * 2 * sizeof(float) ); + float sound_buffer[SAMPLES_PER_FRAME]; + int decoded = BASS_ChannelGetData( hStream, sound_buffer, BASS_DATA_FLOAT + SAMPLES_PER_FRAME * sizeof(float) ); if ( decoded < 0 ) Sleep(1); else sound_driver->write_frame( sound_buffer, decoded / sizeof(float), true ); } else { - short sound_buffer[88*2]; - int decoded = BASS_ChannelGetData( hStream, sound_buffer, 88 * 2 * sizeof(short) ); + short sound_buffer[SAMPLES_PER_FRAME]; + int decoded = BASS_ChannelGetData( hStream, sound_buffer, SAMPLES_PER_FRAME * sizeof(short) ); if ( decoded < 0 ) Sleep(1); else sound_driver->write_frame( sound_buffer, decoded / sizeof(short), true ); } @@ -681,12 +752,12 @@ unsigned __stdcall threadfunc(LPVOID lpV){ return 0; } -void DoCallback(int driverNum, int clientNum, DWORD msg, DWORD param1, DWORD param2) { +void DoCallback(int driverNum, int clientNum, DWORD msg, DWORD_PTR param1, DWORD_PTR param2) { struct Driver_Client *client = &drivers[driverNum].clients[clientNum]; DriverCallback(client->callback, client->flags, drivers[driverNum].hdrvr, msg, client->instance, param1, param2); } -void DoStartDriver() { +void DoStartClient() { if (modm_closed == 1) { DWORD result; unsigned int thrdaddr; @@ -711,7 +782,7 @@ void DoStartDriver() { } } -void DoStopDriver() { +void DoStopClient() { if (modm_closed == 0){ stop_thread = 1; WaitForSingleObject(hCalcThread, INFINITE); @@ -722,16 +793,30 @@ void DoStopDriver() { DeleteCriticalSection(&mim_section); } -void DoResetDriver(DWORD dwParam1, DWORD dwParam2) { +void DoResetClient() { + /* + TODO : If the driver's output queue contains any output buffers (see MODM_LONGDATA) whose contents +have not been sent to the kernel-mode driver, the driver should set the MHDR_DONE flag and +clear the MHDR_INQUEUE flag in each buffer's MIDIHDR structure, and then send the client a +MOM_DONE callback message for each buffer. + */ reset_synth = 1; } -LONG DoOpenDriver(struct Driver *driver, UINT uDeviceID, UINT uMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { +LONG DoOpenClient(struct Driver *driver, UINT uDeviceID, LONG* dwUser, MIDIOPENDESC * desc, DWORD flags) { +/* For the MODM_OPEN message, dwUser is an output parameter. +The driver creates the instance identifier and returns it in the address specified as +the argument. The argument is the instance identifier. +CALLBACK_EVENT Indicates dwCallback member of MIDIOPENDESC is an event handle. +CALLBACK_FUNCTION Indicates dwCallback member of MIDIOPENDESC is the address of a callback function. +CALLBACK_TASK Indicates dwCallback member of MIDIOPENDESC is a task handle. +CALLBACK_WINDOW Indicates dwCallback member of MIDIOPENDESC is a window handle. +*/ int clientNum; - MIDIOPENDESC *desc; if (driver->clientCount == 0) { - DoStartDriver(); - DoResetDriver(dwParam1, dwParam2); + //TODO: Part of this might be done in DoDriverOpen instead. + DoStartClient(); + DoResetClient(); clientNum = 0; } else if (driver->clientCount == MAX_CLIENTS) { return MMSYSERR_ALLOCATED; @@ -747,19 +832,28 @@ LONG DoOpenDriver(struct Driver *driver, UINT uDeviceID, UINT uMsg, DWORD dwUser } clientNum = i; } - desc = (MIDIOPENDESC *)dwParam1; driver->clients[clientNum].allocated = 1; - driver->clients[clientNum].flags = HIWORD(dwParam2); + driver->clients[clientNum].flags = HIWORD(flags); driver->clients[clientNum].callback = desc->dwCallback; driver->clients[clientNum].instance = desc->dwInstance; - *(LONG *)dwUser = clientNum; + *dwUser = clientNum; driver->clientCount++; SetPriorityClass(GetCurrentProcess(), processPriority); + //TODO: desc and flags + DoCallback(uDeviceID, clientNum, MOM_OPEN, 0, 0); return MMSYSERR_NOERROR; } -LONG DoCloseDriver(struct Driver *driver, UINT uDeviceID, UINT uMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { +LONG DoCloseClient(struct Driver *driver, UINT uDeviceID, LONG dwUser) { +/* +If the client has passed data buffers to the user-mode driver by means of MODM_LONGDATA +messages, and if the user-mode driver hasn't finished sending the data to the kernel-mode driver, +the user-mode driver should return MIDIERR_STILLPLAYING in response to MODM_CLOSE. +After the driver closes the device instance it should send a MOM_CLOSE callback message to +the client. +*/ + if (!driver->clients[dwUser].allocated) { return MMSYSERR_INVALPARAM; } @@ -767,29 +861,14 @@ LONG DoCloseDriver(struct Driver *driver, UINT uDeviceID, UINT uMsg, DWORD dwUse driver->clients[dwUser].allocated = 0; driver->clientCount--; if(driver->clientCount <= 0) { - DoResetDriver(dwParam1, dwParam2); + DoResetClient(); driver->clientCount = 0; } DoCallback(uDeviceID, dwUser, MOM_CLOSE, 0, 0); return MMSYSERR_NOERROR; } - -STDAPI_(LONG) midMessage(UINT uDeviceID, UINT uMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { - struct Driver *driver = &drivers[uDeviceID]; - switch (uMsg) { - case MIDM_OPEN: - return DoOpenDriver(driver, uDeviceID, uMsg, dwUser, dwParam1, dwParam2); - - case MIDM_CLOSE: - return DoCloseDriver(driver, uDeviceID, uMsg, dwUser, dwParam1, dwParam2); - - default: - return MMSYSERR_NOERROR; - break; - } -} - -STDAPI_(LONG) modMessage(UINT uDeviceID, UINT uMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2){ +/* Audio Device Messages for MIDI http://msdn.microsoft.com/en-us/library/ff536194%28v=vs.85%29 */ +STDAPI_(DWORD) modMessage(UINT uDeviceID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2){ MIDIHDR *IIMidiHdr; UINT evbpoint; struct Driver *driver = &drivers[uDeviceID]; @@ -798,26 +877,22 @@ STDAPI_(LONG) modMessage(UINT uDeviceID, UINT uMsg, DWORD dwUser, DWORD dwParam1 DWORD result = 0; switch (uMsg) { case MODM_OPEN: - return DoOpenDriver(driver, uDeviceID, uMsg, dwUser, dwParam1, dwParam2); - break; + return DoOpenClient(driver, uDeviceID, reinterpret_cast(dwUser), reinterpret_cast(dwParam1), static_cast(dwParam2)); case MODM_PREPARE: + /*If the driver returns MMSYSERR_NOTSUPPORTED, winmm.dll prepares the buffer for use. For +most drivers, this behavior is sufficient.*/ return MMSYSERR_NOTSUPPORTED; - break; case MODM_UNPREPARE: return MMSYSERR_NOTSUPPORTED; - break; + case MODM_GETNUMDEVS: + return 0x2; case MODM_GETDEVCAPS: - return modGetCaps(uDeviceID, (PVOID)dwParam1, dwParam2); - break; - case MODM_RESET: - DoResetDriver(dwParam1, dwParam2); - return MMSYSERR_NOERROR; + return modGetCaps(uDeviceID, reinterpret_cast(dwParam1), static_cast(dwParam2)); case MODM_LONGDATA: IIMidiHdr = (MIDIHDR *)dwParam1; if( !(IIMidiHdr->dwFlags & MHDR_PREPARED) ) return MIDIERR_UNPREPARED; IIMidiHdr->dwFlags &= ~MHDR_DONE; IIMidiHdr->dwFlags |= MHDR_INQUEUE; - IIMidiHdr = (MIDIHDR *) dwParam1; exlen=(int)IIMidiHdr->dwBufferLength; if( NULL == (sysexbuffer = (unsigned char *)malloc(exlen * sizeof(char)))){ return MMSYSERR_NOMEM; @@ -835,15 +910,22 @@ STDAPI_(LONG) modMessage(UINT uDeviceID, UINT uMsg, DWORD dwUser, DWORD dwParam1 fclose(logfile); #endif } + /* + TODO: When the buffer contents have been sent, the driver should set the MHDR_DONE flag, clear the + MHDR_INQUEUE flag, and send the client a MOM_DONE callback message. + + + In other words, these three lines should be done when the evbuf[evbpoint] is sent. + */ IIMidiHdr->dwFlags &= ~MHDR_INQUEUE; IIMidiHdr->dwFlags |= MHDR_DONE; - DoCallback(uDeviceID, dwUser, MOM_DONE, dwParam1, 0); + DoCallback(uDeviceID, static_cast(dwUser), MOM_DONE, dwParam1, 0); + //fallthrough case MODM_DATA: EnterCriticalSection(&mim_section); evbpoint = evbwpoint; if (++evbwpoint >= EVBUFF_SIZE) evbwpoint -= EVBUFF_SIZE; - evbuf[evbpoint].uDeviceID = uDeviceID; evbuf[evbpoint].uMsg = uMsg; evbuf[evbpoint].dwParam1 = dwParam1; evbuf[evbpoint].dwParam2 = dwParam2; @@ -851,13 +933,43 @@ STDAPI_(LONG) modMessage(UINT uDeviceID, UINT uMsg, DWORD dwUser, DWORD dwParam1 evbuf[evbpoint].sysexbuffer=sysexbuffer; LeaveCriticalSection(&mim_section); return MMSYSERR_NOERROR; - break; - case MODM_GETNUMDEVS: - return 0x2; - break; + + case MODM_GETVOLUME : { + *(LONG*)dwParam1 = static_cast(sound_out_volume_float * 0xFFFF); + return MMSYSERR_NOERROR; + } + case MODM_SETVOLUME: { + sound_out_volume_float = LOWORD(dwParam1) / (float)0xFFFF; + sound_driver->set_volume(sound_out_volume_float); + return MMSYSERR_NOERROR; + } + + case MODM_RESET: + DoResetClient(); + return MMSYSERR_NOERROR; +/* + MODM_GETPOS + MODM_PAUSE + //The driver must halt MIDI playback in the current position. The driver must then turn off all notes that are currently on. + MODM_RESTART + //The MIDI output device driver must restart MIDI playback at the current position. + // playback will start on the first MODM_RESTART message that is received regardless of the number of MODM_PAUSE that messages were received. + //Likewise, MODM_RESTART messages that are received while the driver is already in play mode must be ignored. MMSYSERR_NOERROR must be returned in either case + MODM_STOP + //Like reset, without resetting. + MODM_PROPERTIES + MODM_STRMDATA +*/ + case MODM_CLOSE: - return DoCloseDriver(driver, uDeviceID, uMsg, dwUser, dwParam1, dwParam2); + return DoCloseClient(driver, uDeviceID, static_cast(dwUser)); break; + +/* + MODM_CACHEDRUMPATCHES + MODM_CACHEPATCHES +*/ + default: return MMSYSERR_NOERROR; break; diff --git a/bassmididrv_source/bassmididrv.def b/bassmididrv_source/bassmididrv.def index b7888ec..7ce9200 100644 --- a/bassmididrv_source/bassmididrv.def +++ b/bassmididrv_source/bassmididrv.def @@ -2,4 +2,3 @@ LIBRARY "bassmididrv.dll" EXPORTS DriverProc PRIVATE modMessage PRIVATE - midMessage PRIVATE diff --git a/bassmididrv_source/bassmididrv.sln b/bassmididrv_source/bassmididrv.sln deleted file mode 100644 index 4a08dd3..0000000 --- a/bassmididrv_source/bassmididrv.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bassmidi_win32drv", "bassmididrv.vcxproj", "{BD7491C1-986F-4D48-99E6-018AB4ACF801}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {BD7491C1-986F-4D48-99E6-018AB4ACF801}.Debug|Win32.ActiveCfg = Debug|Win32 - {BD7491C1-986F-4D48-99E6-018AB4ACF801}.Debug|Win32.Build.0 = Debug|Win32 - {BD7491C1-986F-4D48-99E6-018AB4ACF801}.Release|Win32.ActiveCfg = Release|Win32 - {BD7491C1-986F-4D48-99E6-018AB4ACF801}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/bassmididrv_source/bassmididrv.vcxproj b/bassmididrv_source/bassmididrv.vcxproj index ee0e4ee..40631aa 100644 --- a/bassmididrv_source/bassmididrv.vcxproj +++ b/bassmididrv_source/bassmididrv.vcxproj @@ -20,14 +20,14 @@ - - + + - - - - - + + + + + @@ -64,11 +64,11 @@ <_ProjectFileVersion>10.0.40219.1 - .\Debug\ - .\Debug\ + $(ProjectDir)\..\output\$(PlatformName)\$(ConfigurationName) + $(ProjectDir)\..\output\$(PlatformName)\$(ConfigurationName)\intermediate true - .\Release\ - .\Release\ + $(ProjectDir)\..\output\$(PlatformName)\$(ConfigurationName) + $(ProjectDir)\..\output\$(PlatformName)\$(ConfigurationName)\intermediate false AllRules.ruleset @@ -77,8 +77,8 @@ $(IncludePath) - $(DXSDK_DIR)lib\x86;$(LibraryPath) - $(DXSDK_DIR)lib\x86;$(LibraryPath) + $(DXSDK_DIR)lib\x86;$(LibraryPath);$(ProjectDir)\..\external_packages\lib + $(DXSDK_DIR)lib\x86;$(LibraryPath);$(ProjectDir)\..\external_packages\lib @@ -90,11 +90,11 @@ - .\Debug/bassmidi_win32drv.tlb + bassmidi_win32drv.tlb Disabled - ../../bass/c;inc;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\external_packages;%(AdditionalIncludeDirectories) _DEBUG;_USRDLL;I_ASM;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -103,10 +103,10 @@ stdafx.h - .\Debug/bassmidi_win32drv.pch - .\Debug/ - .\Debug/ - .\Debug/ + bassmidi_win32drv.pch + + + Level3 true EditAndContinue @@ -120,19 +120,19 @@ /MACHINE:I386 %(AdditionalOptions) dxguid.lib;winmm.lib;Shlwapi.lib;%(AdditionalDependencies) LinkVerboseLib - ..\bassmididrv.dll + $(OutDir)\bassmididrv.dll true false %(IgnoreSpecificDefaultLibraries) .\bassmididrv.def true - .\Debug/bassmididrv.pdb + bassmididrv.pdb Windows false - .\Debug/bassmidi_win32drv.lib - ../../bass/c + .bassmidi_win32drv.lib + $(ProjectDir)\..\external_packages\lib @@ -145,7 +145,7 @@ - .\Release/bassmidi_win32drv.tlb + bassmidi_win32drv.tlb MinSpace @@ -153,7 +153,7 @@ false Speed true - ../../bass/c;inc;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\external_packages;%(AdditionalIncludeDirectories) NDEBUG;_USRDLL;I_ASM;%(PreprocessorDefinitions) true MultiThreaded @@ -161,10 +161,10 @@ stdafx.h - .\Release/bassmidi_win32drv.pch - .\Release/ - .\Release/ - .\Release/ + bassmidi_win32drv.pch + + + Level3 true Default @@ -178,20 +178,20 @@ /MACHINE:I386 %(AdditionalOptions) dxguid.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Shlwapi.lib;%(AdditionalDependencies) LinkVerboseLib - ..\bassmididrv.dll + $(OutDir)\bassmididrv.dll true false .\bassmididrv.def - .\Release/bassmididrv.pdb + bassmididrv.pdb Windows false - .\Release/bassmidi_win32drv.lib + bassmidi_win32drv.lib true true true - ../../bass/c + $(ProjectDir)\..\external_packages\lib diff --git a/bassmididrv_source/build.bat b/bassmididrv_source/build.bat deleted file mode 100644 index 674bce9..0000000 --- a/bassmididrv_source/build.bat +++ /dev/null @@ -1 +0,0 @@ -@cl /O1 /MT /EHsc /DUNICODE /D_UNICODE /LD /Iinc bassmididrv.cpp dsound.cpp sound_out_dsound.cpp sound_out_xaudio2.cpp user32.lib Shlwapi.lib advapi32.lib winmm.lib Ole32.lib bassmididrv.def diff --git a/bassmididrv_source/build_debug.bat b/bassmididrv_source/build_debug.bat deleted file mode 100644 index 1fd8db5..0000000 --- a/bassmididrv_source/build_debug.bat +++ /dev/null @@ -1 +0,0 @@ -@cl /Od /Zi /MTd /EHsc /DUNICODE /D_UNICODE /LD /Iinc bassmididrv.cpp dsound.cpp sound_out_dsound.cpp sound_out_xaudio2.cpp user32.lib Shlwapi.lib advapi32.lib winmm.lib Ole32.lib bassmididrv.def diff --git a/bassmididrv_source/ds_stream.h b/bassmididrv_source/ds_stream.h index 58f33ac..244bcf9 100644 --- a/bassmididrv_source/ds_stream.h +++ b/bassmididrv_source/ds_stream.h @@ -3,10 +3,10 @@ class ds_stream { -protected: - ds_stream() {} - ~ds_stream() {} public: + ds_stream() {} + virtual ~ds_stream() {} + virtual bool write(const void * data,unsigned bytes)=0; virtual bool is_playing()=0; virtual double get_latency()=0; @@ -23,7 +23,8 @@ class ds_stream struct ds_stream_config { - unsigned srate,nch,bps; + unsigned srate; + unsigned short nch,bps; unsigned buffer_ms; ds_stream_config() @@ -35,7 +36,7 @@ class ds_api { protected: ds_api() {} - ~ds_api() {} + virtual ~ds_api() {} public: virtual ds_stream * ds_stream_create(const ds_stream_config * cfg)=0; virtual void set_device(const GUID * id)=0; diff --git a/bassmididrv_source/dsound.cpp b/bassmididrv_source/dsound.cpp index e7713ce..ff034bf 100644 --- a/bassmididrv_source/dsound.cpp +++ b/bassmididrv_source/dsound.cpp @@ -1,7 +1,10 @@ +#define STRICT +#ifndef _WIN32_WINNT +#define _WIN32_WINNT _WIN32_WINNT_WINXP +#endif + #include -#define _WIN32_WINNT 0x500 -#define STRICT #include //#define HAVE_KS_HEADERS @@ -10,7 +13,7 @@ #include #include #include - +#include #include #ifdef HAVE_KS_HEADERS @@ -120,19 +123,7 @@ class ds_api_i : public ds_api void g_thread_proc(); - - - void g_cleanup_thread() - { - CloseHandle(g_thread); - g_thread = 0; - g_thread_id = 0; - for ( unsigned i = 0; i < g_streams.size(); i++ ) delete g_streams[ i ]; - g_streams.clear(); - g_p_ds->Release(); - g_p_ds = 0; - } - + void g_cleanup_thread(); void g_thread_sleep() { assert(g_is_update_thread()); @@ -151,7 +142,7 @@ class ds_api_i : public ds_api critical_section g_sync; ds_api_i(HWND); - ~ds_api_i(); + virtual ~ds_api_i(); virtual ds_stream * ds_stream_create(const ds_stream_config * cfg); virtual void set_device(const GUID * id); virtual void release(); @@ -165,7 +156,8 @@ class ds_stream_i : public ds_stream critical_section & g_sync; IDirectSoundBuffer * p_dsb; - unsigned srate,nch,bps; + unsigned srate; + unsigned short nch,bps; circular_buffer incoming; bool b_error; @@ -202,7 +194,7 @@ class ds_stream_i : public ds_stream bool is_paused() {return paused;} ds_stream_i(ds_api_i * p_api,const ds_stream_config * cfg); - ~ds_stream_i(); + virtual ~ds_stream_i(); virtual bool write(const void * data,unsigned bytes); virtual bool is_playing(); @@ -224,6 +216,16 @@ class ds_stream_i : public ds_stream }; +void ds_api_i::g_cleanup_thread() +{ + CloseHandle(g_thread); + g_thread = 0; + g_thread_id = 0; + for ( unsigned i = 0; i < g_streams.size(); i++ ) delete g_streams[ i ]; + g_streams.clear(); + g_p_ds->Release(); + g_p_ds = 0; +} void ds_api_i::g_thread_proc() { @@ -633,7 +635,7 @@ void ds_stream_i::set_volume_internal(double val) { double vol_log = val>0 ? 20.0*log10(val) : -100.0; // console::info(uStringPrintf("%06u",(unsigned)(-vol_log * 100))); - p_dsb->SetVolume((long)(vol_log * 100)); + p_dsb->SetVolume(static_cast(vol_log * 100)); current_volume = val; } } @@ -664,7 +666,7 @@ bool ds_stream_i::set_ratio(double ratio) if (b_error) return false; else { - if ( FAILED( p_dsb->SetFrequency( srate * ratio ) ) ) return false; + if ( FAILED( p_dsb->SetFrequency( static_cast(srate * ratio) ) ) ) return false; else return true; } } diff --git a/bassmididrv_source/sound_out.h b/bassmididrv_source/sound_out.h index 6d3887d..0eaea1c 100644 --- a/bassmididrv_source/sound_out.h +++ b/bassmididrv_source/sound_out.h @@ -6,7 +6,7 @@ class sound_out public: virtual ~sound_out() {} - virtual const char* open( void * hwnd, unsigned sample_rate, unsigned nch, bool floating_point, unsigned max_samples_per_frame, unsigned num_frames ) = 0; + virtual const char* open( void * hwnd, unsigned sample_rate, unsigned short nch, bool floating_point, unsigned max_samples_per_frame, unsigned num_frames ) = 0; virtual const char* write_frame( void * buffer, unsigned num_samples, bool wait = true ) = 0; diff --git a/bassmididrv_source/sound_out_dsound.cpp b/bassmididrv_source/sound_out_dsound.cpp index dbd16a0..7ba12a1 100644 --- a/bassmididrv_source/sound_out_dsound.cpp +++ b/bassmididrv_source/sound_out_dsound.cpp @@ -1,3 +1,8 @@ +#define STRICT +#ifndef _WIN32_WINNT +#define _WIN32_WINNT _WIN32_WINNT_WINXP +#endif + #include #include "sound_out.h" @@ -11,7 +16,8 @@ class sound_out_i_dsound : public sound_out bool paused; - unsigned sample_rate, nch, max_samples_per_frame, num_frames, bytes_per_sample, buffer_size_bytes, last_write; + unsigned sample_rate, max_samples_per_frame, num_frames, bytes_per_sample, buffer_size_bytes, last_write; + unsigned short nch; public: sound_out_i_dsound() @@ -26,7 +32,7 @@ class sound_out_i_dsound : public sound_out close(); } - virtual const char* open( void * hwnd, unsigned sample_rate, unsigned nch, bool floating_point, unsigned max_samples_per_frame, unsigned num_frames ) + virtual const char* open( void * hwnd, unsigned sample_rate, unsigned short nch, bool floating_point, unsigned max_samples_per_frame, unsigned num_frames ) { p_api = ds_api_create( (HWND) hwnd ); if ( !p_api ) @@ -78,7 +84,7 @@ class sound_out_i_dsound : public sound_out return 0; } - int buffer_size_write = (int) num_samples * bytes_per_sample; + unsigned int buffer_size_write = num_samples * bytes_per_sample; if ( wait ) { diff --git a/bassmididrv_source/sound_out_xaudio2.cpp b/bassmididrv_source/sound_out_xaudio2.cpp index 19d67c0..464ddaf 100644 --- a/bassmididrv_source/sound_out_xaudio2.cpp +++ b/bassmididrv_source/sound_out_xaudio2.cpp @@ -1,8 +1,12 @@ +#define STRICT +#ifndef _WIN32_WINNT +#define _WIN32_WINNT _WIN32_WINNT_WINXP +#endif + #include "sound_out.h" //#define HAVE_KS_HEADERS -#define STRICT #include #include #include @@ -14,6 +18,7 @@ #include #endif + #pragma comment ( lib, "winmm.lib" ) class sound_out_i_xaudio2; @@ -71,7 +76,7 @@ class XAudio2_Device_Notifier : public IMMNotificationClient if ( flow == eRender ) { EnterCriticalSection( &lock ); - for ( auto it = instances.begin(); it < instances.end(); ++it ) + for ( std::vector::iterator it = instances.begin(); it < instances.end(); ++it ) { xaudio2_device_changed( *it ); } @@ -118,7 +123,7 @@ class XAudio2_Device_Notifier : public IMMNotificationClient } EnterCriticalSection( &lock ); - for ( auto it = instances.begin(); it < instances.end(); ++it ) + for ( std::vector::iterator it = instances.begin(); it < instances.end(); ++it ) { if ( *it == p_instance ) { @@ -177,7 +182,8 @@ class sound_out_i_xaudio2 : public sound_out bool paused; volatile bool device_changed; unsigned reopen_count; - unsigned sample_rate, nch, bytes_per_sample, max_samples_per_frame, num_frames; + unsigned sample_rate, bytes_per_sample, max_samples_per_frame, num_frames; + unsigned short nch; volatile LONG buffered_count; volatile LONG buffer_read_cursor; LONG buffer_write_cursor; @@ -221,7 +227,7 @@ class sound_out_i_xaudio2 : public sound_out device_changed = true; } - virtual const char* open( void * hwnd, unsigned sample_rate, unsigned nch, bool floating_point, unsigned max_samples_per_frame, unsigned num_frames ) + virtual const char* open( void * hwnd, unsigned sample_rate, unsigned short nch, bool floating_point, unsigned max_samples_per_frame, unsigned num_frames ) { this->hwnd = hwnd; this->sample_rate = sample_rate; @@ -421,13 +427,13 @@ class sound_out_i_xaudio2 : public sound_out virtual const char* set_volume( double volume ) { - if ( !reopen_count && FAILED( mVoice->SetVolume( volume ) ) ) return "setting volume"; + if ( !reopen_count && FAILED( mVoice->SetVolume( static_cast(volume) ) ) ) return "setting volume"; return 0; } virtual const char* set_ratio( double ratio ) { - if ( !reopen_count && FAILED( sVoice->SetFrequencyRatio( ratio ) ) ) return "setting ratio"; + if ( !reopen_count && FAILED( sVoice->SetFrequencyRatio( static_cast(ratio) ) ) ) return "setting ratio"; return 0; } diff --git a/drivercfg/Views.h b/drivercfg/Views.h index 3185a5c..9d6f6af 100644 --- a/drivercfg/Views.h +++ b/drivercfg/Views.h @@ -12,8 +12,8 @@ #define BASSMIDIDEF(f) (WINAPI *f) #define LOADBASSFUNCTION(f) *((void**)&f)=GetProcAddress(bass,#f) #define LOADBASSMIDIFUNCTION(f) *((void**)&f)=GetProcAddress(bassmidi,#f) -#include "../bass.h" -#include "../bassmidi.h" +#include "../external_packages/bass.h" +#include "../external_packages/bassmidi.h" using namespace std; using namespace utf8util; diff --git a/drivercfg/drivercfg.vcxproj b/drivercfg/drivercfg.vcxproj index 7c17214..d9579c0 100644 --- a/drivercfg/drivercfg.vcxproj +++ b/drivercfg/drivercfg.vcxproj @@ -129,11 +129,8 @@ - - - - - + + diff --git a/external_packages/XAudio2.h b/external_packages/XAudio2.h new file mode 100644 index 0000000..885b92f --- /dev/null +++ b/external_packages/XAudio2.h @@ -0,0 +1,1282 @@ +/************************************************************************** + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * + * File: xaudio2.h + * Content: Declarations for the XAudio2 game audio API. + * + **************************************************************************/ + +#ifndef __XAUDIO2_INCLUDED__ +#define __XAUDIO2_INCLUDED__ + + +/************************************************************************** + * + * XAudio2 COM object class and interface IDs. + * + **************************************************************************/ + +#include // For DEFINE_CLSID and DEFINE_IID + +// XAudio 2.0 (March 2008 SDK) +//DEFINE_CLSID(XAudio2, fac23f48, 31f5, 45a8, b4, 9b, 52, 25, d6, 14, 01, aa); +//DEFINE_CLSID(XAudio2_Debug, fac23f48, 31f5, 45a8, b4, 9b, 52, 25, d6, 14, 01, db); + +// XAudio 2.1 (June 2008 SDK) +//DEFINE_CLSID(XAudio2, e21a7345, eb21, 468e, be, 50, 80, 4d, b9, 7c, f7, 08); +//DEFINE_CLSID(XAudio2_Debug, f7a76c21, 53d4, 46bb, ac, 53, 8b, 45, 9c, ae, 46, bd); + +// XAudio 2.2 (August 2008 SDK) +//DEFINE_CLSID(XAudio2, b802058a, 464a, 42db, bc, 10, b6, 50, d6, f2, 58, 6a); +//DEFINE_CLSID(XAudio2_Debug, 97dfb7e7, 5161, 4015, 87, a9, c7, 9e, 6a, 19, 52, cc); + +// XAudio 2.3 (November 2008 SDK) +//DEFINE_CLSID(XAudio2, 4c5e637a, 16c7, 4de3, 9c, 46, 5e, d2, 21, 81, 96, 2d); +//DEFINE_CLSID(XAudio2_Debug, ef0aa05d, 8075, 4e5d, be, ad, 45, be, 0c, 3c, cb, b3); + +// XAudio 2.4 (March 2009 SDK) +//DEFINE_CLSID(XAudio2, 03219e78, 5bc3, 44d1, b9, 2e, f6, 3d, 89, cc, 65, 26); +//DEFINE_CLSID(XAudio2_Debug, 4256535c, 1ea4, 4d4b, 8a, d5, f9, db, 76, 2e, ca, 9e); + +// XAudio 2.5 (August 2009 SDK) +//DEFINE_CLSID(XAudio2, 4c9b6dde, 6809, 46e6, a2, 78, 9b, 6a, 97, 58, 86, 70); +//DEFINE_CLSID(XAudio2_Debug, 715bdd1a, aa82, 436b, b0, fa, 6a, ce, a3, 9b, d0, a1); + +// XAudio 2.6 (February 2010 SDK) +//DEFINE_CLSID(XAudio2, 3eda9b49, 2085, 498b, 9b, b2, 39, a6, 77, 84, 93, de); +//DEFINE_CLSID(XAudio2_Debug, 47199894, 7cc2, 444d, 98, 73, ce, d2, 56, 2c, c6, 0e); + +// XAudio 2.7 (June 2010 SDK) +DEFINE_CLSID(XAudio2, 5a508685, a254, 4fba, 9b, 82, 9a, 24, b0, 03, 06, af); +DEFINE_CLSID(XAudio2_Debug, db05ea35, 0329, 4d4b, a5, 3a, 6d, ea, d0, 3d, 38, 52); +DEFINE_IID(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb); + + +// Ignore the rest of this header if only the GUID definitions were requested +#ifndef GUID_DEFS_ONLY + +#ifdef _XBOX + #include // Xbox COM declarations (IUnknown, etc) +#else + #include // Windows COM declarations +#endif + +#include // Markers for documenting API semantics +#include // Basic audio data types and constants +#include // Data types and constants for XMA2 audio + +// All structures defined in this file use tight field packing +#pragma pack(push, 1) + + +/************************************************************************** + * + * XAudio2 constants, flags and error codes. + * + **************************************************************************/ + +// Numeric boundary values +#define XAUDIO2_MAX_BUFFER_BYTES 0x80000000 // Maximum bytes allowed in a source buffer +#define XAUDIO2_MAX_QUEUED_BUFFERS 64 // Maximum buffers allowed in a voice queue +#define XAUDIO2_MAX_BUFFERS_SYSTEM 2 // Maximum buffers allowed for system threads (Xbox 360 only) +#define XAUDIO2_MAX_AUDIO_CHANNELS 64 // Maximum channels in an audio stream +#define XAUDIO2_MIN_SAMPLE_RATE 1000 // Minimum audio sample rate supported +#define XAUDIO2_MAX_SAMPLE_RATE 200000 // Maximum audio sample rate supported +#define XAUDIO2_MAX_VOLUME_LEVEL 16777216.0f // Maximum acceptable volume level (2^24) +#define XAUDIO2_MIN_FREQ_RATIO (1/1024.0f) // Minimum SetFrequencyRatio argument +#define XAUDIO2_MAX_FREQ_RATIO 1024.0f // Maximum MaxFrequencyRatio argument +#define XAUDIO2_DEFAULT_FREQ_RATIO 2.0f // Default MaxFrequencyRatio argument +#define XAUDIO2_MAX_FILTER_ONEOVERQ 1.5f // Maximum XAUDIO2_FILTER_PARAMETERS.OneOverQ +#define XAUDIO2_MAX_FILTER_FREQUENCY 1.0f // Maximum XAUDIO2_FILTER_PARAMETERS.Frequency +#define XAUDIO2_MAX_LOOP_COUNT 254 // Maximum non-infinite XAUDIO2_BUFFER.LoopCount +#define XAUDIO2_MAX_INSTANCES 8 // Maximum simultaneous XAudio2 objects on Xbox 360 + +// For XMA voices on Xbox 360 there is an additional restriction on the MaxFrequencyRatio +// argument and the voice's sample rate: the product of these numbers cannot exceed 600000 +// for one-channel voices or 300000 for voices with more than one channel. +#define XAUDIO2_MAX_RATIO_TIMES_RATE_XMA_MONO 600000 +#define XAUDIO2_MAX_RATIO_TIMES_RATE_XMA_MULTICHANNEL 300000 + +// Numeric values with special meanings +#define XAUDIO2_COMMIT_NOW 0 // Used as an OperationSet argument +#define XAUDIO2_COMMIT_ALL 0 // Used in IXAudio2::CommitChanges +#define XAUDIO2_INVALID_OPSET (UINT32)(-1) // Not allowed for OperationSet arguments +#define XAUDIO2_NO_LOOP_REGION 0 // Used in XAUDIO2_BUFFER.LoopCount +#define XAUDIO2_LOOP_INFINITE 255 // Used in XAUDIO2_BUFFER.LoopCount +#define XAUDIO2_DEFAULT_CHANNELS 0 // Used in CreateMasteringVoice +#define XAUDIO2_DEFAULT_SAMPLERATE 0 // Used in CreateMasteringVoice + +// Flags +#define XAUDIO2_DEBUG_ENGINE 0x0001 // Used in XAudio2Create on Windows only +#define XAUDIO2_VOICE_NOPITCH 0x0002 // Used in IXAudio2::CreateSourceVoice +#define XAUDIO2_VOICE_NOSRC 0x0004 // Used in IXAudio2::CreateSourceVoice +#define XAUDIO2_VOICE_USEFILTER 0x0008 // Used in IXAudio2::CreateSource/SubmixVoice +#define XAUDIO2_VOICE_MUSIC 0x0010 // Used in IXAudio2::CreateSourceVoice +#define XAUDIO2_PLAY_TAILS 0x0020 // Used in IXAudio2SourceVoice::Stop +#define XAUDIO2_END_OF_STREAM 0x0040 // Used in XAUDIO2_BUFFER.Flags +#define XAUDIO2_SEND_USEFILTER 0x0080 // Used in XAUDIO2_SEND_DESCRIPTOR.Flags + +// Default parameters for the built-in filter +#define XAUDIO2_DEFAULT_FILTER_TYPE LowPassFilter +#define XAUDIO2_DEFAULT_FILTER_FREQUENCY XAUDIO2_MAX_FILTER_FREQUENCY +#define XAUDIO2_DEFAULT_FILTER_ONEOVERQ 1.0f + +// Internal XAudio2 constants +#ifdef _XBOX + #define XAUDIO2_QUANTUM_NUMERATOR 2 // On Xbox 360, XAudio2 processes audio + #define XAUDIO2_QUANTUM_DENOMINATOR 375 // in 5.333ms chunks (= 2/375 seconds) +#else + #define XAUDIO2_QUANTUM_NUMERATOR 1 // On Windows, XAudio2 processes audio + #define XAUDIO2_QUANTUM_DENOMINATOR 100 // in 10ms chunks (= 1/100 seconds) +#endif +#define XAUDIO2_QUANTUM_MS (1000.0f * XAUDIO2_QUANTUM_NUMERATOR / XAUDIO2_QUANTUM_DENOMINATOR) + +// XAudio2 error codes +#define FACILITY_XAUDIO2 0x896 +#define XAUDIO2_E_INVALID_CALL 0x88960001 // An API call or one of its arguments was illegal +#define XAUDIO2_E_XMA_DECODER_ERROR 0x88960002 // The XMA hardware suffered an unrecoverable error +#define XAUDIO2_E_XAPO_CREATION_FAILED 0x88960003 // XAudio2 failed to initialize an XAPO effect +#define XAUDIO2_E_DEVICE_INVALIDATED 0x88960004 // An audio device became unusable (unplugged, etc) + + +/************************************************************************** + * + * Forward declarations for the XAudio2 interfaces. + * + **************************************************************************/ + +#ifdef __cplusplus + #define FWD_DECLARE(x) interface x +#else + #define FWD_DECLARE(x) typedef interface x x +#endif + +FWD_DECLARE(IXAudio2); +FWD_DECLARE(IXAudio2Voice); +FWD_DECLARE(IXAudio2SourceVoice); +FWD_DECLARE(IXAudio2SubmixVoice); +FWD_DECLARE(IXAudio2MasteringVoice); +FWD_DECLARE(IXAudio2EngineCallback); +FWD_DECLARE(IXAudio2VoiceCallback); + + +/************************************************************************** + * + * XAudio2 structures and enumerations. + * + **************************************************************************/ + +// Used in IXAudio2::Initialize +#ifdef _XBOX + typedef enum XAUDIO2_XBOX_HWTHREAD_SPECIFIER + { + XboxThread0 = 0x01, + XboxThread1 = 0x02, + XboxThread2 = 0x04, + XboxThread3 = 0x08, + XboxThread4 = 0x10, + XboxThread5 = 0x20, + XAUDIO2_ANY_PROCESSOR = XboxThread4, + XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR + } XAUDIO2_XBOX_HWTHREAD_SPECIFIER, XAUDIO2_PROCESSOR; +#else + typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER + { + Processor1 = 0x00000001, + Processor2 = 0x00000002, + Processor3 = 0x00000004, + Processor4 = 0x00000008, + Processor5 = 0x00000010, + Processor6 = 0x00000020, + Processor7 = 0x00000040, + Processor8 = 0x00000080, + Processor9 = 0x00000100, + Processor10 = 0x00000200, + Processor11 = 0x00000400, + Processor12 = 0x00000800, + Processor13 = 0x00001000, + Processor14 = 0x00002000, + Processor15 = 0x00004000, + Processor16 = 0x00008000, + Processor17 = 0x00010000, + Processor18 = 0x00020000, + Processor19 = 0x00040000, + Processor20 = 0x00080000, + Processor21 = 0x00100000, + Processor22 = 0x00200000, + Processor23 = 0x00400000, + Processor24 = 0x00800000, + Processor25 = 0x01000000, + Processor26 = 0x02000000, + Processor27 = 0x04000000, + Processor28 = 0x08000000, + Processor29 = 0x10000000, + Processor30 = 0x20000000, + Processor31 = 0x40000000, + Processor32 = 0x80000000, + XAUDIO2_ANY_PROCESSOR = 0xffffffff, + XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR + } XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER, XAUDIO2_PROCESSOR; +#endif + +// Used in XAUDIO2_DEVICE_DETAILS below to describe the types of applications +// that the user has specified each device as a default for. 0 means that the +// device isn't the default for any role. +typedef enum XAUDIO2_DEVICE_ROLE +{ + NotDefaultDevice = 0x0, + DefaultConsoleDevice = 0x1, + DefaultMultimediaDevice = 0x2, + DefaultCommunicationsDevice = 0x4, + DefaultGameDevice = 0x8, + GlobalDefaultDevice = 0xf, + InvalidDeviceRole = ~GlobalDefaultDevice +} XAUDIO2_DEVICE_ROLE; + +// Returned by IXAudio2::GetDeviceDetails +typedef struct XAUDIO2_DEVICE_DETAILS +{ + WCHAR DeviceID[256]; // String identifier for the audio device. + WCHAR DisplayName[256]; // Friendly name suitable for display to a human. + XAUDIO2_DEVICE_ROLE Role; // Roles that the device should be used for. + WAVEFORMATEXTENSIBLE OutputFormat; // The device's native PCM audio output format. +} XAUDIO2_DEVICE_DETAILS; + +// Returned by IXAudio2Voice::GetVoiceDetails +typedef struct XAUDIO2_VOICE_DETAILS +{ + UINT32 CreationFlags; // Flags the voice was created with. + UINT32 InputChannels; // Channels in the voice's input audio. + UINT32 InputSampleRate; // Sample rate of the voice's input audio. +} XAUDIO2_VOICE_DETAILS; + +// Used in XAUDIO2_VOICE_SENDS below +typedef struct XAUDIO2_SEND_DESCRIPTOR +{ + UINT32 Flags; // Either 0 or XAUDIO2_SEND_USEFILTER. + IXAudio2Voice* pOutputVoice; // This send's destination voice. +} XAUDIO2_SEND_DESCRIPTOR; + +// Used in the voice creation functions and in IXAudio2Voice::SetOutputVoices +typedef struct XAUDIO2_VOICE_SENDS +{ + UINT32 SendCount; // Number of sends from this voice. + XAUDIO2_SEND_DESCRIPTOR* pSends; // Array of SendCount send descriptors. +} XAUDIO2_VOICE_SENDS; + +// Used in XAUDIO2_EFFECT_CHAIN below +typedef struct XAUDIO2_EFFECT_DESCRIPTOR +{ + IUnknown* pEffect; // Pointer to the effect object's IUnknown interface. + BOOL InitialState; // TRUE if the effect should begin in the enabled state. + UINT32 OutputChannels; // How many output channels the effect should produce. +} XAUDIO2_EFFECT_DESCRIPTOR; + +// Used in the voice creation functions and in IXAudio2Voice::SetEffectChain +typedef struct XAUDIO2_EFFECT_CHAIN +{ + UINT32 EffectCount; // Number of effects in this voice's effect chain. + XAUDIO2_EFFECT_DESCRIPTOR* pEffectDescriptors; // Array of effect descriptors. +} XAUDIO2_EFFECT_CHAIN; + +// Used in XAUDIO2_FILTER_PARAMETERS below +typedef enum XAUDIO2_FILTER_TYPE +{ + LowPassFilter, // Attenuates frequencies above the cutoff frequency. + BandPassFilter, // Attenuates frequencies outside a given range. + HighPassFilter, // Attenuates frequencies below the cutoff frequency. + NotchFilter // Attenuates frequencies inside a given range. +} XAUDIO2_FILTER_TYPE; + +// Used in IXAudio2Voice::Set/GetFilterParameters and Set/GetOutputFilterParameters +typedef struct XAUDIO2_FILTER_PARAMETERS +{ + XAUDIO2_FILTER_TYPE Type; // Low-pass, band-pass or high-pass. + float Frequency; // Radian frequency (2 * sin(pi*CutoffFrequency/SampleRate)); + // must be >= 0 and <= XAUDIO2_MAX_FILTER_FREQUENCY + // (giving a maximum CutoffFrequency of SampleRate/6). + float OneOverQ; // Reciprocal of the filter's quality factor Q; + // must be > 0 and <= XAUDIO2_MAX_FILTER_ONEOVERQ. +} XAUDIO2_FILTER_PARAMETERS; + +// Used in IXAudio2SourceVoice::SubmitSourceBuffer +typedef struct XAUDIO2_BUFFER +{ + UINT32 Flags; // Either 0 or XAUDIO2_END_OF_STREAM. + UINT32 AudioBytes; // Size of the audio data buffer in bytes. + const BYTE* pAudioData; // Pointer to the audio data buffer. + UINT32 PlayBegin; // First sample in this buffer to be played. + UINT32 PlayLength; // Length of the region to be played in samples, + // or 0 to play the whole buffer. + UINT32 LoopBegin; // First sample of the region to be looped. + UINT32 LoopLength; // Length of the desired loop region in samples, + // or 0 to loop the entire buffer. + UINT32 LoopCount; // Number of times to repeat the loop region, + // or XAUDIO2_LOOP_INFINITE to loop forever. + void* pContext; // Context value to be passed back in callbacks. +} XAUDIO2_BUFFER; + +// Used in IXAudio2SourceVoice::SubmitSourceBuffer when submitting XWMA data. +// NOTE: If an XWMA sound is submitted in more than one buffer, each buffer's +// pDecodedPacketCumulativeBytes[PacketCount-1] value must be subtracted from +// all the entries in the next buffer's pDecodedPacketCumulativeBytes array. +// And whether a sound is submitted in more than one buffer or not, the final +// buffer of the sound should use the XAUDIO2_END_OF_STREAM flag, or else the +// client must call IXAudio2SourceVoice::Discontinuity after submitting it. +typedef struct XAUDIO2_BUFFER_WMA +{ + const UINT32* pDecodedPacketCumulativeBytes; // Decoded packet's cumulative size array. + // Each element is the number of bytes accumulated + // when the corresponding XWMA packet is decoded in + // order. The array must have PacketCount elements. + UINT32 PacketCount; // Number of XWMA packets submitted. Must be >= 1 and + // divide evenly into XAUDIO2_BUFFER.AudioBytes. +} XAUDIO2_BUFFER_WMA; + +// Returned by IXAudio2SourceVoice::GetState +typedef struct XAUDIO2_VOICE_STATE +{ + void* pCurrentBufferContext; // The pContext value provided in the XAUDIO2_BUFFER + // that is currently being processed, or NULL if + // there are no buffers in the queue. + UINT32 BuffersQueued; // Number of buffers currently queued on the voice + // (including the one that is being processed). + UINT64 SamplesPlayed; // Total number of samples produced by the voice since + // it began processing the current audio stream. +} XAUDIO2_VOICE_STATE; + +// Returned by IXAudio2::GetPerformanceData +typedef struct XAUDIO2_PERFORMANCE_DATA +{ + // CPU usage information + UINT64 AudioCyclesSinceLastQuery; // CPU cycles spent on audio processing since the + // last call to StartEngine or GetPerformanceData. + UINT64 TotalCyclesSinceLastQuery; // Total CPU cycles elapsed since the last call + // (only counts the CPU XAudio2 is running on). + UINT32 MinimumCyclesPerQuantum; // Fewest CPU cycles spent processing any one + // audio quantum since the last call. + UINT32 MaximumCyclesPerQuantum; // Most CPU cycles spent processing any one + // audio quantum since the last call. + + // Memory usage information + UINT32 MemoryUsageInBytes; // Total heap space currently in use. + + // Audio latency and glitching information + UINT32 CurrentLatencyInSamples; // Minimum delay from when a sample is read from a + // source buffer to when it reaches the speakers. + UINT32 GlitchesSinceEngineStarted; // Audio dropouts since the engine was started. + + // Data about XAudio2's current workload + UINT32 ActiveSourceVoiceCount; // Source voices currently playing. + UINT32 TotalSourceVoiceCount; // Source voices currently existing. + UINT32 ActiveSubmixVoiceCount; // Submix voices currently playing/existing. + + UINT32 ActiveResamplerCount; // Resample xAPOs currently active. + UINT32 ActiveMatrixMixCount; // MatrixMix xAPOs currently active. + + // Usage of the hardware XMA decoder (Xbox 360 only) + UINT32 ActiveXmaSourceVoices; // Number of source voices decoding XMA data. + UINT32 ActiveXmaStreams; // A voice can use more than one XMA stream. +} XAUDIO2_PERFORMANCE_DATA; + +// Used in IXAudio2::SetDebugConfiguration +typedef struct XAUDIO2_DEBUG_CONFIGURATION +{ + UINT32 TraceMask; // Bitmap of enabled debug message types. + UINT32 BreakMask; // Message types that will break into the debugger. + BOOL LogThreadID; // Whether to log the thread ID with each message. + BOOL LogFileline; // Whether to log the source file and line number. + BOOL LogFunctionName; // Whether to log the function name. + BOOL LogTiming; // Whether to log message timestamps. +} XAUDIO2_DEBUG_CONFIGURATION; + +// Values for the TraceMask and BreakMask bitmaps. Only ERRORS and WARNINGS +// are valid in BreakMask. WARNINGS implies ERRORS, DETAIL implies INFO, and +// FUNC_CALLS implies API_CALLS. By default, TraceMask is ERRORS and WARNINGS +// and all the other settings are zero. +#define XAUDIO2_LOG_ERRORS 0x0001 // For handled errors with serious effects. +#define XAUDIO2_LOG_WARNINGS 0x0002 // For handled errors that may be recoverable. +#define XAUDIO2_LOG_INFO 0x0004 // Informational chit-chat (e.g. state changes). +#define XAUDIO2_LOG_DETAIL 0x0008 // More detailed chit-chat. +#define XAUDIO2_LOG_API_CALLS 0x0010 // Public API function entries and exits. +#define XAUDIO2_LOG_FUNC_CALLS 0x0020 // Internal function entries and exits. +#define XAUDIO2_LOG_TIMING 0x0040 // Delays detected and other timing data. +#define XAUDIO2_LOG_LOCKS 0x0080 // Usage of critical sections and mutexes. +#define XAUDIO2_LOG_MEMORY 0x0100 // Memory heap usage information. +#define XAUDIO2_LOG_STREAMING 0x1000 // Audio streaming information. + + +/************************************************************************** + * + * IXAudio2: Top-level XAudio2 COM interface. + * + **************************************************************************/ + +// Use default arguments if compiling as C++ +#ifdef __cplusplus + #define X2DEFAULT(x) =x +#else + #define X2DEFAULT(x) +#endif + +#undef INTERFACE +#define INTERFACE IXAudio2 +DECLARE_INTERFACE_(IXAudio2, IUnknown) +{ + // NAME: IXAudio2::QueryInterface + // DESCRIPTION: Queries for a given COM interface on the XAudio2 object. + // Only IID_IUnknown and IID_IXAudio2 are supported. + // + // ARGUMENTS: + // riid - IID of the interface to be obtained. + // ppvInterface - Returns a pointer to the requested interface. + // + STDMETHOD(QueryInterface) (THIS_ REFIID riid, __deref_out void** ppvInterface) PURE; + + // NAME: IXAudio2::AddRef + // DESCRIPTION: Adds a reference to the XAudio2 object. + // + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + + // NAME: IXAudio2::Release + // DESCRIPTION: Releases a reference to the XAudio2 object. + // + STDMETHOD_(ULONG, Release) (THIS) PURE; + + // NAME: IXAudio2::GetDeviceCount + // DESCRIPTION: Returns the number of audio output devices available. + // + // ARGUMENTS: + // pCount - Returns the device count. + // + STDMETHOD(GetDeviceCount) (THIS_ __out UINT32* pCount) PURE; + + // NAME: IXAudio2::GetDeviceDetails + // DESCRIPTION: Returns information about the device with the given index. + // + // ARGUMENTS: + // Index - Index of the device to be queried. + // pDeviceDetails - Returns the device details. + // + STDMETHOD(GetDeviceDetails) (THIS_ UINT32 Index, __out XAUDIO2_DEVICE_DETAILS* pDeviceDetails) PURE; + + // NAME: IXAudio2::Initialize + // DESCRIPTION: Sets global XAudio2 parameters and prepares it for use. + // + // ARGUMENTS: + // Flags - Flags specifying the XAudio2 object's behavior. Currently unused. + // XAudio2Processor - An XAUDIO2_PROCESSOR enumeration value that specifies + // the hardware thread (Xbox) or processor (Windows) that XAudio2 will use. + // The enumeration values are platform-specific; platform-independent code + // can use XAUDIO2_DEFAULT_PROCESSOR to use the default on each platform. + // + STDMETHOD(Initialize) (THIS_ UINT32 Flags X2DEFAULT(0), + XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)) PURE; + + // NAME: IXAudio2::RegisterForCallbacks + // DESCRIPTION: Adds a new client to receive XAudio2's engine callbacks. + // + // ARGUMENTS: + // pCallback - Callback interface to be called during each processing pass. + // + STDMETHOD(RegisterForCallbacks) (__in IXAudio2EngineCallback* pCallback) PURE; + + // NAME: IXAudio2::UnregisterForCallbacks + // DESCRIPTION: Removes an existing receiver of XAudio2 engine callbacks. + // + // ARGUMENTS: + // pCallback - Previously registered callback interface to be removed. + // + STDMETHOD_(void, UnregisterForCallbacks) (__in IXAudio2EngineCallback* pCallback) PURE; + + // NAME: IXAudio2::CreateSourceVoice + // DESCRIPTION: Creates and configures a source voice. + // + // ARGUMENTS: + // ppSourceVoice - Returns the new object's IXAudio2SourceVoice interface. + // pSourceFormat - Format of the audio that will be fed to the voice. + // Flags - XAUDIO2_VOICE flags specifying the source voice's behavior. + // MaxFrequencyRatio - Maximum SetFrequencyRatio argument to be allowed. + // pCallback - Optional pointer to a client-provided callback interface. + // pSendList - Optional list of voices this voice should send audio to. + // pEffectChain - Optional list of effects to apply to the audio data. + // + STDMETHOD(CreateSourceVoice) (THIS_ __deref_out IXAudio2SourceVoice** ppSourceVoice, + __in const WAVEFORMATEX* pSourceFormat, + UINT32 Flags X2DEFAULT(0), + float MaxFrequencyRatio X2DEFAULT(XAUDIO2_DEFAULT_FREQ_RATIO), + __in_opt IXAudio2VoiceCallback* pCallback X2DEFAULT(NULL), + __in_opt const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL), + __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; + + // NAME: IXAudio2::CreateSubmixVoice + // DESCRIPTION: Creates and configures a submix voice. + // + // ARGUMENTS: + // ppSubmixVoice - Returns the new object's IXAudio2SubmixVoice interface. + // InputChannels - Number of channels in this voice's input audio data. + // InputSampleRate - Sample rate of this voice's input audio data. + // Flags - XAUDIO2_VOICE flags specifying the submix voice's behavior. + // ProcessingStage - Arbitrary number that determines the processing order. + // pSendList - Optional list of voices this voice should send audio to. + // pEffectChain - Optional list of effects to apply to the audio data. + // + STDMETHOD(CreateSubmixVoice) (THIS_ __deref_out IXAudio2SubmixVoice** ppSubmixVoice, + UINT32 InputChannels, UINT32 InputSampleRate, + UINT32 Flags X2DEFAULT(0), UINT32 ProcessingStage X2DEFAULT(0), + __in_opt const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL), + __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; + + + // NAME: IXAudio2::CreateMasteringVoice + // DESCRIPTION: Creates and configures a mastering voice. + // + // ARGUMENTS: + // ppMasteringVoice - Returns the new object's IXAudio2MasteringVoice interface. + // InputChannels - Number of channels in this voice's input audio data. + // InputSampleRate - Sample rate of this voice's input audio data. + // Flags - XAUDIO2_VOICE flags specifying the mastering voice's behavior. + // DeviceIndex - Identifier of the device to receive the output audio. + // pEffectChain - Optional list of effects to apply to the audio data. + // + STDMETHOD(CreateMasteringVoice) (THIS_ __deref_out IXAudio2MasteringVoice** ppMasteringVoice, + UINT32 InputChannels X2DEFAULT(XAUDIO2_DEFAULT_CHANNELS), + UINT32 InputSampleRate X2DEFAULT(XAUDIO2_DEFAULT_SAMPLERATE), + UINT32 Flags X2DEFAULT(0), UINT32 DeviceIndex X2DEFAULT(0), + __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; + + // NAME: IXAudio2::StartEngine + // DESCRIPTION: Creates and starts the audio processing thread. + // + STDMETHOD(StartEngine) (THIS) PURE; + + // NAME: IXAudio2::StopEngine + // DESCRIPTION: Stops and destroys the audio processing thread. + // + STDMETHOD_(void, StopEngine) (THIS) PURE; + + // NAME: IXAudio2::CommitChanges + // DESCRIPTION: Atomically applies a set of operations previously tagged + // with a given identifier. + // + // ARGUMENTS: + // OperationSet - Identifier of the set of operations to be applied. + // + STDMETHOD(CommitChanges) (THIS_ UINT32 OperationSet) PURE; + + // NAME: IXAudio2::GetPerformanceData + // DESCRIPTION: Returns current resource usage details: memory, CPU, etc. + // + // ARGUMENTS: + // pPerfData - Returns the performance data structure. + // + STDMETHOD_(void, GetPerformanceData) (THIS_ __out XAUDIO2_PERFORMANCE_DATA* pPerfData) PURE; + + // NAME: IXAudio2::SetDebugConfiguration + // DESCRIPTION: Configures XAudio2's debug output (in debug builds only). + // + // ARGUMENTS: + // pDebugConfiguration - Structure describing the debug output behavior. + // pReserved - Optional parameter; must be NULL. + // + STDMETHOD_(void, SetDebugConfiguration) (THIS_ __in_opt const XAUDIO2_DEBUG_CONFIGURATION* pDebugConfiguration, + __in_opt __reserved void* pReserved X2DEFAULT(NULL)) PURE; +}; + + +/************************************************************************** + * + * IXAudio2Voice: Base voice management interface. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2Voice +DECLARE_INTERFACE(IXAudio2Voice) +{ + // These methods are declared in a macro so that the same declarations + // can be used in the derived voice types (IXAudio2SourceVoice, etc). + + #define Declare_IXAudio2Voice_Methods() \ + \ + /* NAME: IXAudio2Voice::GetVoiceDetails + // DESCRIPTION: Returns the basic characteristics of this voice. + // + // ARGUMENTS: + // pVoiceDetails - Returns the voice's details. + */\ + STDMETHOD_(void, GetVoiceDetails) (THIS_ __out XAUDIO2_VOICE_DETAILS* pVoiceDetails) PURE; \ + \ + /* NAME: IXAudio2Voice::SetOutputVoices + // DESCRIPTION: Replaces the set of submix/mastering voices that receive + // this voice's output. + // + // ARGUMENTS: + // pSendList - Optional list of voices this voice should send audio to. + */\ + STDMETHOD(SetOutputVoices) (THIS_ __in_opt const XAUDIO2_VOICE_SENDS* pSendList) PURE; \ + \ + /* NAME: IXAudio2Voice::SetEffectChain + // DESCRIPTION: Replaces this voice's current effect chain with a new one. + // + // ARGUMENTS: + // pEffectChain - Structure describing the new effect chain to be used. + */\ + STDMETHOD(SetEffectChain) (THIS_ __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain) PURE; \ + \ + /* NAME: IXAudio2Voice::EnableEffect + // DESCRIPTION: Enables an effect in this voice's effect chain. + // + // ARGUMENTS: + // EffectIndex - Index of an effect within this voice's effect chain. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(EnableEffect) (THIS_ UINT32 EffectIndex, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::DisableEffect + // DESCRIPTION: Disables an effect in this voice's effect chain. + // + // ARGUMENTS: + // EffectIndex - Index of an effect within this voice's effect chain. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(DisableEffect) (THIS_ UINT32 EffectIndex, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetEffectState + // DESCRIPTION: Returns the running state of an effect. + // + // ARGUMENTS: + // EffectIndex - Index of an effect within this voice's effect chain. + // pEnabled - Returns the enabled/disabled state of the given effect. + */\ + STDMETHOD_(void, GetEffectState) (THIS_ UINT32 EffectIndex, __out BOOL* pEnabled) PURE; \ + \ + /* NAME: IXAudio2Voice::SetEffectParameters + // DESCRIPTION: Sets effect-specific parameters. + // + // REMARKS: Unlike IXAPOParameters::SetParameters, this method may + // be called from any thread. XAudio2 implements + // appropriate synchronization to copy the parameters to the + // realtime audio processing thread. + // + // ARGUMENTS: + // EffectIndex - Index of an effect within this voice's effect chain. + // pParameters - Pointer to an effect-specific parameters block. + // ParametersByteSize - Size of the pParameters array in bytes. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetEffectParameters) (THIS_ UINT32 EffectIndex, \ + __in_bcount(ParametersByteSize) const void* pParameters, \ + UINT32 ParametersByteSize, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetEffectParameters + // DESCRIPTION: Obtains the current effect-specific parameters. + // + // ARGUMENTS: + // EffectIndex - Index of an effect within this voice's effect chain. + // pParameters - Returns the current values of the effect-specific parameters. + // ParametersByteSize - Size of the pParameters array in bytes. + */\ + STDMETHOD(GetEffectParameters) (THIS_ UINT32 EffectIndex, \ + __out_bcount(ParametersByteSize) void* pParameters, \ + UINT32 ParametersByteSize) PURE; \ + \ + /* NAME: IXAudio2Voice::SetFilterParameters + // DESCRIPTION: Sets this voice's filter parameters. + // + // ARGUMENTS: + // pParameters - Pointer to the filter's parameter structure. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetFilterParameters) (THIS_ __in const XAUDIO2_FILTER_PARAMETERS* pParameters, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetFilterParameters + // DESCRIPTION: Returns this voice's current filter parameters. + // + // ARGUMENTS: + // pParameters - Returns the filter parameters. + */\ + STDMETHOD_(void, GetFilterParameters) (THIS_ __out XAUDIO2_FILTER_PARAMETERS* pParameters) PURE; \ + \ + /* NAME: IXAudio2Voice::SetOutputFilterParameters + // DESCRIPTION: Sets the filter parameters on one of this voice's sends. + // + // ARGUMENTS: + // pDestinationVoice - Destination voice of the send whose filter parameters will be set. + // pParameters - Pointer to the filter's parameter structure. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetOutputFilterParameters) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \ + __in const XAUDIO2_FILTER_PARAMETERS* pParameters, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetOutputFilterParameters + // DESCRIPTION: Returns the filter parameters from one of this voice's sends. + // + // ARGUMENTS: + // pDestinationVoice - Destination voice of the send whose filter parameters will be read. + // pParameters - Returns the filter parameters. + */\ + STDMETHOD_(void, GetOutputFilterParameters) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \ + __out XAUDIO2_FILTER_PARAMETERS* pParameters) PURE; \ + \ + /* NAME: IXAudio2Voice::SetVolume + // DESCRIPTION: Sets this voice's overall volume level. + // + // ARGUMENTS: + // Volume - New overall volume level to be used, as an amplitude factor. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetVolume) (THIS_ float Volume, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetVolume + // DESCRIPTION: Obtains this voice's current overall volume level. + // + // ARGUMENTS: + // pVolume: Returns the voice's current overall volume level. + */\ + STDMETHOD_(void, GetVolume) (THIS_ __out float* pVolume) PURE; \ + \ + /* NAME: IXAudio2Voice::SetChannelVolumes + // DESCRIPTION: Sets this voice's per-channel volume levels. + // + // ARGUMENTS: + // Channels - Used to confirm the voice's channel count. + // pVolumes - Array of per-channel volume levels to be used. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetChannelVolumes) (THIS_ UINT32 Channels, __in_ecount(Channels) const float* pVolumes, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetChannelVolumes + // DESCRIPTION: Returns this voice's current per-channel volume levels. + // + // ARGUMENTS: + // Channels - Used to confirm the voice's channel count. + // pVolumes - Returns an array of the current per-channel volume levels. + */\ + STDMETHOD_(void, GetChannelVolumes) (THIS_ UINT32 Channels, __out_ecount(Channels) float* pVolumes) PURE; \ + \ + /* NAME: IXAudio2Voice::SetOutputMatrix + // DESCRIPTION: Sets the volume levels used to mix from each channel of this + // voice's output audio to each channel of a given destination + // voice's input audio. + // + // ARGUMENTS: + // pDestinationVoice - The destination voice whose mix matrix to change. + // SourceChannels - Used to confirm this voice's output channel count + // (the number of channels produced by the last effect in the chain). + // DestinationChannels - Confirms the destination voice's input channels. + // pLevelMatrix - Array of [SourceChannels * DestinationChannels] send + // levels. The level used to send from source channel S to destination + // channel D should be in pLevelMatrix[S + SourceChannels * D]. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetOutputMatrix) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \ + UINT32 SourceChannels, UINT32 DestinationChannels, \ + __in_ecount(SourceChannels * DestinationChannels) const float* pLevelMatrix, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetOutputMatrix + // DESCRIPTION: Obtains the volume levels used to send each channel of this + // voice's output audio to each channel of a given destination + // voice's input audio. + // + // ARGUMENTS: + // pDestinationVoice - The destination voice whose mix matrix to obtain. + // SourceChannels - Used to confirm this voice's output channel count + // (the number of channels produced by the last effect in the chain). + // DestinationChannels - Confirms the destination voice's input channels. + // pLevelMatrix - Array of send levels, as above. + */\ + STDMETHOD_(void, GetOutputMatrix) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \ + UINT32 SourceChannels, UINT32 DestinationChannels, \ + __out_ecount(SourceChannels * DestinationChannels) float* pLevelMatrix) PURE; \ + \ + /* NAME: IXAudio2Voice::DestroyVoice + // DESCRIPTION: Destroys this voice, stopping it if necessary and removing + // it from the XAudio2 graph. + */\ + STDMETHOD_(void, DestroyVoice) (THIS) PURE + + Declare_IXAudio2Voice_Methods(); +}; + + +/************************************************************************** + * + * IXAudio2SourceVoice: Source voice management interface. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2SourceVoice +DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice) +{ + // Methods from IXAudio2Voice base interface + Declare_IXAudio2Voice_Methods(); + + // NAME: IXAudio2SourceVoice::Start + // DESCRIPTION: Makes this voice start consuming and processing audio. + // + // ARGUMENTS: + // Flags - Flags controlling how the voice should be started. + // OperationSet - Used to identify this call as part of a deferred batch. + // + STDMETHOD(Start) (THIS_ UINT32 Flags X2DEFAULT(0), UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + + // NAME: IXAudio2SourceVoice::Stop + // DESCRIPTION: Makes this voice stop consuming audio. + // + // ARGUMENTS: + // Flags - Flags controlling how the voice should be stopped. + // OperationSet - Used to identify this call as part of a deferred batch. + // + STDMETHOD(Stop) (THIS_ UINT32 Flags X2DEFAULT(0), UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + + // NAME: IXAudio2SourceVoice::SubmitSourceBuffer + // DESCRIPTION: Adds a new audio buffer to this voice's input queue. + // + // ARGUMENTS: + // pBuffer - Pointer to the buffer structure to be queued. + // pBufferWMA - Additional structure used only when submitting XWMA data. + // + STDMETHOD(SubmitSourceBuffer) (THIS_ __in const XAUDIO2_BUFFER* pBuffer, __in_opt const XAUDIO2_BUFFER_WMA* pBufferWMA X2DEFAULT(NULL)) PURE; + + // NAME: IXAudio2SourceVoice::FlushSourceBuffers + // DESCRIPTION: Removes all pending audio buffers from this voice's queue. + // + STDMETHOD(FlushSourceBuffers) (THIS) PURE; + + // NAME: IXAudio2SourceVoice::Discontinuity + // DESCRIPTION: Notifies the voice of an intentional break in the stream of + // audio buffers (e.g. the end of a sound), to prevent XAudio2 + // from interpreting an empty buffer queue as a glitch. + // + STDMETHOD(Discontinuity) (THIS) PURE; + + // NAME: IXAudio2SourceVoice::ExitLoop + // DESCRIPTION: Breaks out of the current loop when its end is reached. + // + // ARGUMENTS: + // OperationSet - Used to identify this call as part of a deferred batch. + // + STDMETHOD(ExitLoop) (THIS_ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + + // NAME: IXAudio2SourceVoice::GetState + // DESCRIPTION: Returns the number of buffers currently queued on this voice, + // the pContext value associated with the currently processing + // buffer (if any), and other voice state information. + // + // ARGUMENTS: + // pVoiceState - Returns the state information. + // + STDMETHOD_(void, GetState) (THIS_ __out XAUDIO2_VOICE_STATE* pVoiceState) PURE; + + // NAME: IXAudio2SourceVoice::SetFrequencyRatio + // DESCRIPTION: Sets this voice's frequency adjustment, i.e. its pitch. + // + // ARGUMENTS: + // Ratio - Frequency change, expressed as source frequency / target frequency. + // OperationSet - Used to identify this call as part of a deferred batch. + // + STDMETHOD(SetFrequencyRatio) (THIS_ float Ratio, + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + + // NAME: IXAudio2SourceVoice::GetFrequencyRatio + // DESCRIPTION: Returns this voice's current frequency adjustment ratio. + // + // ARGUMENTS: + // pRatio - Returns the frequency adjustment. + // + STDMETHOD_(void, GetFrequencyRatio) (THIS_ __out float* pRatio) PURE; + + // NAME: IXAudio2SourceVoice::SetSourceSampleRate + // DESCRIPTION: Reconfigures this voice to treat its source data as being + // at a different sample rate than the original one specified + // in CreateSourceVoice's pSourceFormat argument. + // + // ARGUMENTS: + // UINT32 - The intended sample rate of further submitted source data. + // + STDMETHOD(SetSourceSampleRate) (THIS_ UINT32 NewSourceSampleRate) PURE; +}; + + +/************************************************************************** + * + * IXAudio2SubmixVoice: Submixing voice management interface. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2SubmixVoice +DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice) +{ + // Methods from IXAudio2Voice base interface + Declare_IXAudio2Voice_Methods(); + + // There are currently no methods specific to submix voices. +}; + + +/************************************************************************** + * + * IXAudio2MasteringVoice: Mastering voice management interface. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2MasteringVoice +DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice) +{ + // Methods from IXAudio2Voice base interface + Declare_IXAudio2Voice_Methods(); + + // There are currently no methods specific to mastering voices. +}; + + +/************************************************************************** + * + * IXAudio2EngineCallback: Client notification interface for engine events. + * + * REMARKS: Contains methods to notify the client when certain events happen + * in the XAudio2 engine. This interface should be implemented by + * the client. XAudio2 will call these methods via the interface + * pointer provided by the client when it calls XAudio2Create or + * IXAudio2::Initialize. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2EngineCallback +DECLARE_INTERFACE(IXAudio2EngineCallback) +{ + // Called by XAudio2 just before an audio processing pass begins. + STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE; + + // Called just after an audio processing pass ends. + STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE; + + // Called in the event of a critical system error which requires XAudio2 + // to be closed down and restarted. The error code is given in Error. + STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE; +}; + + +/************************************************************************** + * + * IXAudio2VoiceCallback: Client notification interface for voice events. + * + * REMARKS: Contains methods to notify the client when certain events happen + * in an XAudio2 voice. This interface should be implemented by the + * client. XAudio2 will call these methods via an interface pointer + * provided by the client in the IXAudio2::CreateSourceVoice call. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2VoiceCallback +DECLARE_INTERFACE(IXAudio2VoiceCallback) +{ + // Called just before this voice's processing pass begins. + STDMETHOD_(void, OnVoiceProcessingPassStart) (THIS_ UINT32 BytesRequired) PURE; + + // Called just after this voice's processing pass ends. + STDMETHOD_(void, OnVoiceProcessingPassEnd) (THIS) PURE; + + // Called when this voice has just finished playing a buffer stream + // (as marked with the XAUDIO2_END_OF_STREAM flag on the last buffer). + STDMETHOD_(void, OnStreamEnd) (THIS) PURE; + + // Called when this voice is about to start processing a new buffer. + STDMETHOD_(void, OnBufferStart) (THIS_ void* pBufferContext) PURE; + + // Called when this voice has just finished processing a buffer. + // The buffer can now be reused or destroyed. + STDMETHOD_(void, OnBufferEnd) (THIS_ void* pBufferContext) PURE; + + // Called when this voice has just reached the end position of a loop. + STDMETHOD_(void, OnLoopEnd) (THIS_ void* pBufferContext) PURE; + + // Called in the event of a critical error during voice processing, + // such as a failing xAPO or an error from the hardware XMA decoder. + // The voice may have to be destroyed and re-created to recover from + // the error. The callback arguments report which buffer was being + // processed when the error occurred, and its HRESULT code. + STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) PURE; +}; + + +/************************************************************************** + * + * Macros to make it easier to use the XAudio2 COM interfaces in C code. + * + **************************************************************************/ + +#ifndef __cplusplus + +// IXAudio2 +#define IXAudio2_QueryInterface(This,riid,ppvInterface) ((This)->lpVtbl->QueryInterface(This,riid,ppvInterface)) +#define IXAudio2_AddRef(This) ((This)->lpVtbl->AddRef(This)) +#define IXAudio2_Release(This) ((This)->lpVtbl->Release(This)) +#define IXAudio2_GetDeviceCount(This,puCount) ((This)->lpVtbl->GetDeviceCount(This,puCount)) +#define IXAudio2_GetDeviceDetails(This,Index,pDeviceDetails) ((This)->lpVtbl->GetDeviceDetails(This,Index,pDeviceDetails)) +#define IXAudio2_Initialize(This,Flags,XAudio2Processor) ((This)->lpVtbl->Initialize(This,Flags,XAudio2Processor)) +#define IXAudio2_CreateSourceVoice(This,ppSourceVoice,pSourceFormat,Flags,MaxFrequencyRatio,pCallback,pSendList,pEffectChain) ((This)->lpVtbl->CreateSourceVoice(This,ppSourceVoice,pSourceFormat,Flags,MaxFrequencyRatio,pCallback,pSendList,pEffectChain)) +#define IXAudio2_CreateSubmixVoice(This,ppSubmixVoice,InputChannels,InputSampleRate,Flags,ProcessingStage,pSendList,pEffectChain) ((This)->lpVtbl->CreateSubmixVoice(This,ppSubmixVoice,InputChannels,InputSampleRate,Flags,ProcessingStage,pSendList,pEffectChain)) +#define IXAudio2_CreateMasteringVoice(This,ppMasteringVoice,InputChannels,InputSampleRate,Flags,DeviceIndex,pEffectChain) ((This)->lpVtbl->CreateMasteringVoice(This,ppMasteringVoice,InputChannels,InputSampleRate,Flags,DeviceIndex,pEffectChain)) +#define IXAudio2_StartEngine(This) ((This)->lpVtbl->StartEngine(This)) +#define IXAudio2_StopEngine(This) ((This)->lpVtbl->StopEngine(This)) +#define IXAudio2_CommitChanges(This,OperationSet) ((This)->lpVtbl->CommitChanges(This,OperationSet)) +#define IXAudio2_GetPerformanceData(This,pPerfData) ((This)->lpVtbl->GetPerformanceData(This,pPerfData)) +#define IXAudio2_SetDebugConfiguration(This,pDebugConfiguration,pReserved) ((This)->lpVtbl->SetDebugConfiguration(This,pDebugConfiguration,pReserved)) + +// IXAudio2Voice +#define IXAudio2Voice_GetVoiceDetails(This,pVoiceDetails) ((This)->lpVtbl->GetVoiceDetails(This,pVoiceDetails)) +#define IXAudio2Voice_SetOutputVoices(This,pSendList) ((This)->lpVtbl->SetOutputVoices(This,pSendList)) +#define IXAudio2Voice_SetEffectChain(This,pEffectChain) ((This)->lpVtbl->SetEffectChain(This,pEffectChain)) +#define IXAudio2Voice_EnableEffect(This,EffectIndex,OperationSet) ((This)->lpVtbl->EnableEffect(This,EffectIndex,OperationSet)) +#define IXAudio2Voice_DisableEffect(This,EffectIndex,OperationSet) ((This)->lpVtbl->DisableEffect(This,EffectIndex,OperationSet)) +#define IXAudio2Voice_GetEffectState(This,EffectIndex,pEnabled) ((This)->lpVtbl->GetEffectState(This,EffectIndex,pEnabled)) +#define IXAudio2Voice_SetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize, OperationSet) ((This)->lpVtbl->SetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize,OperationSet)) +#define IXAudio2Voice_GetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize) ((This)->lpVtbl->GetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize)) +#define IXAudio2Voice_SetFilterParameters(This,pParameters,OperationSet) ((This)->lpVtbl->SetFilterParameters(This,pParameters,OperationSet)) +#define IXAudio2Voice_GetFilterParameters(This,pParameters) ((This)->lpVtbl->GetFilterParameters(This,pParameters)) +#define IXAudio2Voice_SetOutputFilterParameters(This,pDestinationVoice,pParameters,OperationSet) ((This)->lpVtbl->SetOutputFilterParameters(This,pDestinationVoice,pParameters,OperationSet)) +#define IXAudio2Voice_GetOutputFilterParameters(This,pDestinationVoice,pParameters) ((This)->lpVtbl->GetOutputFilterParameters(This,pDestinationVoice,pParameters)) +#define IXAudio2Voice_SetVolume(This,Volume,OperationSet) ((This)->lpVtbl->SetVolume(This,Volume,OperationSet)) +#define IXAudio2Voice_GetVolume(This,pVolume) ((This)->lpVtbl->GetVolume(This,pVolume)) +#define IXAudio2Voice_SetChannelVolumes(This,Channels,pVolumes,OperationSet) ((This)->lpVtbl->SetChannelVolumes(This,Channels,pVolumes,OperationSet)) +#define IXAudio2Voice_GetChannelVolumes(This,Channels,pVolumes) ((This)->lpVtbl->GetChannelVolumes(This,Channels,pVolumes)) +#define IXAudio2Voice_SetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix,OperationSet) ((This)->lpVtbl->SetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix,OperationSet)) +#define IXAudio2Voice_GetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix) ((This)->lpVtbl->GetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix)) +#define IXAudio2Voice_DestroyVoice(This) ((This)->lpVtbl->DestroyVoice(This)) + +// IXAudio2SourceVoice +#define IXAudio2SourceVoice_GetVoiceDetails IXAudio2Voice_GetVoiceDetails +#define IXAudio2SourceVoice_SetOutputVoices IXAudio2Voice_SetOutputVoices +#define IXAudio2SourceVoice_SetEffectChain IXAudio2Voice_SetEffectChain +#define IXAudio2SourceVoice_EnableEffect IXAudio2Voice_EnableEffect +#define IXAudio2SourceVoice_DisableEffect IXAudio2Voice_DisableEffect +#define IXAudio2SourceVoice_GetEffectState IXAudio2Voice_GetEffectState +#define IXAudio2SourceVoice_SetEffectParameters IXAudio2Voice_SetEffectParameters +#define IXAudio2SourceVoice_GetEffectParameters IXAudio2Voice_GetEffectParameters +#define IXAudio2SourceVoice_SetFilterParameters IXAudio2Voice_SetFilterParameters +#define IXAudio2SourceVoice_GetFilterParameters IXAudio2Voice_GetFilterParameters +#define IXAudio2SourceVoice_SetOutputFilterParameters IXAudio2Voice_SetOutputFilterParameters +#define IXAudio2SourceVoice_GetOutputFilterParameters IXAudio2Voice_GetOutputFilterParameters +#define IXAudio2SourceVoice_SetVolume IXAudio2Voice_SetVolume +#define IXAudio2SourceVoice_GetVolume IXAudio2Voice_GetVolume +#define IXAudio2SourceVoice_SetChannelVolumes IXAudio2Voice_SetChannelVolumes +#define IXAudio2SourceVoice_GetChannelVolumes IXAudio2Voice_GetChannelVolumes +#define IXAudio2SourceVoice_SetOutputMatrix IXAudio2Voice_SetOutputMatrix +#define IXAudio2SourceVoice_GetOutputMatrix IXAudio2Voice_GetOutputMatrix +#define IXAudio2SourceVoice_DestroyVoice IXAudio2Voice_DestroyVoice +#define IXAudio2SourceVoice_Start(This,Flags,OperationSet) ((This)->lpVtbl->Start(This,Flags,OperationSet)) +#define IXAudio2SourceVoice_Stop(This,Flags,OperationSet) ((This)->lpVtbl->Stop(This,Flags,OperationSet)) +#define IXAudio2SourceVoice_SubmitSourceBuffer(This,pBuffer,pBufferWMA) ((This)->lpVtbl->SubmitSourceBuffer(This,pBuffer,pBufferWMA)) +#define IXAudio2SourceVoice_FlushSourceBuffers(This) ((This)->lpVtbl->FlushSourceBuffers(This)) +#define IXAudio2SourceVoice_Discontinuity(This) ((This)->lpVtbl->Discontinuity(This)) +#define IXAudio2SourceVoice_ExitLoop(This,OperationSet) ((This)->lpVtbl->ExitLoop(This,OperationSet)) +#define IXAudio2SourceVoice_GetState(This,pVoiceState) ((This)->lpVtbl->GetState(This,pVoiceState)) +#define IXAudio2SourceVoice_SetFrequencyRatio(This,Ratio,OperationSet) ((This)->lpVtbl->SetFrequencyRatio(This,Ratio,OperationSet)) +#define IXAudio2SourceVoice_GetFrequencyRatio(This,pRatio) ((This)->lpVtbl->GetFrequencyRatio(This,pRatio)) +#define IXAudio2SourceVoice_SetSourceSampleRate(This,NewSourceSampleRate) ((This)->lpVtbl->SetSourceSampleRate(This,NewSourceSampleRate)) + +// IXAudio2SubmixVoice +#define IXAudio2SubmixVoice_GetVoiceDetails IXAudio2Voice_GetVoiceDetails +#define IXAudio2SubmixVoice_SetOutputVoices IXAudio2Voice_SetOutputVoices +#define IXAudio2SubmixVoice_SetEffectChain IXAudio2Voice_SetEffectChain +#define IXAudio2SubmixVoice_EnableEffect IXAudio2Voice_EnableEffect +#define IXAudio2SubmixVoice_DisableEffect IXAudio2Voice_DisableEffect +#define IXAudio2SubmixVoice_GetEffectState IXAudio2Voice_GetEffectState +#define IXAudio2SubmixVoice_SetEffectParameters IXAudio2Voice_SetEffectParameters +#define IXAudio2SubmixVoice_GetEffectParameters IXAudio2Voice_GetEffectParameters +#define IXAudio2SubmixVoice_SetFilterParameters IXAudio2Voice_SetFilterParameters +#define IXAudio2SubmixVoice_GetFilterParameters IXAudio2Voice_GetFilterParameters +#define IXAudio2SubmixVoice_SetOutputFilterParameters IXAudio2Voice_SetOutputFilterParameters +#define IXAudio2SubmixVoice_GetOutputFilterParameters IXAudio2Voice_GetOutputFilterParameters +#define IXAudio2SubmixVoice_SetVolume IXAudio2Voice_SetVolume +#define IXAudio2SubmixVoice_GetVolume IXAudio2Voice_GetVolume +#define IXAudio2SubmixVoice_SetChannelVolumes IXAudio2Voice_SetChannelVolumes +#define IXAudio2SubmixVoice_GetChannelVolumes IXAudio2Voice_GetChannelVolumes +#define IXAudio2SubmixVoice_SetOutputMatrix IXAudio2Voice_SetOutputMatrix +#define IXAudio2SubmixVoice_GetOutputMatrix IXAudio2Voice_GetOutputMatrix +#define IXAudio2SubmixVoice_DestroyVoice IXAudio2Voice_DestroyVoice + +// IXAudio2MasteringVoice +#define IXAudio2MasteringVoice_GetVoiceDetails IXAudio2Voice_GetVoiceDetails +#define IXAudio2MasteringVoice_SetOutputVoices IXAudio2Voice_SetOutputVoices +#define IXAudio2MasteringVoice_SetEffectChain IXAudio2Voice_SetEffectChain +#define IXAudio2MasteringVoice_EnableEffect IXAudio2Voice_EnableEffect +#define IXAudio2MasteringVoice_DisableEffect IXAudio2Voice_DisableEffect +#define IXAudio2MasteringVoice_GetEffectState IXAudio2Voice_GetEffectState +#define IXAudio2MasteringVoice_SetEffectParameters IXAudio2Voice_SetEffectParameters +#define IXAudio2MasteringVoice_GetEffectParameters IXAudio2Voice_GetEffectParameters +#define IXAudio2MasteringVoice_SetFilterParameters IXAudio2Voice_SetFilterParameters +#define IXAudio2MasteringVoice_GetFilterParameters IXAudio2Voice_GetFilterParameters +#define IXAudio2MasteringVoice_SetOutputFilterParameters IXAudio2Voice_SetOutputFilterParameters +#define IXAudio2MasteringVoice_GetOutputFilterParameters IXAudio2Voice_GetOutputFilterParameters +#define IXAudio2MasteringVoice_SetVolume IXAudio2Voice_SetVolume +#define IXAudio2MasteringVoice_GetVolume IXAudio2Voice_GetVolume +#define IXAudio2MasteringVoice_SetChannelVolumes IXAudio2Voice_SetChannelVolumes +#define IXAudio2MasteringVoice_GetChannelVolumes IXAudio2Voice_GetChannelVolumes +#define IXAudio2MasteringVoice_SetOutputMatrix IXAudio2Voice_SetOutputMatrix +#define IXAudio2MasteringVoice_GetOutputMatrix IXAudio2Voice_GetOutputMatrix +#define IXAudio2MasteringVoice_DestroyVoice IXAudio2Voice_DestroyVoice + +#endif // #ifndef __cplusplus + + +/************************************************************************** + * + * Utility functions used to convert from pitch in semitones and volume + * in decibels to the frequency and amplitude ratio units used by XAudio2. + * These are only defined if the client #defines XAUDIO2_HELPER_FUNCTIONS + * prior to #including xaudio2.h. + * + **************************************************************************/ + +#ifdef XAUDIO2_HELPER_FUNCTIONS + +#define _USE_MATH_DEFINES // Make math.h define M_PI +#include // For powf, log10f, sinf and asinf + +// Calculate the argument to SetVolume from a decibel value +__inline float XAudio2DecibelsToAmplitudeRatio(float Decibels) +{ + return powf(10.0f, Decibels / 20.0f); +} + +// Recover a volume in decibels from an amplitude factor +__inline float XAudio2AmplitudeRatioToDecibels(float Volume) +{ + if (Volume == 0) + { + return -3.402823466e+38f; // Smallest float value (-FLT_MAX) + } + return 20.0f * log10f(Volume); +} + +// Calculate the argument to SetFrequencyRatio from a semitone value +__inline float XAudio2SemitonesToFrequencyRatio(float Semitones) +{ + // FrequencyRatio = 2 ^ Octaves + // = 2 ^ (Semitones / 12) + return powf(2.0f, Semitones / 12.0f); +} + +// Recover a pitch in semitones from a frequency ratio +__inline float XAudio2FrequencyRatioToSemitones(float FrequencyRatio) +{ + // Semitones = 12 * log2(FrequencyRatio) + // = 12 * log2(10) * log10(FrequencyRatio) + return 39.86313713864835f * log10f(FrequencyRatio); +} + +// Convert from filter cutoff frequencies expressed in Hertz to the radian +// frequency values used in XAUDIO2_FILTER_PARAMETERS.Frequency. Note that +// the highest CutoffFrequency supported is SampleRate/6. Higher values of +// CutoffFrequency will return XAUDIO2_MAX_FILTER_FREQUENCY. +__inline float XAudio2CutoffFrequencyToRadians(float CutoffFrequency, UINT32 SampleRate) +{ + if ((UINT32)(CutoffFrequency * 6.0f) >= SampleRate) + { + return XAUDIO2_MAX_FILTER_FREQUENCY; + } + return 2.0f * sinf((float)M_PI * CutoffFrequency / SampleRate); +} + +// Convert from radian frequencies back to absolute frequencies in Hertz +__inline float XAudio2RadiansToCutoffFrequency(float Radians, float SampleRate) +{ + return SampleRate * asinf(Radians / 2.0f) / (float)M_PI; +} +#endif // #ifdef XAUDIO2_HELPER_FUNCTIONS + + +/************************************************************************** + * + * XAudio2Create: Top-level function that creates an XAudio2 instance. + * + * On Windows this is just an inline function that calls CoCreateInstance + * and Initialize. The arguments are described above, under Initialize, + * except that the XAUDIO2_DEBUG_ENGINE flag can be used here to select + * the debug version of XAudio2. + * + * On Xbox, this function is implemented in the XAudio2 library, and the + * XAUDIO2_DEBUG_ENGINE flag has no effect; the client must explicitly + * link with the debug version of the library to obtain debug behavior. + * + **************************************************************************/ + +#ifdef _XBOX + +STDAPI XAudio2Create(__deref_out IXAudio2** ppXAudio2, UINT32 Flags X2DEFAULT(0), + XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)); + +#else // Windows + +__inline HRESULT XAudio2Create(__deref_out IXAudio2** ppXAudio2, UINT32 Flags X2DEFAULT(0), + XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)) +{ + // Instantiate the appropriate XAudio2 engine + IXAudio2* pXAudio2; + + #ifdef __cplusplus + + HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? __uuidof(XAudio2_Debug) : __uuidof(XAudio2), + NULL, CLSCTX_INPROC_SERVER, __uuidof(IXAudio2), (void**)&pXAudio2); + if (SUCCEEDED(hr)) + { + hr = pXAudio2->Initialize(Flags, XAudio2Processor); + + if (SUCCEEDED(hr)) + { + *ppXAudio2 = pXAudio2; + } + else + { + pXAudio2->Release(); + } + } + + #else + + HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? &CLSID_XAudio2_Debug : &CLSID_XAudio2, + NULL, CLSCTX_INPROC_SERVER, &IID_IXAudio2, (void**)&pXAudio2); + if (SUCCEEDED(hr)) + { + hr = pXAudio2->lpVtbl->Initialize(pXAudio2, Flags, XAudio2Processor); + + if (SUCCEEDED(hr)) + { + *ppXAudio2 = pXAudio2; + } + else + { + pXAudio2->lpVtbl->Release(pXAudio2); + } + } + + #endif // #ifdef __cplusplus + + return hr; +} + +#endif // #ifdef _XBOX + + +// Undo the #pragma pack(push, 1) directive at the top of this file +#pragma pack(pop) + +#endif // #ifndef GUID_DEFS_ONLY +#endif // #ifndef __XAUDIO2_INCLUDED__ diff --git a/external_packages/audiodefs.h b/external_packages/audiodefs.h new file mode 100644 index 0000000..ff995ec --- /dev/null +++ b/external_packages/audiodefs.h @@ -0,0 +1,263 @@ +/*************************************************************************** + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * + * File: audiodefs.h + * Content: Basic constants and data types for audio work. + * + * Remarks: This header file defines all of the audio format constants and + * structures required for XAudio2 and XACT work. Providing these + * in a single location avoids certain dependency problems in the + * legacy audio headers (mmreg.h, mmsystem.h, ksmedia.h). + * + * NOTE: Including the legacy headers after this one may cause a + * compilation error, because they define some of the same types + * defined here without preprocessor guards to avoid multiple + * definitions. If a source file needs one of the old headers, + * it must include it before including audiodefs.h. + * + ***************************************************************************/ + +#ifndef __AUDIODEFS_INCLUDED__ +#define __AUDIODEFS_INCLUDED__ + +#include // For WORD, DWORD, etc. + +#pragma pack(push, 1) // Pack structures to 1-byte boundaries + + +/************************************************************************** + * + * WAVEFORMATEX: Base structure for many audio formats. Format-specific + * extensions can be defined for particular formats by using a non-zero + * cbSize value and adding extra fields to the end of this structure. + * + ***************************************************************************/ + +#ifndef _WAVEFORMATEX_ + + #define _WAVEFORMATEX_ + typedef struct tWAVEFORMATEX + { + WORD wFormatTag; // Integer identifier of the format + WORD nChannels; // Number of audio channels + DWORD nSamplesPerSec; // Audio sample rate + DWORD nAvgBytesPerSec; // Bytes per second (possibly approximate) + WORD nBlockAlign; // Size in bytes of a sample block (all channels) + WORD wBitsPerSample; // Size in bits of a single per-channel sample + WORD cbSize; // Bytes of extra data appended to this struct + } WAVEFORMATEX; + +#endif + +// Defining pointer types outside of the #if block to make sure they are +// defined even if mmreg.h or mmsystem.h is #included before this file + +typedef WAVEFORMATEX *PWAVEFORMATEX, *NPWAVEFORMATEX, *LPWAVEFORMATEX; +typedef const WAVEFORMATEX *PCWAVEFORMATEX, *LPCWAVEFORMATEX; + + +/************************************************************************** + * + * WAVEFORMATEXTENSIBLE: Extended version of WAVEFORMATEX that should be + * used as a basis for all new audio formats. The format tag is replaced + * with a GUID, allowing new formats to be defined without registering a + * format tag with Microsoft. There are also new fields that can be used + * to specify the spatial positions for each channel and the bit packing + * used for wide samples (e.g. 24-bit PCM samples in 32-bit containers). + * + ***************************************************************************/ + +#ifndef _WAVEFORMATEXTENSIBLE_ + + #define _WAVEFORMATEXTENSIBLE_ + typedef struct + { + WAVEFORMATEX Format; // Base WAVEFORMATEX data + union + { + WORD wValidBitsPerSample; // Valid bits in each sample container + WORD wSamplesPerBlock; // Samples per block of audio data; valid + // if wBitsPerSample=0 (but rarely used). + WORD wReserved; // Zero if neither case above applies. + } Samples; + DWORD dwChannelMask; // Positions of the audio channels + GUID SubFormat; // Format identifier GUID + } WAVEFORMATEXTENSIBLE; + +#endif + +typedef WAVEFORMATEXTENSIBLE *PWAVEFORMATEXTENSIBLE, *LPWAVEFORMATEXTENSIBLE; +typedef const WAVEFORMATEXTENSIBLE *PCWAVEFORMATEXTENSIBLE, *LPCWAVEFORMATEXTENSIBLE; + + + +/************************************************************************** + * + * Define the most common wave format tags used in WAVEFORMATEX formats. + * + ***************************************************************************/ + +#ifndef WAVE_FORMAT_PCM // Pulse Code Modulation + + // If WAVE_FORMAT_PCM is not defined, we need to define some legacy types + // for compatibility with the Windows mmreg.h / mmsystem.h header files. + + // Old general format structure (information common to all formats) + typedef struct waveformat_tag + { + WORD wFormatTag; + WORD nChannels; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; + } WAVEFORMAT, *PWAVEFORMAT, NEAR *NPWAVEFORMAT, FAR *LPWAVEFORMAT; + + // Specific format structure for PCM data + typedef struct pcmwaveformat_tag + { + WAVEFORMAT wf; + WORD wBitsPerSample; + } PCMWAVEFORMAT, *PPCMWAVEFORMAT, NEAR *NPPCMWAVEFORMAT, FAR *LPPCMWAVEFORMAT; + + #define WAVE_FORMAT_PCM 0x0001 + +#endif + +#ifndef WAVE_FORMAT_ADPCM // Microsoft Adaptive Differental PCM + + // Replicate the Microsoft ADPCM type definitions from mmreg.h. + + typedef struct adpcmcoef_tag + { + short iCoef1; + short iCoef2; + } ADPCMCOEFSET; + + #pragma warning(push) + #pragma warning(disable:4200) // Disable zero-sized array warnings + + typedef struct adpcmwaveformat_tag { + WAVEFORMATEX wfx; + WORD wSamplesPerBlock; + WORD wNumCoef; + ADPCMCOEFSET aCoef[]; // Always 7 coefficient pairs for MS ADPCM + } ADPCMWAVEFORMAT; + + #pragma warning(pop) + + #define WAVE_FORMAT_ADPCM 0x0002 + +#endif + +// Other frequently used format tags + +#ifndef WAVE_FORMAT_UNKNOWN + #define WAVE_FORMAT_UNKNOWN 0x0000 // Unknown or invalid format tag +#endif + +#ifndef WAVE_FORMAT_IEEE_FLOAT + #define WAVE_FORMAT_IEEE_FLOAT 0x0003 // 32-bit floating-point +#endif + +#ifndef WAVE_FORMAT_MPEGLAYER3 + #define WAVE_FORMAT_MPEGLAYER3 0x0055 // ISO/MPEG Layer3 +#endif + +#ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF + #define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092 // Dolby Audio Codec 3 over S/PDIF +#endif + +#ifndef WAVE_FORMAT_WMAUDIO2 + #define WAVE_FORMAT_WMAUDIO2 0x0161 // Windows Media Audio +#endif + +#ifndef WAVE_FORMAT_WMAUDIO3 + #define WAVE_FORMAT_WMAUDIO3 0x0162 // Windows Media Audio Pro +#endif + +#ifndef WAVE_FORMAT_WMASPDIF + #define WAVE_FORMAT_WMASPDIF 0x0164 // Windows Media Audio over S/PDIF +#endif + +#ifndef WAVE_FORMAT_EXTENSIBLE + #define WAVE_FORMAT_EXTENSIBLE 0xFFFE // All WAVEFORMATEXTENSIBLE formats +#endif + + +/************************************************************************** + * + * Define the most common wave format GUIDs used in WAVEFORMATEXTENSIBLE + * formats. Note that including the Windows ksmedia.h header after this + * one will cause build problems; this cannot be avoided, since ksmedia.h + * defines these macros without preprocessor guards. + * + ***************************************************************************/ + +#ifdef __cplusplus // uuid() and __uuidof() are only available in C++ + + #ifndef KSDATAFORMAT_SUBTYPE_PCM + struct __declspec(uuid("00000001-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_PCM_STRUCT; + #define KSDATAFORMAT_SUBTYPE_PCM __uuidof(KSDATAFORMAT_SUBTYPE_PCM_STRUCT) + #endif + + #ifndef KSDATAFORMAT_SUBTYPE_ADPCM + struct __declspec(uuid("00000002-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_ADPCM_STRUCT; + #define KSDATAFORMAT_SUBTYPE_ADPCM __uuidof(KSDATAFORMAT_SUBTYPE_ADPCM_STRUCT) + #endif + + #ifndef KSDATAFORMAT_SUBTYPE_IEEE_FLOAT + struct __declspec(uuid("00000003-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_STRUCT; + #define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT __uuidof(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_STRUCT) + #endif + +#endif + + +/************************************************************************** + * + * Speaker positions used in the WAVEFORMATEXTENSIBLE dwChannelMask field. + * + ***************************************************************************/ + +#ifndef SPEAKER_FRONT_LEFT + #define SPEAKER_FRONT_LEFT 0x00000001 + #define SPEAKER_FRONT_RIGHT 0x00000002 + #define SPEAKER_FRONT_CENTER 0x00000004 + #define SPEAKER_LOW_FREQUENCY 0x00000008 + #define SPEAKER_BACK_LEFT 0x00000010 + #define SPEAKER_BACK_RIGHT 0x00000020 + #define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040 + #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080 + #define SPEAKER_BACK_CENTER 0x00000100 + #define SPEAKER_SIDE_LEFT 0x00000200 + #define SPEAKER_SIDE_RIGHT 0x00000400 + #define SPEAKER_TOP_CENTER 0x00000800 + #define SPEAKER_TOP_FRONT_LEFT 0x00001000 + #define SPEAKER_TOP_FRONT_CENTER 0x00002000 + #define SPEAKER_TOP_FRONT_RIGHT 0x00004000 + #define SPEAKER_TOP_BACK_LEFT 0x00008000 + #define SPEAKER_TOP_BACK_CENTER 0x00010000 + #define SPEAKER_TOP_BACK_RIGHT 0x00020000 + #define SPEAKER_RESERVED 0x7FFC0000 + #define SPEAKER_ALL 0x80000000 + #define _SPEAKER_POSITIONS_ +#endif + +#ifndef SPEAKER_STEREO + #define SPEAKER_MONO (SPEAKER_FRONT_CENTER) + #define SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT) + #define SPEAKER_2POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY) + #define SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER) + #define SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) + #define SPEAKER_4POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) + #define SPEAKER_5POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) + #define SPEAKER_7POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER) + #define SPEAKER_5POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) + #define SPEAKER_7POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) +#endif + + +#pragma pack(pop) + +#endif // #ifndef __AUDIODEFS_INCLUDED__ diff --git a/bass.h b/external_packages/bass.h similarity index 95% rename from bass.h rename to external_packages/bass.h index dc4c477..c77e76d 100644 --- a/bass.h +++ b/external_packages/bass.h @@ -1,6 +1,6 @@ /* BASS 2.4 C/C++ header file - Copyright (c) 1999-2010 Un4seen Developments Ltd. + Copyright (c) 1999-2012 Un4seen Developments Ltd. See the BASS.CHM file for more detailed documentation */ @@ -114,24 +114,31 @@ typedef DWORD HPLUGIN; // Plugin handle #define BASS_CONFIG_VERIFY 23 #define BASS_CONFIG_UPDATETHREADS 24 #define BASS_CONFIG_DEV_BUFFER 27 +#define BASS_CONFIG_VISTA_TRUEPOS 30 +#define BASS_CONFIG_IOS_MIXAUDIO 34 #define BASS_CONFIG_DEV_DEFAULT 36 #define BASS_CONFIG_NET_READTIMEOUT 37 +#define BASS_CONFIG_VISTA_SPEAKERS 38 +#define BASS_CONFIG_IOS_SPEAKER 39 +#define BASS_CONFIG_HANDLES 41 +#define BASS_CONFIG_UNICODE 42 +#define BASS_CONFIG_SRC 43 +#define BASS_CONFIG_SRC_SAMPLE 44 // BASS_SetConfigPtr options #define BASS_CONFIG_NET_AGENT 16 #define BASS_CONFIG_NET_PROXY 17 -// Initialization flags -#define BASS_DEVICE_8BITS 1 // use 8 bit resolution, else 16 bit -#define BASS_DEVICE_MONO 2 // use mono, else stereo -#define BASS_DEVICE_3D 4 // enable 3D functionality -#define BASS_DEVICE_LATENCY 256 // calculate device latency (BASS_INFO struct) -#define BASS_DEVICE_CPSPEAKERS 1024 // detect speakers via Windows control panel -#define BASS_DEVICE_SPEAKERS 2048 // force enabling of speaker assignment -#define BASS_DEVICE_NOSPEAKER 4096 // ignore speaker arrangement -#ifdef __linux__ -#define BASS_DEVICE_DMIX 8192 // use ALSA "dmix" plugin -#endif +// BASS_Init flags +#define BASS_DEVICE_8BITS 1 // 8 bit resolution, else 16 bit +#define BASS_DEVICE_MONO 2 // mono, else stereo +#define BASS_DEVICE_3D 4 // enable 3D functionality +#define BASS_DEVICE_LATENCY 0x100 // calculate device latency (BASS_INFO struct) +#define BASS_DEVICE_CPSPEAKERS 0x400 // detect speakers via Windows control panel +#define BASS_DEVICE_SPEAKERS 0x800 // force enabling of speaker assignment +#define BASS_DEVICE_NOSPEAKER 0x1000 // ignore speaker arrangement +#define BASS_DEVICE_DMIX 0x2000 // use ALSA "dmix" plugin +#define BASS_DEVICE_FREQ 0x4000 // set device sample rate // DirectSound interfaces (for use with BASS_GetDSoundObject) #define BASS_OBJECT_DS 1 // IDirectSound @@ -166,9 +173,9 @@ typedef struct { DWORD minbuf; // recommended minimum buffer length in ms (requires BASS_DEVICE_LATENCY) DWORD dsver; // DirectSound version DWORD latency; // delay (in ms) before start of playback (requires BASS_DEVICE_LATENCY) - DWORD initflags;// BASS_Init "flags" parameter + DWORD initflags; // BASS_Init "flags" parameter DWORD speakers; // number of speakers available - DWORD freq; // current output rate (Vista/OSX only) + DWORD freq; // current output rate } BASS_INFO; // BASS_INFO flags (from DSOUND.H) @@ -186,7 +193,7 @@ typedef struct { DWORD formats; // supported standard formats (WAVE_FORMAT_xxx flags) DWORD inputs; // number of inputs BOOL singlein; // TRUE = only 1 input can be set at a time - DWORD freq; // current input rate (Vista/OSX only) + DWORD freq; // current input rate } BASS_RECORDINFO; // BASS_RECORDINFO flags (from DSOUND.H) @@ -323,6 +330,7 @@ typedef struct { #define BASS_CTYPE_STREAM_MP3 0x10005 #define BASS_CTYPE_STREAM_AIFF 0x10006 #define BASS_CTYPE_STREAM_CA 0x10007 +#define BASS_CTYPE_STREAM_MF 0x10008 #define BASS_CTYPE_STREAM_WAV 0x40000 // WAVE flag, LOWORD=codec #define BASS_CTYPE_STREAM_WAV_PCM 0x50001 #define BASS_CTYPE_STREAM_WAV_FLOAT 0x50003 @@ -542,6 +550,8 @@ RETURN : TRUE = continue recording, FALSE = stop */ #define BASS_ATTRIB_PAN 3 #define BASS_ATTRIB_EAXMIX 4 #define BASS_ATTRIB_NOBUFFER 5 +#define BASS_ATTRIB_CPU 7 +#define BASS_ATTRIB_SRC 8 #define BASS_ATTRIB_MUSIC_AMPLIFY 0x100 #define BASS_ATTRIB_MUSIC_PANSEP 0x101 #define BASS_ATTRIB_MUSIC_PSCALER 0x102 @@ -573,9 +583,12 @@ RETURN : TRUE = continue recording, FALSE = stop */ #define BASS_TAG_ICY 4 // ICY headers : series of null-terminated ANSI strings #define BASS_TAG_META 5 // ICY metadata : ANSI string #define BASS_TAG_APE 6 // APE tags : series of null-terminated UTF-8 strings +#define BASS_TAG_MP4 7 // MP4/iTunes metadata : series of null-terminated UTF-8 strings #define BASS_TAG_VENDOR 9 // OGG encoder : UTF-8 string #define BASS_TAG_LYRICS3 10 // Lyric3v2 tag : ASCII string #define BASS_TAG_CA_CODEC 11 // CoreAudio codec info : TAG_CA_CODEC structure +#define BASS_TAG_MF 13 // Media Foundation tags : series of null-terminated UTF-8 strings +#define BASS_TAG_WAVEFORMAT 14 // WAVE format : WAVEFORMATEEX structure #define BASS_TAG_RIFF_INFO 0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings #define BASS_TAG_RIFF_BEXT 0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure #define BASS_TAG_RIFF_CART 0x102 // RIFF/BWF "cart" tags : TAG_CART structure @@ -630,9 +643,6 @@ typedef struct { #endif } TAG_BEXT; #pragma pack(pop) -#ifdef _MSC_VER -#pragma warning(pop) -#endif // BWF "cart" tag structures typedef struct @@ -670,6 +680,9 @@ typedef struct char TagText[1]; // free form text for scripts or tags #endif } TAG_CART; +#ifdef _MSC_VER +#pragma warning(pop) +#endif // CoreAudio codec info structure typedef struct { @@ -678,6 +691,23 @@ typedef struct { const char *name; // description } TAG_CA_CODEC; +#ifndef _WAVEFORMATEX_ +#define _WAVEFORMATEX_ +#pragma pack(push,1) +typedef struct tWAVEFORMATEX +{ + WORD wFormatTag; + WORD nChannels; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; + WORD wBitsPerSample; + WORD cbSize; +} WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX; +typedef const WAVEFORMATEX *LPCWAVEFORMATEX; +#pragma pack(pop) +#endif + // BASS_ChannelGetLength/GetPosition/SetPosition modes #define BASS_POS_BYTE 0 // byte position #define BASS_POS_MUSIC_ORDER 1 // order.row position, MAKELONG(order,row) @@ -801,7 +831,7 @@ typedef struct { BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value); DWORD BASSDEF(BASS_GetConfig)(DWORD option); -BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, void *value); +BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, const void *value); void *BASSDEF(BASS_GetConfigPtr)(DWORD option); DWORD BASSDEF(BASS_GetVersion)(); int BASSDEF(BASS_ErrorGetCode)(); diff --git a/bassmidi.h b/external_packages/bassmidi.h similarity index 99% rename from bassmidi.h rename to external_packages/bassmidi.h index b6756f6..4509bbd 100644 --- a/bassmidi.h +++ b/external_packages/bassmidi.h @@ -137,6 +137,8 @@ typedef struct { #define MIDI_EVENT_SYSTEM 61 #define MIDI_EVENT_TEMPO 62 #define MIDI_EVENT_SCALETUNING 63 +#define MIDI_EVENT_CONTROL 64 +#define MIDI_EVENT_CHANPRES_VIBRATO 65 #define MIDI_EVENT_MIXLEVEL 0x10000 #define MIDI_EVENT_TRANSPOSE 0x10001 #define MIDI_EVENT_SYSTEMEX 0x10002 diff --git a/external_packages/comdecl.h b/external_packages/comdecl.h new file mode 100644 index 0000000..2ae9a96 --- /dev/null +++ b/external_packages/comdecl.h @@ -0,0 +1,59 @@ +// comdecl.h: Macros to facilitate COM interface and GUID declarations. +// Copyright (c) Microsoft Corporation. All rights reserved. + +#ifndef _COMDECL_H_ +#define _COMDECL_H_ + +#ifndef _XBOX + #include // For standard COM interface macros +#else + #pragma warning(push) + #pragma warning(disable:4061) + #include // Required by xobjbase.h + #include // Special definitions for Xbox build + #pragma warning(pop) +#endif + +// The DEFINE_CLSID() and DEFINE_IID() macros defined below allow COM GUIDs to +// be declared and defined in such a way that clients can obtain the GUIDs using +// either the __uuidof() extension or the old-style CLSID_Foo / IID_IFoo names. +// If using the latter approach, the client can also choose whether to get the +// GUID definitions by defining the INITGUID preprocessor constant or by linking +// to a GUID library. This works in either C or C++. + +#ifdef __cplusplus + + #define DECLSPEC_UUID_WRAPPER(x) __declspec(uuid(#x)) + #ifdef INITGUID + + #define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + class DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) className; \ + EXTERN_C const GUID DECLSPEC_SELECTANY CLSID_##className = __uuidof(className) + + #define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + interface DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) interfaceName; \ + EXTERN_C const GUID DECLSPEC_SELECTANY IID_##interfaceName = __uuidof(interfaceName) + + #else // INITGUID + + #define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + class DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) className; \ + EXTERN_C const GUID CLSID_##className + + #define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + interface DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) interfaceName; \ + EXTERN_C const GUID IID_##interfaceName + + #endif // INITGUID + +#else // __cplusplus + + #define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + DEFINE_GUID(CLSID_##className, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8) + + #define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + DEFINE_GUID(IID_##interfaceName, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8) + +#endif // __cplusplus + +#endif // #ifndef _COMDECL_H_ diff --git a/external_packages/inttypes.h b/external_packages/inttypes.h new file mode 100644 index 0000000..4b3828a --- /dev/null +++ b/external_packages/inttypes.h @@ -0,0 +1,305 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + + +#endif // _MSC_INTTYPES_H_ ] diff --git a/external_packages/lib/bass.dll b/external_packages/lib/bass.dll new file mode 100644 index 0000000..5d5e81c Binary files /dev/null and b/external_packages/lib/bass.dll differ diff --git a/external_packages/lib/bass.lib b/external_packages/lib/bass.lib new file mode 100644 index 0000000..ac5ab1d Binary files /dev/null and b/external_packages/lib/bass.lib differ diff --git a/external_packages/lib/bass_mpc.dll b/external_packages/lib/bass_mpc.dll new file mode 100644 index 0000000..1b0ee18 Binary files /dev/null and b/external_packages/lib/bass_mpc.dll differ diff --git a/external_packages/lib/bassflac.dll b/external_packages/lib/bassflac.dll new file mode 100644 index 0000000..1b84e1a Binary files /dev/null and b/external_packages/lib/bassflac.dll differ diff --git a/external_packages/lib/bassmidi.dll b/external_packages/lib/bassmidi.dll new file mode 100644 index 0000000..970603c Binary files /dev/null and b/external_packages/lib/bassmidi.dll differ diff --git a/external_packages/lib/bassmidi.lib b/external_packages/lib/bassmidi.lib new file mode 100644 index 0000000..1900d0d Binary files /dev/null and b/external_packages/lib/bassmidi.lib differ diff --git a/external_packages/lib/bassopus.dll b/external_packages/lib/bassopus.dll new file mode 100644 index 0000000..64fb1ee Binary files /dev/null and b/external_packages/lib/bassopus.dll differ diff --git a/external_packages/lib/basswv.dll b/external_packages/lib/basswv.dll new file mode 100644 index 0000000..aa3e8fe Binary files /dev/null and b/external_packages/lib/basswv.dll differ diff --git a/external_packages/lib64/bass.dll b/external_packages/lib64/bass.dll new file mode 100644 index 0000000..b024b7b Binary files /dev/null and b/external_packages/lib64/bass.dll differ diff --git a/external_packages/lib64/bass.lib b/external_packages/lib64/bass.lib new file mode 100644 index 0000000..cf672a1 Binary files /dev/null and b/external_packages/lib64/bass.lib differ diff --git a/external_packages/lib64/bass_mpc.dll b/external_packages/lib64/bass_mpc.dll new file mode 100644 index 0000000..37ee092 Binary files /dev/null and b/external_packages/lib64/bass_mpc.dll differ diff --git a/external_packages/lib64/bassflac.dll b/external_packages/lib64/bassflac.dll new file mode 100644 index 0000000..572b677 Binary files /dev/null and b/external_packages/lib64/bassflac.dll differ diff --git a/external_packages/lib64/bassmidi.dll b/external_packages/lib64/bassmidi.dll new file mode 100644 index 0000000..13c1ae0 Binary files /dev/null and b/external_packages/lib64/bassmidi.dll differ diff --git a/external_packages/lib64/bassmidi.lib b/external_packages/lib64/bassmidi.lib new file mode 100644 index 0000000..8e35fd0 Binary files /dev/null and b/external_packages/lib64/bassmidi.lib differ diff --git a/external_packages/lib64/bassopus.dll b/external_packages/lib64/bassopus.dll new file mode 100644 index 0000000..f3e10c1 Binary files /dev/null and b/external_packages/lib64/bassopus.dll differ diff --git a/external_packages/lib64/basswv.dll b/external_packages/lib64/basswv.dll new file mode 100644 index 0000000..4156471 Binary files /dev/null and b/external_packages/lib64/basswv.dll differ diff --git a/bassmididrv_source/mmddk.h b/external_packages/mmddk.h similarity index 75% rename from bassmididrv_source/mmddk.h rename to external_packages/mmddk.h index 3b51df3..5bbe0a5 100644 --- a/bassmididrv_source/mmddk.h +++ b/external_packages/mmddk.h @@ -1,6 +1,4 @@ -/* -*- tab-width: 8; c-basic-offset: 4 -*- */ - -/***************************************************************************** +/* * Copyright 1998, Luiz Otavio L. Zorzella * 1999, Eric Pouech * @@ -19,9 +17,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ***************************************************************************** + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef __MMDDK_H #define __MMDDK_H @@ -29,8 +25,9 @@ #include #include -/* Maxium drivers */ -#define MAXWAVEDRIVERS 10 +#ifdef __cplusplus +extern "C" { +#endif #define MAX_MIDIINDRV (16) /* For now I'm making 16 the maximum number of midi devices one can @@ -69,8 +66,8 @@ typedef struct { * - codes from 0 to 0x7FFFFFFF are user defined * - codes from 0x80000000 to 0xFFFFFFFF are reserved for future definition by microsoft */ -#define DRVM_IOCTL_CMD_USER 0x00000000L -#define DRVM_IOCTL_CMD_SYSTEM 0x80000000L +#define DRVM_IOCTL_CMD_USER __MSABI_LONG(0x00000000) +#define DRVM_IOCTL_CMD_SYSTEM __MSABI_LONG(0x80000000) #define DRVM_MAPPER 0x2000 #define DRVM_USER 0x4000 @@ -91,11 +88,10 @@ typedef struct { #define DRV_QUERYSTRINGID (DRV_RESERVED + 14) #define DRV_QUERYSTRINGIDSIZE (DRV_RESERVED + 15) #define DRV_QUERYIDFROMSTRINGID (DRV_RESERVED + 16) -#ifdef __WINESRC__ -#define DRV_QUERYDSOUNDIFACE (DRV_RESERVED + 20) -#define DRV_QUERYDSOUNDDESC (DRV_RESERVED + 21) -#define DRV_QUERYDSOUNDGUID (DRV_RESERVED + 22) -#endif +#define DRV_QUERYFUNCTIONINSTANCEID (DRV_RESERVED + 17) +#define DRV_QUERYFUNCTIONINSTANCEIDSIZE (DRV_RESERVED + 18) + +#define DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY 0x00000001 #define WODM_INIT DRVM_INIT #define WODM_GETNUMDEVS 3 @@ -206,12 +202,12 @@ typedef struct { #define JOY_HW_LASTENTRY 12 /* calibration flags */ -#define JOY_ISCAL_XY 0x00000001l /* XY are calibrated */ -#define JOY_ISCAL_Z 0x00000002l /* Z is calibrated */ -#define JOY_ISCAL_R 0x00000004l /* R is calibrated */ -#define JOY_ISCAL_U 0x00000008l /* U is calibrated */ -#define JOY_ISCAL_V 0x00000010l /* V is calibrated */ -#define JOY_ISCAL_POV 0x00000020l /* POV is calibrated */ +#define JOY_ISCAL_XY __MSABI_LONG(0x00000001) /* XY are calibrated */ +#define JOY_ISCAL_Z __MSABI_LONG(0x00000002) /* Z is calibrated */ +#define JOY_ISCAL_R __MSABI_LONG(0x00000004) /* R is calibrated */ +#define JOY_ISCAL_U __MSABI_LONG(0x00000008) /* U is calibrated */ +#define JOY_ISCAL_V __MSABI_LONG(0x00000010) /* V is calibrated */ +#define JOY_ISCAL_POV __MSABI_LONG(0x00000020) /* POV is calibrated */ /* point of view constants */ #define JOY_POV_NUMDIRS 4 @@ -221,42 +217,42 @@ typedef struct { #define JOY_POVVAL_RIGHT 3 /* Specific settings for joystick hardware */ -#define JOY_HWS_HASZ 0x00000001l /* has Z info? */ -#define JOY_HWS_HASPOV 0x00000002l /* point of view hat present */ -#define JOY_HWS_POVISBUTTONCOMBOS 0x00000004l /* pov done through combo of buttons */ -#define JOY_HWS_POVISPOLL 0x00000008l /* pov done through polling */ -#define JOY_HWS_ISYOKE 0x00000010l /* joystick is a flight yoke */ -#define JOY_HWS_ISGAMEPAD 0x00000020l /* joystick is a game pad */ -#define JOY_HWS_ISCARCTRL 0x00000040l /* joystick is a car controller */ +#define JOY_HWS_HASZ __MSABI_LONG(0x00000001) /* has Z info? */ +#define JOY_HWS_HASPOV __MSABI_LONG(0x00000002) /* point of view hat present */ +#define JOY_HWS_POVISBUTTONCOMBOS __MSABI_LONG(0x00000004) /* pov done through combo of buttons */ +#define JOY_HWS_POVISPOLL __MSABI_LONG(0x00000008) /* pov done through polling */ +#define JOY_HWS_ISYOKE __MSABI_LONG(0x00000010) /* joystick is a flight yoke */ +#define JOY_HWS_ISGAMEPAD __MSABI_LONG(0x00000020) /* joystick is a game pad */ +#define JOY_HWS_ISCARCTRL __MSABI_LONG(0x00000040) /* joystick is a car controller */ /* X defaults to J1 X axis */ -#define JOY_HWS_XISJ1Y 0x00000080l /* X is on J1 Y axis */ -#define JOY_HWS_XISJ2X 0x00000100l /* X is on J2 X axis */ -#define JOY_HWS_XISJ2Y 0x00000200l /* X is on J2 Y axis */ +#define JOY_HWS_XISJ1Y __MSABI_LONG(0x00000080) /* X is on J1 Y axis */ +#define JOY_HWS_XISJ2X __MSABI_LONG(0x00000100) /* X is on J2 X axis */ +#define JOY_HWS_XISJ2Y __MSABI_LONG(0x00000200) /* X is on J2 Y axis */ /* Y defaults to J1 Y axis */ -#define JOY_HWS_YISJ1X 0x00000400l /* Y is on J1 X axis */ -#define JOY_HWS_YISJ2X 0x00000800l /* Y is on J2 X axis */ -#define JOY_HWS_YISJ2Y 0x00001000l /* Y is on J2 Y axis */ +#define JOY_HWS_YISJ1X __MSABI_LONG(0x00000400) /* Y is on J1 X axis */ +#define JOY_HWS_YISJ2X __MSABI_LONG(0x00000800) /* Y is on J2 X axis */ +#define JOY_HWS_YISJ2Y __MSABI_LONG(0x00001000) /* Y is on J2 Y axis */ /* Z defaults to J2 Y axis */ -#define JOY_HWS_ZISJ1X 0x00002000l /* Z is on J1 X axis */ -#define JOY_HWS_ZISJ1Y 0x00004000l /* Z is on J1 Y axis */ -#define JOY_HWS_ZISJ2X 0x00008000l /* Z is on J2 X axis */ +#define JOY_HWS_ZISJ1X __MSABI_LONG(0x00002000) /* Z is on J1 X axis */ +#define JOY_HWS_ZISJ1Y __MSABI_LONG(0x00004000) /* Z is on J1 Y axis */ +#define JOY_HWS_ZISJ2X __MSABI_LONG(0x00008000) /* Z is on J2 X axis */ /* POV defaults to J2 Y axis, if it is not button based */ -#define JOY_HWS_POVISJ1X 0x00010000l /* pov done through J1 X axis */ -#define JOY_HWS_POVISJ1Y 0x00020000l /* pov done through J1 Y axis */ -#define JOY_HWS_POVISJ2X 0x00040000l /* pov done through J2 X axis */ +#define JOY_HWS_POVISJ1X __MSABI_LONG(0x00010000) /* pov done through J1 X axis */ +#define JOY_HWS_POVISJ1Y __MSABI_LONG(0x00020000) /* pov done through J1 Y axis */ +#define JOY_HWS_POVISJ2X __MSABI_LONG(0x00040000) /* pov done through J2 X axis */ /* R defaults to J2 X axis */ -#define JOY_HWS_HASR 0x00080000l /* has R (4th axis) info */ -#define JOY_HWS_RISJ1X 0x00100000l /* R done through J1 X axis */ -#define JOY_HWS_RISJ1Y 0x00200000l /* R done through J1 Y axis */ -#define JOY_HWS_RISJ2Y 0x00400000l /* R done through J2 X axis */ +#define JOY_HWS_HASR __MSABI_LONG(0x00080000) /* has R (4th axis) info */ +#define JOY_HWS_RISJ1X __MSABI_LONG(0x00100000) /* R done through J1 X axis */ +#define JOY_HWS_RISJ1Y __MSABI_LONG(0x00200000) /* R done through J1 Y axis */ +#define JOY_HWS_RISJ2Y __MSABI_LONG(0x00400000) /* R done through J2 X axis */ /* U & V for future hardware */ -#define JOY_HWS_HASU 0x00800000l /* has U (5th axis) info */ -#define JOY_HWS_HASV 0x01000000l /* has V (6th axis) info */ +#define JOY_HWS_HASU __MSABI_LONG(0x00800000) /* has U (5th axis) info */ +#define JOY_HWS_HASV __MSABI_LONG(0x01000000) /* has V (6th axis) info */ /* Usage settings */ -#define JOY_US_HASRUDDER 0x00000001l /* joystick configured with rudder */ -#define JOY_US_PRESENT 0x00000002l /* is joystick actually present? */ -#define JOY_US_ISOEM 0x00000004l /* joystick is an OEM defined type */ +#define JOY_US_HASRUDDER __MSABI_LONG(0x00000001) /* joystick configured with rudder */ +#define JOY_US_PRESENT __MSABI_LONG(0x00000002) /* is joystick actually present? */ +#define JOY_US_ISOEM __MSABI_LONG(0x00000004) /* joystick is an OEM defined type */ /* struct for storing x,y, z, and rudder values */ @@ -377,23 +373,23 @@ typedef JOYDEVMSGPROC *LPJOYDEVMSGPROC; #define MCI_RECT 7 #define MCI_CONSTANT 8 #define MCI_END_CONSTANT 9 +#define MCI_HWND 10 +#define MCI_HPAL 11 +#define MCI_HDC 12 -#define MAKEMCIRESOURCE(wRet, wRes) MAKELRESULT((wRet), (wRes)) +#ifdef _WIN64 +#define MCI_INTEGER64 13 +#endif /* _WIN64 */ -typedef struct { - DWORD dwCallback; - DWORD dwInstance; - HMIDIOUT hMidi; - DWORD dwFlags; -} PORTALLOC, *LPPORTALLOC; +#define MAKEMCIRESOURCE(wRet, wRes) MAKELRESULT((wRet), (wRes)) typedef struct { HWAVE hWave; LPWAVEFORMATEX lpFormat; - DWORD dwCallback; - DWORD dwInstance; + DWORD_PTR dwCallback; + DWORD_PTR dwInstance; UINT uMappedDeviceID; - DWORD dnDevNode; + DWORD_PTR dnDevNode; } WAVEOPENDESC, *LPWAVEOPENDESC; typedef struct { @@ -403,9 +399,9 @@ typedef struct { typedef struct { HMIDI hMidi; - DWORD dwCallback; - DWORD dwInstance; - DWORD dnDevNode; + DWORD_PTR dwCallback; + DWORD_PTR dwInstance; + DWORD_PTR dnDevNode; DWORD cIds; MIDIOPENSTRMID rgIds; } MIDIOPENDESC, *LPMIDIOPENDESC; @@ -414,8 +410,9 @@ typedef struct tMIXEROPENDESC { HMIXEROBJ hmx; LPVOID pReserved0; - DWORD dwCallback; - DWORD dwInstance; + DWORD_PTR dwCallback; + DWORD_PTR dwInstance; + DWORD_PTR dnDevNode; } MIXEROPENDESC, *LPMIXEROPENDESC; typedef struct { @@ -432,8 +429,8 @@ typedef struct { UINT wType; /* driver type (filled in by the driver) */ } MCI_OPEN_DRIVER_PARMSW, *LPMCI_OPEN_DRIVER_PARMSW; -DWORD WINAPI mciGetDriverData(UINT uDeviceID); -BOOL WINAPI mciSetDriverData(UINT uDeviceID, DWORD dwData); +DWORD_PTR WINAPI mciGetDriverData(UINT uDeviceID); +BOOL WINAPI mciSetDriverData(UINT uDeviceID, DWORD_PTR dwData); UINT WINAPI mciDriverYield(UINT uDeviceID); BOOL WINAPI mciDriverNotify(HWND hwndCallback, UINT uDeviceID, UINT uStatus); @@ -449,23 +446,23 @@ BOOL WINAPI mciFreeCommandResource(UINT uTable); #define DCB_TYPEMASK 0x0007 #define DCB_NOSWITCH 0x0008 /* don't switch stacks for callback */ -BOOL WINAPI DriverCallback(DWORD dwCallBack, UINT uFlags, HDRVR hDev, - UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2); +BOOL APIENTRY DriverCallback(DWORD_PTR dwCallback, DWORD dwFlags, + HDRVR hDevice, DWORD dwMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2); -typedef void (*LPTASKCALLBACK)(DWORD dwInst); +typedef VOID (*LPTASKCALLBACK)(DWORD_PTR dwInst); #define TASKERR_NOTASKSUPPORT 1 #define TASKERR_OUTOFMEMORY 2 -MMRESULT WINAPI mmTaskCreate(LPTASKCALLBACK, HANDLE*, DWORD); -void WINAPI mmTaskBlock(HANDLE); -BOOL WINAPI mmTaskSignal(HANDLE); -void WINAPI mmTaskYield(void); -HANDLE WINAPI mmGetCurrentTask(void); - - -#define WAVE_DIRECTSOUND 0x0080 - +UINT WINAPI mmTaskCreate(LPTASKCALLBACK, HANDLE*, DWORD_PTR); +VOID WINAPI mmTaskBlock(DWORD); +BOOL WINAPI mmTaskSignal(DWORD); +VOID WINAPI mmTaskYield(VOID); +DWORD WINAPI mmGetCurrentTask(VOID); #include +#ifdef __cplusplus +} +#endif + #endif /* __MMDDK_H */ diff --git a/external_packages/stdint.h b/external_packages/stdint.h new file mode 100644 index 0000000..d02608a --- /dev/null +++ b/external_packages/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/external_packages/xma2defs.h b/external_packages/xma2defs.h new file mode 100644 index 0000000..13a4306 --- /dev/null +++ b/external_packages/xma2defs.h @@ -0,0 +1,718 @@ +/*************************************************************************** + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * + * File: xma2defs.h + * Content: Constants, data types and functions for XMA2 compressed audio. + * + ***************************************************************************/ + +#ifndef __XMA2DEFS_INCLUDED__ +#define __XMA2DEFS_INCLUDED__ + +#include // Markers for documenting API semantics +#include // For S_OK, E_FAIL +#include // Basic data types and constants for audio work + + +/*************************************************************************** + * Overview + ***************************************************************************/ + +// A typical XMA2 file contains these RIFF chunks: +// +// 'fmt' or 'XMA2' chunk (or both): A description of the XMA data's structure +// and characteristics (length, channels, sample rate, loops, block size, etc). +// +// 'seek' chunk: A seek table to help navigate the XMA data. +// +// 'data' chunk: The encoded XMA2 data. +// +// The encoded XMA2 data is structured as a set of BLOCKS, which contain PACKETS, +// which contain FRAMES, which contain SUBFRAMES (roughly speaking). The frames +// in a file may also be divided into several subsets, called STREAMS. +// +// FRAME: A variable-sized segment of XMA data that decodes to exactly 512 mono +// or stereo PCM samples. This is the smallest unit of XMA data that can +// be decoded in isolation. Frames are an arbitrary number of bits in +// length, and need not be byte-aligned. See "XMA frame structure" below. +// +// SUBFRAME: A region of bits in an XMA frame that decodes to 128 mono or stereo +// samples. The XMA decoder cannot decode a subframe in isolation; it needs +// a whole frame to work with. However, it can begin emitting the frame's +// decoded samples at any one of the four subframe boundaries. Subframes +// can be addressed for seeking and looping purposes. +// +// PACKET: A 2Kb region containing a 32-bit header and some XMA frames. Frames +// can (and usually do) span packets. A packet's header includes the offset +// in bits of the first frame that begins within that packet. All of the +// frames that begin in a given packet belong to the same "stream" (see the +// Multichannel Audio section below). +// +// STREAM: A set of packets within an XMA file that all contain data for the +// same mono or stereo component of a PCM file with more than two channels. +// The packets comprising a given stream may be interleaved with each other +// more or less arbitrarily; see Multichannel Audio. +// +// BLOCK: An array of XMA packets; or, to break it down differently, a series of +// consecutive XMA frames, padded at the end with reserved data. A block +// must contain at least one 2Kb packet per stream, and it can hold up to +// 4095 packets (8190Kb), but its size is typically in the 32Kb-128Kb range. +// (The size chosen involves a trade-off between memory use and efficiency +// of reading from permanent storage.) +// +// XMA frames do not span blocks, so a block is guaranteed to begin with a +// set of complete frames, one per stream. Also, a block in a multi-stream +// XMA2 file always contains the same number of samples for each stream; +// see Multichannel Audio. +// +// The 'data' chunk in an XMA2 file is an array of XMA2WAVEFORMAT.BlockCount XMA +// blocks, all the same size (as specified in XMA2WAVEFORMAT.BlockSizeInBytes) +// except for the last one, which may be shorter. + + +// MULTICHANNEL AUDIO: the XMA decoder can only decode raw XMA data into either +// mono or stereo PCM data. In order to encode a 6-channel file (say), the file +// must be deinterleaved into 3 stereo streams that are encoded independently, +// producing 3 encoded XMA data streams. Then the packets in these 3 streams +// are interleaved to produce a single XMA2 file, and some information is added +// to the file so that the original 6-channel audio can be reconstructed at +// decode time. This works using the concept of an XMA stream (see above). +// +// The frames for all the streams in an XMA file are interleaved in an arbitrary +// order. To locate a frame that belongs to a given stream in a given XMA block, +// you must examine the first few packets in the block. Here (and only here) the +// packets are guaranteed to be presented in stream order, so that all frames +// beginning in packet 0 belong to stream 0 (the first stereo pair), etc. +// +// (This means that when decoding multi-stream XMA files, only entire XMA blocks +// should be submitted to the decoder; otherwise it cannot know which frames +// belong to which stream.) +// +// Once you have one frame that belongs to a given stream, you can find the next +// one by looking at the frame's 'NextFrameOffsetBits' value (which is stored in +// its first 15 bits; see XMAFRAME below). The GetXmaFrameBitPosition function +// uses this technique. + + +// SEEKING IN XMA2 FILES: Here is some pseudocode to find the byte position and +// subframe in an XMA2 file which will contain sample S when decoded. +// +// 1. Traverse the seek table to find the XMA2 block containing sample S. The +// seek table is an array of big-endian DWORDs, one per block in the file. +// The Nth DWORD is the total number of PCM samples that would be obtained +// by decoding the entire XMA file up to the end of block N. Hence, the +// block we want is the first one whose seek table entry is greater than S. +// (See the GetXmaBlockContainingSample helper function.) +// +// 2. Calculate which frame F within the block found above contains sample S. +// Since each frame decodes to 512 samples, this is straightforward. The +// first frame in the block produces samples X to X + 512, where X is the +// seek table entry for the prior block. So F is (S - X) / 512. +// +// 3. Find the bit offset within the block where frame F starts. Since frames +// are variable-sized, this can only be done by traversing all the frames in +// the block until we reach frame F. (See GetXmaFrameBitPosition.) +// +// 4. Frame F has four 128-sample subframes. To find the subframe containing S, +// we can use the formula (S % 512) / 128. +// +// In the case of multi-stream XMA files, sample S is a multichannel sample with +// parts coming from several frames, one per stream. To find all these frames, +// steps 2-4 need to be repeated for each stream N, using the knowledge that the +// first packets in a block are presented in stream order. The frame traversal +// in step 3 must be started at the first frame in the Nth packet of the block, +// which will be the first frame for stream N. (And the packet header will tell +// you the first frame's start position within the packet.) +// +// Step 1 can be performed using the GetXmaBlockContainingSample function below, +// and steps 2-4 by calling GetXmaDecodePositionForSample once for each stream. + + + +/*************************************************************************** + * XMA constants + ***************************************************************************/ + +// Size of the PCM samples produced by the XMA decoder +#define XMA_OUTPUT_SAMPLE_BYTES 2u +#define XMA_OUTPUT_SAMPLE_BITS (XMA_OUTPUT_SAMPLE_BYTES * 8u) + +// Size of an XMA packet +#define XMA_BYTES_PER_PACKET 2048u +#define XMA_BITS_PER_PACKET (XMA_BYTES_PER_PACKET * 8u) + +// Size of an XMA packet header +#define XMA_PACKET_HEADER_BYTES 4u +#define XMA_PACKET_HEADER_BITS (XMA_PACKET_HEADER_BYTES * 8u) + +// Sample blocks in a decoded XMA frame +#define XMA_SAMPLES_PER_FRAME 512u + +// Sample blocks in a decoded XMA subframe +#define XMA_SAMPLES_PER_SUBFRAME 128u + +// Maximum encoded data that can be submitted to the XMA decoder at a time +#define XMA_READBUFFER_MAX_PACKETS 4095u +#define XMA_READBUFFER_MAX_BYTES (XMA_READBUFFER_MAX_PACKETS * XMA_BYTES_PER_PACKET) + +// Maximum size allowed for the XMA decoder's output buffers +#define XMA_WRITEBUFFER_MAX_BYTES (31u * 256u) + +// Required byte alignment of the XMA decoder's output buffers +#define XMA_WRITEBUFFER_BYTE_ALIGNMENT 256u + +// Decode chunk sizes for the XMA_PLAYBACK_INIT.subframesToDecode field +#define XMA_MIN_SUBFRAMES_TO_DECODE 1u +#define XMA_MAX_SUBFRAMES_TO_DECODE 8u +#define XMA_OPTIMAL_SUBFRAMES_TO_DECODE 4u + +// LoopCount<255 means finite repetitions; LoopCount=255 means infinite looping +#define XMA_MAX_LOOPCOUNT 254u +#define XMA_INFINITE_LOOP 255u + + + +/*************************************************************************** + * XMA format structures + ***************************************************************************/ + +// The currently recommended way to express format information for XMA2 files +// is the XMA2WAVEFORMATEX structure. This structure is fully compliant with +// the WAVEFORMATEX standard and contains all the information needed to parse +// and manage XMA2 files in a compact way. + +#define WAVE_FORMAT_XMA2 0x166 + +typedef struct XMA2WAVEFORMATEX +{ + WAVEFORMATEX wfx; + // Meaning of the WAVEFORMATEX fields here: + // wFormatTag; // Audio format type; always WAVE_FORMAT_XMA2 + // nChannels; // Channel count of the decoded audio + // nSamplesPerSec; // Sample rate of the decoded audio + // nAvgBytesPerSec; // Used internally by the XMA encoder + // nBlockAlign; // Decoded sample size; channels * wBitsPerSample / 8 + // wBitsPerSample; // Bits per decoded mono sample; always 16 for XMA + // cbSize; // Size in bytes of the rest of this structure (34) + + WORD NumStreams; // Number of audio streams (1 or 2 channels each) + DWORD ChannelMask; // Spatial positions of the channels in this file, + // stored as SPEAKER_xxx values (see audiodefs.h) + DWORD SamplesEncoded; // Total number of PCM samples the file decodes to + DWORD BytesPerBlock; // XMA block size (but the last one may be shorter) + DWORD PlayBegin; // First valid sample in the decoded audio + DWORD PlayLength; // Length of the valid part of the decoded audio + DWORD LoopBegin; // Beginning of the loop region in decoded sample terms + DWORD LoopLength; // Length of the loop region in decoded sample terms + BYTE LoopCount; // Number of loop repetitions; 255 = infinite + BYTE EncoderVersion; // Version of XMA encoder that generated the file + WORD BlockCount; // XMA blocks in file (and entries in its seek table) +} XMA2WAVEFORMATEX, *PXMA2WAVEFORMATEX; + + +// The legacy XMA format structures are described here for reference, but they +// should not be used in new content. XMAWAVEFORMAT was the structure used in +// XMA version 1 files. XMA2WAVEFORMAT was used in early XMA2 files; it is not +// placed in the usual 'fmt' RIFF chunk but in its own 'XMA2' chunk. + +#ifndef WAVE_FORMAT_XMA +#define WAVE_FORMAT_XMA 0x0165 + +// Values used in the ChannelMask fields below. Similar to the SPEAKER_xxx +// values defined in audiodefs.h, but modified to fit in a single byte. +#ifndef XMA_SPEAKER_LEFT + #define XMA_SPEAKER_LEFT 0x01 + #define XMA_SPEAKER_RIGHT 0x02 + #define XMA_SPEAKER_CENTER 0x04 + #define XMA_SPEAKER_LFE 0x08 + #define XMA_SPEAKER_LEFT_SURROUND 0x10 + #define XMA_SPEAKER_RIGHT_SURROUND 0x20 + #define XMA_SPEAKER_LEFT_BACK 0x40 + #define XMA_SPEAKER_RIGHT_BACK 0x80 +#endif + + +// Used in XMAWAVEFORMAT for per-stream data +typedef struct XMASTREAMFORMAT +{ + DWORD PsuedoBytesPerSec; // Used by the XMA encoder (typo preserved for legacy reasons) + DWORD SampleRate; // The stream's decoded sample rate (in XMA2 files, + // this is the same for all streams in the file). + DWORD LoopStart; // Bit offset of the frame containing the loop start + // point, relative to the beginning of the stream. + DWORD LoopEnd; // Bit offset of the frame containing the loop end. + BYTE SubframeData; // Two 4-bit numbers specifying the exact location of + // the loop points within the frames that contain them. + // SubframeEnd: Subframe of the loop end frame where + // the loop ends. Ranges from 0 to 3. + // SubframeSkip: Subframes to skip in the start frame to + // reach the loop. Ranges from 0 to 4. + BYTE Channels; // Number of channels in the stream (1 or 2) + WORD ChannelMask; // Spatial positions of the channels in the stream +} XMASTREAMFORMAT; + +// Legacy XMA1 format structure +typedef struct XMAWAVEFORMAT +{ + WORD FormatTag; // Audio format type (always WAVE_FORMAT_XMA) + WORD BitsPerSample; // Bit depth (currently required to be 16) + WORD EncodeOptions; // Options for XMA encoder/decoder + WORD LargestSkip; // Largest skip used in interleaving streams + WORD NumStreams; // Number of interleaved audio streams + BYTE LoopCount; // Number of loop repetitions; 255 = infinite + BYTE Version; // XMA encoder version that generated the file. + // Always 3 or higher for XMA2 files. + XMASTREAMFORMAT XmaStreams[1]; // Per-stream format information; the actual + // array length is in the NumStreams field. +} XMAWAVEFORMAT; + + +// Used in XMA2WAVEFORMAT for per-stream data +typedef struct XMA2STREAMFORMAT +{ + BYTE Channels; // Number of channels in the stream (1 or 2) + BYTE RESERVED; // Reserved for future use + WORD ChannelMask; // Spatial positions of the channels in the stream +} XMA2STREAMFORMAT; + +// Legacy XMA2 format structure (big-endian byte ordering) +typedef struct XMA2WAVEFORMAT +{ + BYTE Version; // XMA encoder version that generated the file. + // Always 3 or higher for XMA2 files. + BYTE NumStreams; // Number of interleaved audio streams + BYTE RESERVED; // Reserved for future use + BYTE LoopCount; // Number of loop repetitions; 255 = infinite + DWORD LoopBegin; // Loop begin point, in samples + DWORD LoopEnd; // Loop end point, in samples + DWORD SampleRate; // The file's decoded sample rate + DWORD EncodeOptions; // Options for the XMA encoder/decoder + DWORD PsuedoBytesPerSec; // Used internally by the XMA encoder + DWORD BlockSizeInBytes; // Size in bytes of this file's XMA blocks (except + // possibly the last one). Always a multiple of + // 2Kb, since XMA blocks are arrays of 2Kb packets. + DWORD SamplesEncoded; // Total number of PCM samples encoded in this file + DWORD SamplesInSource; // Actual number of PCM samples in the source + // material used to generate this file + DWORD BlockCount; // Number of XMA blocks in this file (and hence + // also the number of entries in its seek table) + XMA2STREAMFORMAT Streams[1]; // Per-stream format information; the actual + // array length is in the NumStreams field. +} XMA2WAVEFORMAT; + +#endif // #ifndef WAVE_FORMAT_XMA + + + +/*************************************************************************** + * XMA packet structure (in big-endian form) + ***************************************************************************/ + +typedef struct XMA2PACKET +{ + int FrameCount : 6; // Number of XMA frames that begin in this packet + int FrameOffsetInBits : 15; // Bit of XmaData where the first complete frame begins + int PacketMetaData : 3; // Metadata stored in the packet (always 1 for XMA2) + int PacketSkipCount : 8; // How many packets belonging to other streams must be + // skipped to find the next packet belonging to this one + BYTE XmaData[XMA_BYTES_PER_PACKET - sizeof(DWORD)]; // XMA encoded data +} XMA2PACKET; + +// E.g. if the first DWORD of a packet is 0x30107902: +// +// 001100 000001000001111 001 00000010 +// | | | |____ Skip 2 packets to find the next one for this stream +// | | |___________ XMA2 signature (always 001) +// | |_____________________ First frame starts 527 bits into packet +// |________________________________ Packet contains 12 frames + + +// Helper functions to extract the fields above from an XMA packet. (Note that +// the bitfields cannot be read directly on little-endian architectures such as +// the Intel x86, as they are laid out in big-endian form.) + +__inline DWORD GetXmaPacketFrameCount(__in_bcount(1) const BYTE* pPacket) +{ + return (DWORD)(pPacket[0] >> 2); +} + +__inline DWORD GetXmaPacketFirstFrameOffsetInBits(__in_bcount(3) const BYTE* pPacket) +{ + return ((DWORD)(pPacket[0] & 0x3) << 13) | + ((DWORD)(pPacket[1]) << 5) | + ((DWORD)(pPacket[2]) >> 3); +} + +__inline DWORD GetXmaPacketMetadata(__in_bcount(3) const BYTE* pPacket) +{ + return (DWORD)(pPacket[2] & 0x7); +} + +__inline DWORD GetXmaPacketSkipCount(__in_bcount(4) const BYTE* pPacket) +{ + return (DWORD)(pPacket[3]); +} + + + +/*************************************************************************** + * XMA frame structure + ***************************************************************************/ + +// There is no way to represent the XMA frame as a C struct, since it is a +// variable-sized string of bits that need not be stored at a byte-aligned +// position in memory. This is the layout: +// +// XMAFRAME +// { +// LengthInBits: A 15-bit number representing the length of this frame. +// XmaData: Encoded XMA data; its size in bits is (LengthInBits - 15). +// } + +// Size in bits of the frame's initial LengthInBits field +#define XMA_BITS_IN_FRAME_LENGTH_FIELD 15 + +// Special LengthInBits value that marks an invalid final frame +#define XMA_FINAL_FRAME_MARKER 0x7FFF + + + +/*************************************************************************** + * XMA helper functions + ***************************************************************************/ + +// We define a local ASSERT macro to equal the global one if it exists. +// You can define XMA2DEFS_ASSERT in advance to override this default. +#ifndef XMA2DEFS_ASSERT + #ifdef ASSERT + #define XMA2DEFS_ASSERT ASSERT + #else + #define XMA2DEFS_ASSERT(a) /* No-op by default */ + #endif +#endif + + +// GetXmaBlockContainingSample: Use a given seek table to find the XMA block +// containing a given decoded sample. Note that the seek table entries in an +// XMA file are stored in big-endian form and may need to be converted prior +// to calling this function. + +__inline HRESULT GetXmaBlockContainingSample +( + DWORD nBlockCount, // Blocks in the file (= seek table entries) + __in_ecount(nBlockCount) const DWORD* pSeekTable, // Pointer to the seek table data + DWORD nDesiredSample, // Decoded sample to locate + __out DWORD* pnBlockContainingSample, // Index of the block containing the sample + __out DWORD* pnSampleOffsetWithinBlock // Position of the sample in this block +) +{ + DWORD nPreviousTotalSamples = 0; + DWORD nBlock; + DWORD nTotalSamplesSoFar; + + XMA2DEFS_ASSERT(pSeekTable); + XMA2DEFS_ASSERT(pnBlockContainingSample); + XMA2DEFS_ASSERT(pnSampleOffsetWithinBlock); + + for (nBlock = 0; nBlock < nBlockCount; ++nBlock) + { + nTotalSamplesSoFar = pSeekTable[nBlock]; + if (nTotalSamplesSoFar > nDesiredSample) + { + *pnBlockContainingSample = nBlock; + *pnSampleOffsetWithinBlock = nDesiredSample - nPreviousTotalSamples; + return S_OK; + } + nPreviousTotalSamples = nTotalSamplesSoFar; + } + + return E_FAIL; +} + + +// GetXmaFrameLengthInBits: Reads a given frame's LengthInBits field. + +__inline DWORD GetXmaFrameLengthInBits +( + __in_bcount(nBitPosition / 8 + 3) + __in const BYTE* pPacket, // Pointer to XMA packet[s] containing the frame + DWORD nBitPosition // Bit offset of the frame within this packet +) +{ + DWORD nRegion; + DWORD nBytePosition = nBitPosition / 8; + DWORD nBitOffset = nBitPosition % 8; + + if (nBitOffset < 2) // Only need to read 2 bytes (and might not be safe to read more) + { + nRegion = (DWORD)(pPacket[nBytePosition+0]) << 8 | + (DWORD)(pPacket[nBytePosition+1]); + return (nRegion >> (1 - nBitOffset)) & 0x7FFF; // Last 15 bits + } + else // Need to read 3 bytes + { + nRegion = (DWORD)(pPacket[nBytePosition+0]) << 16 | + (DWORD)(pPacket[nBytePosition+1]) << 8 | + (DWORD)(pPacket[nBytePosition+2]); + return (nRegion >> (9 - nBitOffset)) & 0x7FFF; // Last 15 bits + } +} + + +// GetXmaFrameBitPosition: Calculates the bit offset of a given frame within +// an XMA block or set of blocks. Returns 0 on failure. + +__inline DWORD GetXmaFrameBitPosition +( + __in_bcount(nXmaDataBytes) const BYTE* pXmaData, // Pointer to XMA block[s] + DWORD nXmaDataBytes, // Size of pXmaData in bytes + DWORD nStreamIndex, // Stream within which to seek + DWORD nDesiredFrame // Frame sought +) +{ + const BYTE* pCurrentPacket; + DWORD nPacketsExamined = 0; + DWORD nFrameCountSoFar = 0; + DWORD nFramesToSkip; + DWORD nFrameBitOffset; + + XMA2DEFS_ASSERT(pXmaData); + XMA2DEFS_ASSERT(nXmaDataBytes % XMA_BYTES_PER_PACKET == 0); + + // Get the first XMA packet belonging to the desired stream, relying on the + // fact that the first packets for each stream are in consecutive order at + // the beginning of an XMA block. + + pCurrentPacket = pXmaData + nStreamIndex * XMA_BYTES_PER_PACKET; + for (;;) + { + // If we have exceeded the size of the XMA data, return failure + if (pCurrentPacket + XMA_BYTES_PER_PACKET > pXmaData + nXmaDataBytes) + { + return 0; + } + + // If the current packet contains the frame we are looking for... + if (nFrameCountSoFar + GetXmaPacketFrameCount(pCurrentPacket) > nDesiredFrame) + { + // See how many frames in this packet we need to skip to get to it + XMA2DEFS_ASSERT(nDesiredFrame >= nFrameCountSoFar); + nFramesToSkip = nDesiredFrame - nFrameCountSoFar; + + // Get the bit offset of the first frame in this packet + nFrameBitOffset = XMA_PACKET_HEADER_BITS + GetXmaPacketFirstFrameOffsetInBits(pCurrentPacket); + + // Advance nFrameBitOffset to the frame of interest + while (nFramesToSkip--) + { + nFrameBitOffset += GetXmaFrameLengthInBits(pCurrentPacket, nFrameBitOffset); + } + + // The bit offset to return is the number of bits from pXmaData to + // pCurrentPacket plus the bit offset of the frame of interest + return (DWORD)(pCurrentPacket - pXmaData) * 8 + nFrameBitOffset; + } + + // If we haven't found the right packet yet, advance our counters + ++nPacketsExamined; + nFrameCountSoFar += GetXmaPacketFrameCount(pCurrentPacket); + + // And skip to the next packet belonging to the same stream + pCurrentPacket += XMA_BYTES_PER_PACKET * (GetXmaPacketSkipCount(pCurrentPacket) + 1); + } +} + + +// GetLastXmaFrameBitPosition: Calculates the bit offset of the last complete +// frame in an XMA block or set of blocks. + +__inline DWORD GetLastXmaFrameBitPosition +( + __in_bcount(nXmaDataBytes) const BYTE* pXmaData, // Pointer to XMA block[s] + DWORD nXmaDataBytes, // Size of pXmaData in bytes + DWORD nStreamIndex // Stream within which to seek +) +{ + const BYTE* pLastPacket; + DWORD nBytesToNextPacket; + DWORD nFrameBitOffset; + DWORD nFramesInLastPacket; + + XMA2DEFS_ASSERT(pXmaData); + XMA2DEFS_ASSERT(nXmaDataBytes % XMA_BYTES_PER_PACKET == 0); + XMA2DEFS_ASSERT(nXmaDataBytes >= XMA_BYTES_PER_PACKET * (nStreamIndex + 1)); + + // Get the first XMA packet belonging to the desired stream, relying on the + // fact that the first packets for each stream are in consecutive order at + // the beginning of an XMA block. + pLastPacket = pXmaData + nStreamIndex * XMA_BYTES_PER_PACKET; + + // Search for the last packet belonging to the desired stream + for (;;) + { + nBytesToNextPacket = XMA_BYTES_PER_PACKET * (GetXmaPacketSkipCount(pLastPacket) + 1); + XMA2DEFS_ASSERT(nBytesToNextPacket); + if (pLastPacket + nBytesToNextPacket + XMA_BYTES_PER_PACKET > pXmaData + nXmaDataBytes) + { + break; // The next packet would extend beyond the end of pXmaData + } + pLastPacket += nBytesToNextPacket; + } + + // The last packet can sometimes have no seekable frames, in which case we + // have to use the previous one + if (GetXmaPacketFrameCount(pLastPacket) == 0) + { + pLastPacket -= nBytesToNextPacket; + } + + // Found the last packet. Get the bit offset of its first frame. + nFrameBitOffset = XMA_PACKET_HEADER_BITS + GetXmaPacketFirstFrameOffsetInBits(pLastPacket); + + // Traverse frames until we reach the last one + nFramesInLastPacket = GetXmaPacketFrameCount(pLastPacket); + while (--nFramesInLastPacket) + { + nFrameBitOffset += GetXmaFrameLengthInBits(pLastPacket, nFrameBitOffset); + } + + // The bit offset to return is the number of bits from pXmaData to + // pLastPacket plus the offset of the last frame in this packet. + return (DWORD)(pLastPacket - pXmaData) * 8 + nFrameBitOffset; +} + + +// GetXmaDecodePositionForSample: Obtains the information needed to make the +// decoder generate audio starting at a given sample position relative to the +// beginning of the given XMA block: the bit offset of the appropriate frame, +// and the right subframe within that frame. This data can be passed directly +// to the XMAPlaybackSetDecodePosition function. + +__inline HRESULT GetXmaDecodePositionForSample +( + __in_bcount(nXmaDataBytes) const BYTE* pXmaData, // Pointer to XMA block[s] + DWORD nXmaDataBytes, // Size of pXmaData in bytes + DWORD nStreamIndex, // Stream within which to seek + DWORD nDesiredSample, // Sample sought + __out DWORD* pnBitOffset, // Returns the bit offset within pXmaData of + // the frame containing the sample sought + __out DWORD* pnSubFrame // Returns the subframe containing the sample +) +{ + DWORD nDesiredFrame = nDesiredSample / XMA_SAMPLES_PER_FRAME; + DWORD nSubFrame = (nDesiredSample % XMA_SAMPLES_PER_FRAME) / XMA_SAMPLES_PER_SUBFRAME; + DWORD nBitOffset = GetXmaFrameBitPosition(pXmaData, nXmaDataBytes, nStreamIndex, nDesiredFrame); + + XMA2DEFS_ASSERT(pnBitOffset); + XMA2DEFS_ASSERT(pnSubFrame); + + if (nBitOffset) + { + *pnBitOffset = nBitOffset; + *pnSubFrame = nSubFrame; + return S_OK; + } + else + { + return E_FAIL; + } +} + + +// GetXmaSampleRate: Obtains the legal XMA sample rate (24, 32, 44.1 or 48Khz) +// corresponding to a generic sample rate. + +__inline DWORD GetXmaSampleRate(DWORD dwGeneralRate) +{ + DWORD dwXmaRate = 48000; // Default XMA rate for all rates above 44100Hz + + if (dwGeneralRate <= 24000) dwXmaRate = 24000; + else if (dwGeneralRate <= 32000) dwXmaRate = 32000; + else if (dwGeneralRate <= 44100) dwXmaRate = 44100; + + return dwXmaRate; +} + + +// Functions to convert between WAVEFORMATEXTENSIBLE channel masks (combinations +// of the SPEAKER_xxx flags defined in audiodefs.h) and XMA channel masks (which +// are limited to eight possible speaker positions: left, right, center, low +// frequency, side left, side right, back left and back right). + +__inline DWORD GetStandardChannelMaskFromXmaMask(BYTE bXmaMask) +{ + DWORD dwStandardMask = 0; + + if (bXmaMask & XMA_SPEAKER_LEFT) dwStandardMask |= SPEAKER_FRONT_LEFT; + if (bXmaMask & XMA_SPEAKER_RIGHT) dwStandardMask |= SPEAKER_FRONT_RIGHT; + if (bXmaMask & XMA_SPEAKER_CENTER) dwStandardMask |= SPEAKER_FRONT_CENTER; + if (bXmaMask & XMA_SPEAKER_LFE) dwStandardMask |= SPEAKER_LOW_FREQUENCY; + if (bXmaMask & XMA_SPEAKER_LEFT_SURROUND) dwStandardMask |= SPEAKER_SIDE_LEFT; + if (bXmaMask & XMA_SPEAKER_RIGHT_SURROUND) dwStandardMask |= SPEAKER_SIDE_RIGHT; + if (bXmaMask & XMA_SPEAKER_LEFT_BACK) dwStandardMask |= SPEAKER_BACK_LEFT; + if (bXmaMask & XMA_SPEAKER_RIGHT_BACK) dwStandardMask |= SPEAKER_BACK_RIGHT; + + return dwStandardMask; +} + +__inline BYTE GetXmaChannelMaskFromStandardMask(DWORD dwStandardMask) +{ + BYTE bXmaMask = 0; + + if (dwStandardMask & SPEAKER_FRONT_LEFT) bXmaMask |= XMA_SPEAKER_LEFT; + if (dwStandardMask & SPEAKER_FRONT_RIGHT) bXmaMask |= XMA_SPEAKER_RIGHT; + if (dwStandardMask & SPEAKER_FRONT_CENTER) bXmaMask |= XMA_SPEAKER_CENTER; + if (dwStandardMask & SPEAKER_LOW_FREQUENCY) bXmaMask |= XMA_SPEAKER_LFE; + if (dwStandardMask & SPEAKER_SIDE_LEFT) bXmaMask |= XMA_SPEAKER_LEFT_SURROUND; + if (dwStandardMask & SPEAKER_SIDE_RIGHT) bXmaMask |= XMA_SPEAKER_RIGHT_SURROUND; + if (dwStandardMask & SPEAKER_BACK_LEFT) bXmaMask |= XMA_SPEAKER_LEFT_BACK; + if (dwStandardMask & SPEAKER_BACK_RIGHT) bXmaMask |= XMA_SPEAKER_RIGHT_BACK; + + return bXmaMask; +} + + +// LocalizeXma2Format: Modifies a XMA2WAVEFORMATEX structure in place to comply +// with the current platform's byte-ordering rules (little- or big-endian). + +__inline HRESULT LocalizeXma2Format(__inout XMA2WAVEFORMATEX* pXma2Format) +{ + #define XMASWAP2BYTES(n) ((WORD)(((n) >> 8) | (((n) & 0xff) << 8))) + #define XMASWAP4BYTES(n) ((DWORD)((n) >> 24 | (n) << 24 | ((n) & 0xff00) << 8 | ((n) & 0xff0000) >> 8)) + + if (pXma2Format->wfx.wFormatTag == WAVE_FORMAT_XMA2) + { + return S_OK; + } + else if (XMASWAP2BYTES(pXma2Format->wfx.wFormatTag) == WAVE_FORMAT_XMA2) + { + pXma2Format->wfx.wFormatTag = XMASWAP2BYTES(pXma2Format->wfx.wFormatTag); + pXma2Format->wfx.nChannels = XMASWAP2BYTES(pXma2Format->wfx.nChannels); + pXma2Format->wfx.nSamplesPerSec = XMASWAP4BYTES(pXma2Format->wfx.nSamplesPerSec); + pXma2Format->wfx.nAvgBytesPerSec = XMASWAP4BYTES(pXma2Format->wfx.nAvgBytesPerSec); + pXma2Format->wfx.nBlockAlign = XMASWAP2BYTES(pXma2Format->wfx.nBlockAlign); + pXma2Format->wfx.wBitsPerSample = XMASWAP2BYTES(pXma2Format->wfx.wBitsPerSample); + pXma2Format->wfx.cbSize = XMASWAP2BYTES(pXma2Format->wfx.cbSize); + pXma2Format->NumStreams = XMASWAP2BYTES(pXma2Format->NumStreams); + pXma2Format->ChannelMask = XMASWAP4BYTES(pXma2Format->ChannelMask); + pXma2Format->SamplesEncoded = XMASWAP4BYTES(pXma2Format->SamplesEncoded); + pXma2Format->BytesPerBlock = XMASWAP4BYTES(pXma2Format->BytesPerBlock); + pXma2Format->PlayBegin = XMASWAP4BYTES(pXma2Format->PlayBegin); + pXma2Format->PlayLength = XMASWAP4BYTES(pXma2Format->PlayLength); + pXma2Format->LoopBegin = XMASWAP4BYTES(pXma2Format->LoopBegin); + pXma2Format->LoopLength = XMASWAP4BYTES(pXma2Format->LoopLength); + pXma2Format->BlockCount = XMASWAP2BYTES(pXma2Format->BlockCount); + return S_OK; + } + else + { + return E_FAIL; // Not a recognizable XMA2 format + } + + #undef XMASWAP2BYTES + #undef XMASWAP4BYTES +} + + +#endif // #ifndef __XMA2DEFS_INCLUDED__ diff --git a/sfpacker/maindlg.h b/sfpacker/maindlg.h index 791d785..71ac749 100644 --- a/sfpacker/maindlg.h +++ b/sfpacker/maindlg.h @@ -20,8 +20,8 @@ #define BASSMIDIDEF(f) (WINAPI *f) #define LOADBASSFUNCTION(f) *((void**)&f)=GetProcAddress(bass,#f) #define LOADBASSMIDIFUNCTION(f) *((void**)&f)=GetProcAddress(bassmidi,#f) -#include "../bass.h" -#include "../bassmidi.h" +#include "../external_packages/bass.h" +#include "../external_packages/bassmidi.h" using namespace std; using namespace utf8util;