mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-11-24 19:52:30 +01:00
WaveMix v3.
This commit is contained in:
parent
10af864767
commit
2945069de0
Binary file not shown.
@ -143,16 +143,6 @@ void Sound::Close()
|
||||
}
|
||||
}
|
||||
|
||||
int Sound::SubFactor(int a1, int a2)
|
||||
{
|
||||
return a1 - a2;
|
||||
}
|
||||
|
||||
int Sound::AddFactor(int a1, int a2)
|
||||
{
|
||||
return a1 + a2;
|
||||
}
|
||||
|
||||
void Sound::PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, __int16 loops)
|
||||
{
|
||||
MIXPLAYPARAMS mixParams{};
|
||||
|
@ -10,8 +10,6 @@ public:
|
||||
static void Activate();
|
||||
static void Deactivate();
|
||||
static void Close();
|
||||
static int SubFactor(int a1, int a2);
|
||||
static int AddFactor(int a1, int a2);
|
||||
static void PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, __int16 loops);
|
||||
static MIXWAVE* LoadWaveFile(LPCSTR lpName);
|
||||
static void FreeSound(MIXWAVE* wave);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "pch.h"
|
||||
#include "WaveMix.h"
|
||||
|
||||
#include "pinball.h"
|
||||
|
||||
int WaveMix::initialized_flag;
|
||||
char WaveMix::FileName[276];
|
||||
CHANNELNODE WaveMix::channel_nodes[MAXQUEUEDWAVES];
|
||||
@ -163,6 +165,42 @@ int WaveMix::FreeWave(HANDLE hMixSession, MIXWAVE* lpMixWave)
|
||||
|
||||
int WaveMix::Activate(HANDLE hMixSession, bool fActivate)
|
||||
{
|
||||
GLOBALS* globals = SessionToGlobalDataPtr(hMixSession);
|
||||
Globals = globals;
|
||||
if (!globals)
|
||||
return 5;
|
||||
if (fActivate)
|
||||
{
|
||||
if (GlobalsActive)
|
||||
return GlobalsActive != globals ? 4 : 0;
|
||||
if (globals->SettingsDialogActiveFlag)
|
||||
return 12;
|
||||
GlobalsActive = globals;
|
||||
sndPlaySoundA(nullptr, 0);
|
||||
auto result = GetWaveDevice();
|
||||
if (result)
|
||||
{
|
||||
GlobalsActive = nullptr;
|
||||
return result;
|
||||
}
|
||||
Globals->fActive = 1;
|
||||
SetWaveOutPosition(Globals->dwCurrentSample);
|
||||
XWAVEHDR* xHDR;
|
||||
do
|
||||
xHDR = GetWaveBlock();
|
||||
while (MixerPlay(xHDR, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (globals->fActive)
|
||||
{
|
||||
Globals->dwCurrentSample = MyWaveOutGetPosition(globals->hWaveOut, globals->fGoodGetPos);
|
||||
}
|
||||
ReleaseWaveDevice(globals);
|
||||
Globals->fActive = 0;
|
||||
if (Globals == GlobalsActive)
|
||||
GlobalsActive = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -324,6 +362,108 @@ int WaveMix::ReadConfigSettings(MIXCONFIG* lpConfig)
|
||||
return 1;
|
||||
}
|
||||
|
||||
UINT deviceId;
|
||||
if (static_cast<char>(lpConfig->dwFlags) >= 0)
|
||||
{
|
||||
deviceId = GetPrivateProfileIntA("general", "WaveOutDevice", 0, FileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceId = lpConfig->wDeviceID;
|
||||
}
|
||||
Globals->wDeviceID = deviceId;
|
||||
if (Globals->wDeviceID >= waveDeviceCount)
|
||||
Globals->wDeviceID = 0;
|
||||
|
||||
if (waveOutGetDevCapsA(Globals->wDeviceID, &Globals->WaveoutCaps, 0x34u)
|
||||
|| !RemoveInvalidIniNameCharacters(Globals->WaveoutCaps.szPname))
|
||||
{
|
||||
lstrcpyA(Globals->WaveoutCaps.szPname, "Unkown Device");
|
||||
}
|
||||
|
||||
if (!ReadRegistryToGetMachineSpecificInfSection(Globals->wDeviceID, Globals->szDevicePName, 96))
|
||||
{
|
||||
lstrcpyA(Globals->szDevicePName, GetOperatingSystemPrefix());
|
||||
lstrcatA(Globals->szDevicePName, Globals->WaveoutCaps.szPname);
|
||||
}
|
||||
|
||||
auto remix = GetPrivateProfileIntA("default", "Remix", 1, FileName);
|
||||
auto goodWavePos = GetPrivateProfileIntA("default", "GoodWavePos", DefaultGoodWavePos(Globals->wDeviceID),
|
||||
FileName);
|
||||
auto waveBlocks = GetPrivateProfileIntA("default", "WaveBlocks", 3, FileName);
|
||||
auto samplesPerSec = GetPrivateProfileIntA("default", "SamplesPerSec", 11, FileName);
|
||||
if ((Globals->WaveoutCaps.dwSupport & 0x10) != 0)
|
||||
{
|
||||
if (!ShowDebugDialogs)
|
||||
return 0;
|
||||
wsprintfA(string_buffer,
|
||||
"%s is a syncronous (blocking) wave output device. This will not permit audio to play while other applications are running.",
|
||||
Globals->WaveoutCaps.szPname);
|
||||
MessageBoxA(nullptr, string_buffer, "WavMix32", 0x40u);
|
||||
return 0;
|
||||
}
|
||||
if (GetPrivateProfileIntA("not compatible", Globals->szDevicePName, 0, FileName))
|
||||
{
|
||||
if (!ShowDebugDialogs)
|
||||
return 0;
|
||||
wsprintfA(string_buffer, "%s is not compatible with the realtime wavemixer.", Globals->szDevicePName);
|
||||
MessageBoxA(nullptr, string_buffer, "WavMix32", 0x40u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Globals->pfnRemix = GetPrivateProfileIntA(Globals->szDevicePName, "Remix", remix, FileName) != 2
|
||||
? ResetRemix
|
||||
: NoResetRemix;
|
||||
Globals->fGoodGetPos = GetPrivateProfileIntA(Globals->szDevicePName, "GoodWavePos", goodWavePos, FileName) != 0;
|
||||
Globals->WaveBlockCount = GetPrivateProfileIntA(Globals->szDevicePName, "WaveBlocks", waveBlocks, FileName);
|
||||
if (Globals->WaveBlockCount < 2)
|
||||
Globals->WaveBlockCount = 2;
|
||||
else if (Globals->WaveBlockCount > 10)
|
||||
Globals->WaveBlockCount = 10;
|
||||
|
||||
Globals->PauseBlocks = GetPrivateProfileIntA(Globals->szDevicePName, "PauseBlocks",
|
||||
DefaultPauseBlocks(Globals->WaveBlockCount), FileName);
|
||||
if (Globals->PauseBlocks >= 0)
|
||||
{
|
||||
if (Globals->PauseBlocks > Globals->WaveBlockCount)
|
||||
Globals->PauseBlocks = Globals->WaveBlockCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
Globals->PauseBlocks = 0;
|
||||
}
|
||||
|
||||
auto samplesPerSec2 = GetPrivateProfileIntA(Globals->szDevicePName, "SamplesPerSec", samplesPerSec, FileName);
|
||||
auto channels = GetPrivateProfileIntA(Globals->szDevicePName, "Channels", 1, FileName);
|
||||
Globals->PCM.wf.nChannels = channels;
|
||||
if (channels)
|
||||
{
|
||||
if (channels > 2u)
|
||||
Globals->PCM.wf.nChannels = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Globals->PCM.wf.nChannels = 1;
|
||||
}
|
||||
DWORD nAvgBytesPerSec;
|
||||
if (samplesPerSec2 == 22)
|
||||
{
|
||||
Globals->PCM.wf.nSamplesPerSec = 22050;
|
||||
nAvgBytesPerSec = 22050 * Globals->PCM.wf.nChannels;
|
||||
}
|
||||
else if (samplesPerSec2 == 44)
|
||||
{
|
||||
Globals->PCM.wf.nSamplesPerSec = 44100;
|
||||
nAvgBytesPerSec = 44100 * Globals->PCM.wf.nChannels;
|
||||
}
|
||||
else
|
||||
{
|
||||
nAvgBytesPerSec = 11025 * Globals->PCM.wf.nChannels;
|
||||
}
|
||||
Globals->PCM.wf.nAvgBytesPerSec = nAvgBytesPerSec;
|
||||
auto waveBlockLen2 = GetPrivateProfileIntA("default", "WaveBlockLen", 0, FileName);
|
||||
Globals->dwWaveBlockLen = FigureOutDMABufferSize(waveBlockLen2, &Globals->PCM);
|
||||
Configure(Globals, nullptr, lpConfig, nullptr, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -421,20 +561,18 @@ int WaveMix::DefaultPauseBlocks(int waveBlocks)
|
||||
|
||||
int WaveMix::Configure(GLOBALS* hMixSession, HWND hWndParent, MIXCONFIG* lpConfig, int* flag1Ptr, int saveConfigFlag)
|
||||
{
|
||||
MIXCONFIG mixConfigLocal;
|
||||
MIXCONFIG mixConfigLocal{};
|
||||
tagWAVEOUTCAPSA pwoc{};
|
||||
|
||||
auto hMixSession2 = hMixSession;
|
||||
auto mixConfig = lpConfig;
|
||||
auto hMixSession3 = hMixSession;
|
||||
auto flag1Ptr_2 = flag1Ptr;
|
||||
auto someFlag1 = 0;
|
||||
auto globals1 = SessionToGlobalDataPtr(hMixSession);
|
||||
Globals = globals1;
|
||||
if (!globals1)
|
||||
auto globals = SessionToGlobalDataPtr(hMixSession);
|
||||
Globals = globals;
|
||||
if (!globals)
|
||||
return 5;
|
||||
if (globals1->fActive)
|
||||
if (globals->fActive)
|
||||
return 4;
|
||||
if (globals1->SettingsDialogActiveFlag)
|
||||
if (globals->SettingsDialogActiveFlag)
|
||||
return 12;
|
||||
FlushChannel(hMixSession, -1, 1u);
|
||||
|
||||
@ -443,9 +581,169 @@ int WaveMix::Configure(GLOBALS* hMixSession, HWND hWndParent, MIXCONFIG* lpConfi
|
||||
mixConfigLocal.wSize = 30;
|
||||
mixConfigLocal.dwFlags = 1023;
|
||||
GetConfig(static_cast<GLOBALS*>(hMixSession), &mixConfigLocal);
|
||||
auto dialog = MakeSettingsDlgTemplate();
|
||||
if (!dialog)
|
||||
return 1;
|
||||
Globals->SettingsDialogActiveFlag = 1;
|
||||
auto dlgResult = DialogBoxIndirectParamA(HModule, &dialog->Dialog, hWndParent, SettingsDlgProc,
|
||||
(LPARAM)&mixConfigLocal);
|
||||
DestroySettingsDlgTemplate(dialog);
|
||||
Globals->SettingsDialogActiveFlag = 0;
|
||||
if (dlgResult != 1)
|
||||
return 1;
|
||||
if (Globals->dwWaveBlockLen == mixConfigLocal.WaveBlockLen)
|
||||
mixConfigLocal.dwFlags &= 0xFFFFFFF7;
|
||||
|
||||
mixConfig = &mixConfigLocal;
|
||||
}
|
||||
if (!mixConfig->dwFlags)
|
||||
return 1;
|
||||
|
||||
globals = SessionToGlobalDataPtr(hMixSession);
|
||||
Globals = globals;
|
||||
if (!globals)
|
||||
return 5;
|
||||
|
||||
auto dwFlags = mixConfig->dwFlags;
|
||||
if ((dwFlags & 0x100) != 0)
|
||||
ShowDebugDialogs = mixConfig->ShowDebugDialogs != 0;
|
||||
if ((dwFlags & 0x80u) != 0)
|
||||
{
|
||||
if (mixConfig->wDeviceID != globals->wDeviceID)
|
||||
{
|
||||
auto result = waveOutGetDevCapsA(mixConfig->wDeviceID, &pwoc, 0x34u);
|
||||
if (result)
|
||||
return result;
|
||||
memcpy(&Globals->WaveoutCaps, &pwoc, sizeof Globals->WaveoutCaps);
|
||||
Globals->wDeviceID = mixConfig->wDeviceID;
|
||||
if (Globals->WaveoutCaps.wChannels == 1 && Globals->PCM.wf.nChannels == 2)
|
||||
{
|
||||
Globals->PCM.wf.nChannels = 1;
|
||||
someFlag1 = 1;
|
||||
Globals->PCM.wf.nBlockAlign = 1;
|
||||
Globals->PCM.wf.nAvgBytesPerSec = Globals->PCM.wf.nSamplesPerSec;
|
||||
}
|
||||
lstrcpyA(globals->szDevicePName, pwoc.szPname);
|
||||
if (!RemoveInvalidIniNameCharacters(Globals->szDevicePName))
|
||||
lstrcpyA(Globals->szDevicePName, "Unkown Device");
|
||||
if (!ReadRegistryToGetMachineSpecificInfSection(Globals->wDeviceID, Globals->szDevicePName, 96))
|
||||
{
|
||||
lstrcpyA(Globals->szDevicePName, GetOperatingSystemPrefix());
|
||||
lstrcatA(Globals->szDevicePName, Globals->WaveoutCaps.szPname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
if ((dwFlags & 1) != 0)
|
||||
{
|
||||
if (mixConfig->wChannels <= 1u)
|
||||
{
|
||||
if (globals->PCM.wf.nChannels == 2)
|
||||
someFlag1 = 1;
|
||||
globals->PCM.wf.nChannels = 1;
|
||||
globals->PCM.wf.nBlockAlign = 1;
|
||||
globals->PCM.wf.nAvgBytesPerSec = globals->PCM.wf.nSamplesPerSec;
|
||||
}
|
||||
if (globals->WaveoutCaps.wChannels > 1u)
|
||||
{
|
||||
if (globals->PCM.wf.nChannels == 1)
|
||||
someFlag1 = 1;
|
||||
globals->PCM.wf.nChannels = 2;
|
||||
globals->PCM.wf.nBlockAlign = 2;
|
||||
globals->PCM.wf.nAvgBytesPerSec = 2 * globals->PCM.wf.nSamplesPerSec;
|
||||
}
|
||||
}
|
||||
|
||||
if ((dwFlags & 2) != 0)
|
||||
{
|
||||
auto nAvgBytesPerSec = 0u;
|
||||
if (mixConfig->wSamplingRate == 22)
|
||||
{
|
||||
if (globals->PCM.wf.nSamplesPerSec != 22050)
|
||||
someFlag1 = 1;
|
||||
globals->PCM.wf.nSamplesPerSec = 22050;
|
||||
nAvgBytesPerSec = 22050 * globals->PCM.wf.nChannels;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mixConfig->wSamplingRate == 44)
|
||||
{
|
||||
if (globals->PCM.wf.nSamplesPerSec != 44100)
|
||||
someFlag1 = 1;
|
||||
globals->PCM.wf.nSamplesPerSec = 44100;
|
||||
nAvgBytesPerSec = 44100 * globals->PCM.wf.nChannels;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (globals->PCM.wf.nSamplesPerSec != 11025)
|
||||
someFlag1 = 1;
|
||||
globals->PCM.wf.nSamplesPerSec = 11025;
|
||||
nAvgBytesPerSec = 11025 * globals->PCM.wf.nChannels;
|
||||
}
|
||||
}
|
||||
globals->PCM.wf.nAvgBytesPerSec = nAvgBytesPerSec;
|
||||
}
|
||||
|
||||
if ((dwFlags & 4) != 0)
|
||||
{
|
||||
auto v24 = 2;
|
||||
globals->WaveBlockCount = mixConfig->WaveBlockCount;
|
||||
if (mixConfig->WaveBlockCount < 2)
|
||||
globals->WaveBlockCount = 2;
|
||||
else if (mixConfig->WaveBlockCount > 10)
|
||||
globals->WaveBlockCount = 10;
|
||||
if (globals->PauseBlocks >= 0)
|
||||
{
|
||||
if (globals->PauseBlocks > globals->WaveBlockCount)
|
||||
globals->PauseBlocks = globals->WaveBlockCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
globals->PauseBlocks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (someFlag1)
|
||||
globals->dwWaveBlockLen = FigureOutDMABufferSize(0, &globals->PCM);
|
||||
|
||||
if ((dwFlags & 8) != 0)
|
||||
{
|
||||
if (mixConfig->WaveBlockLen)
|
||||
globals->dwWaveBlockLen = mixConfig->WaveBlockLen;
|
||||
}
|
||||
|
||||
if (globals->dwWaveBlockLen < 344)
|
||||
globals->dwWaveBlockLen = 344;
|
||||
else if (globals->dwWaveBlockLen > 11025)
|
||||
globals->dwWaveBlockLen = 11025;
|
||||
|
||||
auto dwFlags2 = dwFlags;
|
||||
if ((dwFlags & 0x10) != 0)
|
||||
globals->CmixPtr = cmixit;
|
||||
|
||||
if ((dwFlags2 & 0x20) != 0)
|
||||
{
|
||||
globals->pfnRemix = !mixConfig->ResetMixDefaultFlag ? NoResetRemix : ResetRemix;
|
||||
}
|
||||
|
||||
if ((dwFlags2 & 0x40) != 0)
|
||||
globals->fGoodGetPos = mixConfig->GoodWavePos != 0;
|
||||
|
||||
if ((dwFlags2 & 0x200) != 0)
|
||||
{
|
||||
globals->PauseBlocks = mixConfig->PauseBlocks;
|
||||
if (mixConfig->PauseBlocks > globals->WaveBlockCount)
|
||||
globals->PauseBlocks = globals->WaveBlockCount;
|
||||
}
|
||||
|
||||
GetConfig(hMixSession, mixConfig);
|
||||
if (flag1Ptr)
|
||||
*flag1Ptr = someFlag1;
|
||||
if (saveConfigFlag)
|
||||
SaveConfigSettings(dwFlags);
|
||||
if (ShowDebugDialogs)
|
||||
ShowCurrentSettings();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WaveMix::GetConfig(HANDLE hMixSession, MIXCONFIG* lpConfig)
|
||||
@ -461,11 +759,11 @@ int WaveMix::GetConfig(HANDLE hMixSession, MIXCONFIG* lpConfig)
|
||||
if ((dwFlags & 1) != 0)
|
||||
lpConfig->wChannels = globals->PCM.wf.nChannels;
|
||||
if ((dwFlags & 2) != 0)
|
||||
lpConfig->wSamplingRate = 11 * (globals->PCM.wf.nSamplesPerSec / 0x2B11);
|
||||
lpConfig->wSamplingRate = static_cast<WORD>(11 * (globals->PCM.wf.nSamplesPerSec / 0x2B11));
|
||||
if ((dwFlags & 4) != 0)
|
||||
lpConfig->WaveBlockCount = globals->WaveBlockCount;
|
||||
if ((dwFlags & 8) != 0)
|
||||
lpConfig->WaveBlockLen = globals->WaveBlockLen;
|
||||
lpConfig->WaveBlockLen = static_cast<WORD>(globals->dwWaveBlockLen);
|
||||
if ((dwFlags & 0x10) != 0)
|
||||
lpConfig->CmixPtrDefaultFlag = globals->CmixPtr == cmixit;
|
||||
if ((dwFlags & 0x20) != 0)
|
||||
@ -481,14 +779,14 @@ int WaveMix::GetConfig(HANDLE hMixSession, MIXCONFIG* lpConfig)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned WaveMix::MyWaveOutGetPosition(HWAVEOUT hwo, int fGoodGetPos)
|
||||
unsigned WaveMix::MyWaveOutGetPosition(HWAVEOUT hWaveOut, int fGoodGetPos)
|
||||
{
|
||||
mmtime_tag pmmt{};
|
||||
|
||||
if (!fGoodGetPos)
|
||||
return (timeGetTime() - Globals->dwBaseTime) * Globals->PCM.wf.nAvgBytesPerSec / 0x3E8 & 0xFFFFFFF8;
|
||||
pmmt.wType = 4;
|
||||
waveOutGetPosition(hwo, &pmmt, 0xCu);
|
||||
pmmt.wType = TIME_BYTES;
|
||||
waveOutGetPosition(hWaveOut, &pmmt, 0xCu);
|
||||
return Globals->pfnSampleAdjust(pmmt.u.ms, Globals->dwWaveOutPos);
|
||||
}
|
||||
|
||||
@ -520,6 +818,37 @@ int WaveMix::ResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel)
|
||||
AddToPlayingQueue(block);
|
||||
}
|
||||
|
||||
auto dwCurrentSamplePrev = Globals->dwCurrentSample;
|
||||
MyWaveOutReset(Globals->hWaveOut);
|
||||
Globals->dwCurrentSample = dwCurrentSamplePrev;
|
||||
auto pauseFlag = 0;
|
||||
if (Globals->PauseBlocks > 0)
|
||||
{
|
||||
waveOutPause(Globals->hWaveOut);
|
||||
pauseFlag = 1;
|
||||
}
|
||||
|
||||
auto pauseCount = 0;
|
||||
for (auto xHDR = play_queue.first; xHDR; xHDR = xHDR->QNext)
|
||||
{
|
||||
if (waveOutWrite(Globals->hWaveOut, &xHDR->wh, sizeof(WAVEHDR)))
|
||||
{
|
||||
if (ShowDebugDialogs)
|
||||
MessageBoxA(nullptr, "Failed to write block to device", "WavMix32", 0x30u);
|
||||
xHDR->fAvailable = 1;
|
||||
RemoveFromPlayingQueue(xHDR);
|
||||
}
|
||||
if (pauseFlag)
|
||||
{
|
||||
if (++pauseCount >= Globals->PauseBlocks)
|
||||
{
|
||||
waveOutRestart(Globals->hWaveOut);
|
||||
pauseFlag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pauseFlag)
|
||||
waveOutRestart(Globals->hWaveOut);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -585,7 +914,7 @@ XWAVEHDR* WaveMix::GetWaveBlock()
|
||||
|
||||
XWAVEHDR* result = Globals->WaveBlockArray[index];
|
||||
result->fAvailable = 0;
|
||||
result->wh.dwBufferLength = Globals->WaveBlockLen;
|
||||
result->wh.dwBufferLength = Globals->dwWaveBlockLen;
|
||||
result->wh.lpData = reinterpret_cast<LPSTR>(&result[1]);
|
||||
result->g = GlobalsActive;
|
||||
return result;
|
||||
@ -629,7 +958,7 @@ int WaveMix::MixerPlay(XWAVEHDR* lpXWH, int fWriteBlocks)
|
||||
|
||||
auto currentSample = Globals->dwCurrentSample;
|
||||
auto dataPtr = reinterpret_cast<unsigned char*>(lpXWH->wh.lpData);
|
||||
auto waveBlockLen = Globals->WaveBlockLen;
|
||||
auto waveBlockLen = Globals->dwWaveBlockLen;
|
||||
while (waveBlockLen)
|
||||
{
|
||||
if (currentSample >= minStartPos)
|
||||
@ -666,7 +995,7 @@ int WaveMix::MixerPlay(XWAVEHDR* lpXWH, int fWriteBlocks)
|
||||
if (waveCount)
|
||||
{
|
||||
auto dataLength = endBlockPosition - currentSample;
|
||||
Globals->CmixPtr(dataPtr, play_data, play_volume, waveCount, dataLength);
|
||||
Globals->CmixPtr(dataPtr, play_data, play_volume, waveCount, static_cast<WORD>(dataLength));
|
||||
|
||||
dataPtr += dataLength;
|
||||
waveBlockLen -= dataLength;
|
||||
@ -713,11 +1042,11 @@ int WaveMix::MixerPlay(XWAVEHDR* lpXWH, int fWriteBlocks)
|
||||
}
|
||||
|
||||
lpXWH->dwWavePos = Globals->dwCurrentSample;
|
||||
Globals->dwCurrentSample += Globals->WaveBlockLen;
|
||||
Globals->dwCurrentSample += Globals->dwWaveBlockLen;
|
||||
if (fWriteBlocks)
|
||||
{
|
||||
AddToPlayingQueue(lpXWH);
|
||||
if (waveOutWrite(Globals->hWaveOut, &lpXWH->wh, 0x20u))
|
||||
if (waveOutWrite(Globals->hWaveOut, &lpXWH->wh, sizeof(WAVEHDR)))
|
||||
{
|
||||
if (ShowDebugDialogs)
|
||||
MessageBoxA(nullptr, "Failed to write block to device", "WavMix32", 0x30u);
|
||||
@ -743,6 +1072,508 @@ XWAVEHDR* WaveMix::AddToPlayingQueue(XWAVEHDR* lpXWH)
|
||||
return play_queue.first;
|
||||
}
|
||||
|
||||
void WaveMix::MyWaveOutReset(HWAVEOUT hWaveOut)
|
||||
{
|
||||
auto position = MyWaveOutGetPosition(hWaveOut, Globals->fGoodGetPos);
|
||||
waveOutReset(hWaveOut);
|
||||
SetWaveOutPosition(position);
|
||||
}
|
||||
|
||||
void WaveMix::SetWaveOutPosition(unsigned newPosition)
|
||||
{
|
||||
DWORD position;
|
||||
mmtime_tag pmmt{};
|
||||
|
||||
pmmt.wType = TIME_BYTES;
|
||||
if (Globals->hWaveOut)
|
||||
{
|
||||
waveOutGetPosition(Globals->hWaveOut, &pmmt, 0xCu);
|
||||
position = pmmt.u.ms; /*Todo: check union ms vs sample with TIME_BYTES*/
|
||||
}
|
||||
else
|
||||
{
|
||||
position = 0;
|
||||
}
|
||||
|
||||
if (position < newPosition)
|
||||
{
|
||||
Globals->dwWaveOutPos = newPosition - position;
|
||||
Globals->pfnSampleAdjust = AddFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
Globals->dwWaveOutPos = position - newPosition;
|
||||
Globals->pfnSampleAdjust = SubFactor;
|
||||
}
|
||||
Globals->dwCurrentSample = newPosition;
|
||||
Globals->dwBaseTime = timeGetTime() - 1000 * newPosition / Globals->PCM.wf.nAvgBytesPerSec;
|
||||
}
|
||||
|
||||
DWORD WaveMix::SubFactor(DWORD a1, DWORD a2)
|
||||
{
|
||||
return a1 - a2;
|
||||
}
|
||||
|
||||
DWORD WaveMix::AddFactor(DWORD a1, DWORD a2)
|
||||
{
|
||||
return a1 + a2;
|
||||
}
|
||||
|
||||
dialog_template* WaveMix::MakeSettingsDlgTemplate()
|
||||
{
|
||||
auto size = 0u;
|
||||
dialog_template* temp = MakeDlgTemplate(&size, 0x80C80080, 0, 0, 212, 132, L"WavMix32 Settings (Ver %X.%X Static)");
|
||||
temp = AddDlgControl(&size, temp, 128, 65537, 1, 155, 5, 50, 14, L"&Ok");
|
||||
temp = AddDlgControl(&size, temp, 128, 0x10000, 2, 155, 25, 50, 14, L"&Cancel");
|
||||
temp = AddDlgControl(&size, temp, 130, 0, 1012, 5, 5, 115, 8, L"Number of WaveBlocks (%d-%d):");
|
||||
temp = AddDlgControl(&size, temp, 130, 0, 1013, 5, 20, 115, 8, L"Size of WaveBlocks (%d-%d):");
|
||||
temp = AddDlgControl(&size, temp, 130, 0, 0xFFFF, 5, 35, 102, 8, L"Playback Frequency (11,22,44):");
|
||||
temp = AddDlgControl(&size, temp, 130, 0, 0xFFFF, 5, 80, 57, 8, L"Playback Device:");
|
||||
temp = AddDlgControl(&size, temp, 130, 0, 1014, 5, 50, 115, 8, L"Number of Pause Blocks (%d-%d):");
|
||||
temp = AddDlgControl(&size, temp, 130, 0, 1015, 5, 65, 63, 8, L"Max Channels = %d");
|
||||
temp = AddDlgControl(&size, temp, 129, 8454272, 1003, 125, 5, 25, 12, L"-1");
|
||||
temp = AddDlgControl(&size, temp, 129, 8454272, 1007, 125, 20, 25, 12, L"-1");
|
||||
temp = AddDlgControl(&size, temp, 129, 8454272, 1008, 125, 35, 25, 12, L"-1");
|
||||
temp = AddDlgControl(&size, temp, 129, 8454272, 1011, 125, 50, 25, 12, L"-1");
|
||||
temp = AddDlgControl(&size, temp, 133, 2162946, 1009, 65, 80, 140, 60, L"No Devices");
|
||||
temp = AddDlgControl(&size, temp, 128, 65539, 1000, 5, 101, 40, 10, L"Stereo");
|
||||
temp = AddDlgControl(&size, temp, 128, 65539, 1001, 55, 101, 60, 10, L"Reset Remix");
|
||||
temp = AddDlgControl(&size, temp, 128, 65539, 1010, 125, 101, 78, 10, L"Show Debug Dialogs");
|
||||
temp = AddDlgControl(&size, temp, 128, 65539, 1005, 5, 117, 40, 10, L"CMixit");
|
||||
return AddDlgControl(&size, temp, 128, 65539, 1004, 55, 117, 75, 10, L"Good Get Position");
|
||||
}
|
||||
|
||||
dialog_template* WaveMix::MakeDlgTemplate(unsigned* totalSize, unsigned style, short x, short y, short cx, short cy,
|
||||
const wchar_t* String)
|
||||
{
|
||||
auto dlgSize = 2 * wcslen(String) + 24;
|
||||
*totalSize = dlgSize;
|
||||
if ((dlgSize & 3) != 0)
|
||||
*totalSize = dlgSize - (dlgSize & 3) + 4;
|
||||
|
||||
auto hGlobal = GlobalAlloc(GHND, *totalSize);
|
||||
auto dlgTemplate = static_cast<dialog_template*>(GlobalLock(hGlobal));
|
||||
if (dlgTemplate)
|
||||
{
|
||||
dlgTemplate->Dialog.dwExtendedStyle = 0;
|
||||
dlgTemplate->Dialog.cdit = 0;
|
||||
dlgTemplate->Dialog.style = style | 0x10000000;
|
||||
dlgTemplate->Dialog.x = x;
|
||||
dlgTemplate->Dialog.y = y;
|
||||
dlgTemplate->Dialog.cx = cx;
|
||||
dlgTemplate->Dialog.cy = cy;
|
||||
memcpy(dlgTemplate->Header, String, 2 * wcslen(String) + 2);
|
||||
}
|
||||
return dlgTemplate;
|
||||
}
|
||||
|
||||
dialog_template* WaveMix::AddDlgControl(unsigned* totalSize, dialog_template* dlgTemplate, short idClass,
|
||||
unsigned style, WORD id, short x, short y, short cx, short cy,
|
||||
const wchar_t* String)
|
||||
{
|
||||
dialog_template* dlgTemplate2 = dlgTemplate;
|
||||
if (dlgTemplate)
|
||||
{
|
||||
auto prevSize = *totalSize;
|
||||
*totalSize += 2 * wcslen(String) + 25;
|
||||
if ((*totalSize & 3) != 0)
|
||||
*totalSize = *totalSize - (*totalSize & 3) + 4;
|
||||
|
||||
GlobalUnlock(GlobalHandle(dlgTemplate2));
|
||||
unsigned int newSize = *totalSize;
|
||||
HGLOBAL hGlobal = GlobalReAlloc(GlobalHandle(dlgTemplate2), newSize, 0x42u);
|
||||
dlgTemplate2 = static_cast<dialog_template*>(GlobalLock(hGlobal));
|
||||
if (dlgTemplate2)
|
||||
{
|
||||
auto dlgItem = (dialog_item_template*)((char*)dlgTemplate2 + prevSize);
|
||||
dlgItem->Item.dwExtendedStyle = 0;
|
||||
dlgItem->Item.style = style | 0x50000000;
|
||||
dlgItem->Item.x = x;
|
||||
dlgItem->Item.y = y;
|
||||
dlgItem->Item.cx = cx;
|
||||
dlgItem->Item.cy = cy;
|
||||
dlgItem->Item.id = id;
|
||||
dlgItem->sysClass = 0xFFFF;
|
||||
dlgItem->idClass = idClass;
|
||||
wcscpy_s(dlgItem->Header, wcslen(String) + 1, String);
|
||||
++dlgTemplate2->Dialog.cdit;
|
||||
}
|
||||
}
|
||||
return dlgTemplate2;
|
||||
}
|
||||
|
||||
void WaveMix::DestroySettingsDlgTemplate(LPCVOID pMem)
|
||||
{
|
||||
if (pMem)
|
||||
{
|
||||
GlobalUnlock(GlobalHandle(pMem));
|
||||
GlobalFree(GlobalHandle(pMem));
|
||||
}
|
||||
}
|
||||
|
||||
int WaveMix::Settings_OnInitDialog(HWND hWnd, int wParam, MIXCONFIG* lpMixconfig)
|
||||
{
|
||||
tagWAVEOUTCAPSA pwoc{};
|
||||
CHAR String[256];
|
||||
|
||||
GetWindowTextA(hWnd, String, 256);
|
||||
wsprintfA(string_buffer, String, 2, 81);
|
||||
SetWindowTextA(hWnd, string_buffer);
|
||||
SetWindowLongA(hWnd, -21, (LONG)lpMixconfig);
|
||||
SendMessageA(GetDlgItem(hWnd, 1000), 0xF1u, lpMixconfig->wChannels > 1u, 0);
|
||||
SendMessageA(GetDlgItem(hWnd, 1001), 0xF1u, lpMixconfig->ResetMixDefaultFlag != 0, 0);
|
||||
SendMessageA(GetDlgItem(hWnd, 1004), 0xF1u, lpMixconfig->GoodWavePos != 0, 0);
|
||||
SendMessageA(GetDlgItem(hWnd, 1005), 0xF1u, lpMixconfig->CmixPtrDefaultFlag != 0, 0);
|
||||
SendMessageA(GetDlgItem(hWnd, 1010), 0xF1u, lpMixconfig->ShowDebugDialogs != 0, 0);
|
||||
EnableWindow(GetDlgItem(hWnd, 1005), 0);
|
||||
SendMessageA(GetDlgItem(hWnd, 1003), 0xC5u, 2u, 0);
|
||||
SendMessageA(GetDlgItem(hWnd, 1007), 0xC5u, 4u, 0);
|
||||
SendMessageA(GetDlgItem(hWnd, 1008), 0xC5u, 2u, 0);
|
||||
SendMessageA(GetDlgItem(hWnd, 1011), 0xC5u, 2u, 0);
|
||||
GetWindowTextA(GetDlgItem(hWnd, 1012), String, 100);
|
||||
wsprintfA(string_buffer, String, 2, 10);
|
||||
SetWindowTextA(GetDlgItem(hWnd, 1012), string_buffer);
|
||||
GetWindowTextA(GetDlgItem(hWnd, 1013), String, 100);
|
||||
wsprintfA(string_buffer, String, 344, 11025);
|
||||
SetWindowTextA(GetDlgItem(hWnd, 1013), string_buffer);
|
||||
GetWindowTextA(GetDlgItem(hWnd, 1014), String, 100);
|
||||
wsprintfA(string_buffer, String, 0, 10);
|
||||
SetWindowTextA(GetDlgItem(hWnd, 1014), string_buffer);
|
||||
GetWindowTextA(GetDlgItem(hWnd, 1015), String, 100);
|
||||
wsprintfA(string_buffer, String, 16);
|
||||
SetWindowTextA(GetDlgItem(hWnd, 1015), string_buffer);
|
||||
wsprintfA(string_buffer, "%d", lpMixconfig->WaveBlockCount);
|
||||
SetWindowTextA(GetDlgItem(hWnd, 1003), string_buffer);
|
||||
wsprintfA(string_buffer, "%d", lpMixconfig->WaveBlockLen);
|
||||
SetWindowTextA(GetDlgItem(hWnd, 1007), string_buffer);
|
||||
wsprintfA(string_buffer, "%d", lpMixconfig->wSamplingRate);
|
||||
SetWindowTextA(GetDlgItem(hWnd, 1008), string_buffer);
|
||||
wsprintfA(string_buffer, "%d", lpMixconfig->PauseBlocks);
|
||||
SetWindowTextA(GetDlgItem(hWnd, 1011), string_buffer);
|
||||
|
||||
signed int uDeviceID = 0;
|
||||
signed int deviceCount = waveOutGetNumDevs();
|
||||
if (deviceCount > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
MMRESULT getResult = waveOutGetDevCapsA(uDeviceID, &pwoc, 0x34u);
|
||||
if (getResult)
|
||||
{
|
||||
wsprintfA(string_buffer, "waveOutGetDevCaps failed (err %u) for device %d", getResult, uDeviceID);
|
||||
MessageBoxA(nullptr, string_buffer, "WavMix32", 0x40u);
|
||||
}
|
||||
else
|
||||
{
|
||||
wsprintfA(string_buffer, "%d: %s", uDeviceID, pwoc.szPname);
|
||||
SendMessageA(GetDlgItem(hWnd, 1009), 0x143u, 0, (LPARAM)string_buffer);
|
||||
}
|
||||
++uDeviceID;
|
||||
}
|
||||
while (uDeviceID < deviceCount);
|
||||
}
|
||||
SendMessageA(GetDlgItem(hWnd, 1009), 0x14Eu, lpMixconfig->wDeviceID, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WaveMix::Settings_OnCommand(HWND hWnd, int command, int lParam, int wParam)
|
||||
{
|
||||
auto userData = (MIXCONFIG*)GetWindowLongA(hWnd, -21);
|
||||
if (command == 1)
|
||||
{
|
||||
if (userData)
|
||||
{
|
||||
userData->wChannels = (SendMessageA(GetDlgItem(hWnd, 1000), 0xF0u, 0, 0) != 0) + 1;
|
||||
userData->ResetMixDefaultFlag = SendMessageA(GetDlgItem(hWnd, 1001), 0xF0u, 0, 0) != 0;
|
||||
userData->GoodWavePos = SendMessageA(GetDlgItem(hWnd, 1004), 0xF0u, 0, 0) != 0;
|
||||
userData->ShowDebugDialogs = SendMessageA(GetDlgItem(hWnd, 1010), 0xF0u, 0, 0) != 0;
|
||||
userData->CmixPtrDefaultFlag = SendMessageA(GetDlgItem(hWnd, 1005), 0xF0u, 0, 0) != 0;
|
||||
GetWindowTextA(GetDlgItem(hWnd, 1003), string_buffer, 10);
|
||||
userData->WaveBlockCount = atoi(string_buffer);
|
||||
GetWindowTextA(GetDlgItem(hWnd, 1007), string_buffer, 10);
|
||||
userData->WaveBlockLen = atoi(string_buffer);
|
||||
GetWindowTextA(GetDlgItem(hWnd, 1008), string_buffer, 10);
|
||||
userData->wSamplingRate = atoi(string_buffer);
|
||||
GetWindowTextA(GetDlgItem(hWnd, 1011), string_buffer, 10);
|
||||
userData->PauseBlocks = atoi(string_buffer);
|
||||
GetWindowTextA(GetDlgItem(hWnd, 1009), string_buffer, 10);
|
||||
userData->wDeviceID = isdigit(string_buffer[0]) ? atoi(string_buffer) : 0;
|
||||
EndDialog(hWnd, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (command != 2)
|
||||
return 0;
|
||||
EndDialog(hWnd, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WaveMix::ReadRegistryToGetMachineSpecificInfSection(unsigned wDeviceId, LPSTR lpString1, int maxLength)
|
||||
{
|
||||
HKEY phkResult;
|
||||
CHAR SubKey[52];
|
||||
|
||||
int result = 0;
|
||||
int osPrefixLength = lstrlenA(GetOperatingSystemPrefix());
|
||||
if (maxLength < osPrefixLength + 10)
|
||||
return 0;
|
||||
wsprintfA(SubKey, "Device%u", wDeviceId);
|
||||
if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\WaveMix", &phkResult))
|
||||
return 0;
|
||||
lstrcpyA(lpString1, GetOperatingSystemPrefix());
|
||||
LONG cbData = maxLength - osPrefixLength;
|
||||
if (!RegQueryValueA(phkResult, SubKey, &lpString1[osPrefixLength], &cbData) && cbData > 0)
|
||||
result = 1;
|
||||
RegCloseKey(phkResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning (disable : 4996)/*Original uses GetVersion*/
|
||||
const char* WaveMix::GetOperatingSystemPrefix()
|
||||
{
|
||||
if (GetVersion() < 0x80000000)
|
||||
return "WinNT:";
|
||||
if (GetVersion() >= 0x80000000 && static_cast<unsigned __int8>(GetVersion()) >= 4u)
|
||||
return "Win95:";
|
||||
if (GetVersion() >= 0x80000000 && static_cast<unsigned __int8>(GetVersion()) < 4u)
|
||||
return "Win31:";
|
||||
return "OS_X"; /*The next big thing: waveOut on OSX*/
|
||||
}
|
||||
#pragma warning (default : 4996)/*Original uses GetVersion*/
|
||||
|
||||
unsigned WaveMix::FigureOutDMABufferSize(unsigned waveBlockLen, PCMWAVEFORMAT* pcm)
|
||||
{
|
||||
unsigned int result = waveBlockLen;
|
||||
if (!waveBlockLen)
|
||||
result = pcm->wf.nSamplesPerSec * pcm->wf.nChannels * (pcm->wBitsPerSample >> 3) >> 4;
|
||||
if (result < 344)
|
||||
result = 344;
|
||||
if (result > 11025)
|
||||
result = 11025;
|
||||
return result;
|
||||
}
|
||||
|
||||
int WaveMix::NoResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel)
|
||||
{
|
||||
Pump();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void WaveMix::SaveConfigSettings(unsigned dwFlags)
|
||||
{
|
||||
if ((dwFlags & 0x80u) != 0)
|
||||
{
|
||||
wsprintfA(string_buffer, "%d", Globals->wDeviceID);
|
||||
WritePrivateProfileStringA("general", "WaveOutDevice", string_buffer, FileName);
|
||||
}
|
||||
if ((dwFlags & 1) != 0)
|
||||
{
|
||||
wsprintfA(string_buffer, "%d", Globals->PCM.wf.nChannels);
|
||||
WritePrivateProfileStringA(Globals->szDevicePName, "Channels", string_buffer, FileName);
|
||||
}
|
||||
if ((dwFlags & 2) != 0)
|
||||
{
|
||||
wsprintfA(string_buffer, "%d", static_cast<unsigned __int16>(11 * (Globals->PCM.wf.nSamplesPerSec / 0x2B11)));
|
||||
WritePrivateProfileStringA(Globals->szDevicePName, "SamplesPerSec", string_buffer, FileName);
|
||||
}
|
||||
if ((dwFlags & 4) != 0)
|
||||
{
|
||||
wsprintfA(string_buffer, "%d", Globals->WaveBlockCount);
|
||||
WritePrivateProfileStringA(Globals->szDevicePName, "WaveBlocks", string_buffer, FileName);
|
||||
}
|
||||
if ((dwFlags & 8) != 0)
|
||||
{
|
||||
wsprintfA(string_buffer, "%d", LOWORD(WaveMix::Globals->dwWaveBlockLen));
|
||||
WritePrivateProfileStringA(Globals->szDevicePName, "WaveBlockLen", string_buffer, FileName);
|
||||
}
|
||||
if ((dwFlags & 0x10) != 0)
|
||||
{
|
||||
wsprintfA(string_buffer, "%d", Globals->CmixPtr == cmixit);
|
||||
WritePrivateProfileStringA(Globals->szDevicePName, "CMixit", string_buffer, FileName);
|
||||
}
|
||||
if ((dwFlags & 0x20) != 0)
|
||||
{
|
||||
wsprintfA(string_buffer, "%d", (Globals->pfnRemix != ResetRemix) + 1);
|
||||
WritePrivateProfileStringA(Globals->szDevicePName, "Remix", string_buffer, FileName);
|
||||
}
|
||||
if ((dwFlags & 0x40) != 0)
|
||||
{
|
||||
wsprintfA(string_buffer, "%d", Globals->fGoodGetPos == 0);
|
||||
WritePrivateProfileStringA(Globals->szDevicePName, "GoodWavePos", string_buffer, FileName);
|
||||
}
|
||||
if ((dwFlags & 0x100) != 0)
|
||||
{
|
||||
wsprintfA(string_buffer, "%d", ShowDebugDialogs != 0);
|
||||
WritePrivateProfileStringA("general", "ShowDebugDialogs", string_buffer, FileName);
|
||||
}
|
||||
if ((dwFlags & 0x200) != 0)
|
||||
{
|
||||
wsprintfA(string_buffer, "%d", Globals->PauseBlocks);
|
||||
WritePrivateProfileStringA(Globals->szDevicePName, "PauseBlocks", string_buffer, FileName);
|
||||
}
|
||||
}
|
||||
|
||||
void WaveMix::ShowCurrentSettings()
|
||||
{
|
||||
tagWAVEOUTCAPSA pwoc{};
|
||||
|
||||
if (waveOutGetDevCapsA(Globals->wDeviceID, &pwoc, 0x34u) || !RemoveInvalidIniNameCharacters(pwoc.szPname))
|
||||
lstrcpyA(pwoc.szPname, "Unknown Device");
|
||||
auto cmixitType = "cmixit";
|
||||
if (Globals->CmixPtr != cmixit)
|
||||
cmixitType = "386 mixit";
|
||||
auto getGood = "TRUE";
|
||||
if (!Globals->fGoodGetPos)
|
||||
getGood = "FALSE";
|
||||
auto remixType = "Reset";
|
||||
if (Globals->pfnRemix != ResetRemix)
|
||||
remixType = "NoReset";
|
||||
wsprintfA(
|
||||
string_buffer,
|
||||
"Using:\t%s.\n"
|
||||
"\tRemix = %s\n"
|
||||
"\tGoodGetPos=%s\n"
|
||||
"\t%d ping pong wave blocks\n"
|
||||
"\tWave block len = %lu bytes\n"
|
||||
"\tpfnMixit=%s\n"
|
||||
"\tSamplesPerSec=%lu,\n"
|
||||
"\tChannels=%d\n"
|
||||
"\tPauseBlocks=%d",
|
||||
pwoc.szPname,
|
||||
remixType,
|
||||
getGood,
|
||||
Globals->WaveBlockCount,
|
||||
Globals->dwWaveBlockLen,
|
||||
cmixitType,
|
||||
Globals->PCM.wf.nSamplesPerSec,
|
||||
Globals->PCM.wf.nChannels,
|
||||
Globals->PauseBlocks);
|
||||
MessageBoxA(nullptr, string_buffer, "WavMix32", 0x40u);
|
||||
}
|
||||
|
||||
unsigned WaveMix::GetWaveDevice()
|
||||
{
|
||||
WAVEFORMATEX pwfx{};
|
||||
|
||||
if (Globals->hWaveOut)
|
||||
return 0;
|
||||
HWND window = CreateWindowExA(0, "WavMix32", pinball::WindowName, 0x8000000u, 0, 0, 0, 0, nullptr, nullptr, HModule,
|
||||
nullptr);
|
||||
GLOBALS* globals = Globals;
|
||||
Globals->hWndApp = window;
|
||||
if (!window)
|
||||
{
|
||||
if (ShowDebugDialogs)
|
||||
MessageBoxA(nullptr, "Failed to create callback window.", "WavMix32", 0x30u);
|
||||
return 1;
|
||||
}
|
||||
pwfx.wFormatTag = globals->PCM.wf.wFormatTag;
|
||||
pwfx.nChannels = globals->PCM.wf.nChannels;
|
||||
pwfx.nSamplesPerSec = globals->PCM.wf.nSamplesPerSec;
|
||||
pwfx.nAvgBytesPerSec = globals->PCM.wf.nAvgBytesPerSec;
|
||||
pwfx.nBlockAlign = globals->PCM.wf.nBlockAlign;
|
||||
pwfx.wBitsPerSample = globals->PCM.wBitsPerSample;
|
||||
pwfx.cbSize = 0;
|
||||
unsigned int openResult = waveOutOpen(&globals->hWaveOut, 0xFFFFFFFF, &pwfx,
|
||||
reinterpret_cast<DWORD_PTR>(globals->hWndApp), 0,
|
||||
0x10000u);
|
||||
if (openResult)
|
||||
{
|
||||
DestroyWindow(Globals->hWndApp);
|
||||
Globals->hWndApp = nullptr;
|
||||
return openResult;
|
||||
}
|
||||
if (AllocWaveBlocks(Globals->hWaveOut, block_array1)
|
||||
&& AllocWaveBlocks(Globals->hWaveOut, block_array2))
|
||||
{
|
||||
Globals->WaveBlockArray = block_array1;
|
||||
return 0;
|
||||
}
|
||||
FreeWaveBlocks(Globals->hWaveOut, block_array1);
|
||||
FreeWaveBlocks(Globals->hWaveOut, block_array2);
|
||||
waveOutClose(Globals->hWaveOut);
|
||||
Globals->hWaveOut = nullptr;
|
||||
DestroyWindow(Globals->hWndApp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void WaveMix::FreeWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks)
|
||||
{
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
auto blockPtr = &waveBlocks[i];
|
||||
if (*blockPtr)
|
||||
{
|
||||
waveOutUnprepareHeader(hwo, &(*blockPtr)->wh, sizeof(WAVEHDR));
|
||||
GlobalUnlock(GlobalHandle(*blockPtr));
|
||||
GlobalFree(GlobalHandle(*blockPtr));
|
||||
*blockPtr = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int WaveMix::AllocWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks)
|
||||
{
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
auto xHDR = static_cast<XWAVEHDR*>(GlobalLock(GlobalAlloc(GMEM_SHARE, 0x2B41u)));
|
||||
waveBlocks[i] = xHDR;
|
||||
if (!xHDR)
|
||||
{
|
||||
if (ShowDebugDialogs)
|
||||
MessageBoxA(
|
||||
nullptr,
|
||||
"Unable to allocate memory for waveform data. Try making more memory available by closing other applications.",
|
||||
"WavMix32",
|
||||
0x30u);
|
||||
for (int j = i - 1; j >= 0; --j)
|
||||
{
|
||||
GlobalUnlock(GlobalHandle(waveBlocks[j]));
|
||||
GlobalFree(GlobalHandle(waveBlocks[j]));
|
||||
waveBlocks[j] = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
xHDR->wh.lpData = (LPSTR)&xHDR[1];
|
||||
xHDR->wh.dwBufferLength = Globals->dwWaveBlockLen;
|
||||
xHDR->wh.dwFlags = 0;
|
||||
xHDR->wh.dwLoops = 0;
|
||||
xHDR->fAvailable = 1;
|
||||
xHDR->dwWavePos = 0;
|
||||
}
|
||||
int index = 0;
|
||||
while (!waveOutPrepareHeader(hwo, &waveBlocks[index]->wh, sizeof(WAVEHDR)))
|
||||
{
|
||||
waveBlocks[index++]->wh.dwFlags |= 1u;
|
||||
if (index >= 10)
|
||||
return 1;
|
||||
}
|
||||
if (ShowDebugDialogs)
|
||||
MessageBoxA(nullptr, "Unable to prepare wave header.", "WavMix32", 0x30u);
|
||||
FreeWaveBlocks(hwo, waveBlocks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WaveMix::ReleaseWaveDevice(GLOBALS* globals)
|
||||
{
|
||||
if (globals->fActive)
|
||||
{
|
||||
if (globals->hWaveOut)
|
||||
{
|
||||
MyWaveOutReset(globals->hWaveOut);
|
||||
DestroyPlayQueue();
|
||||
FreeWaveBlocks(globals->hWaveOut, block_array1);
|
||||
FreeWaveBlocks(globals->hWaveOut, block_array2);
|
||||
waveOutClose(globals->hWaveOut);
|
||||
globals->hWaveOut = nullptr;
|
||||
DestroyWindow(globals->hWndApp);
|
||||
globals->hWndApp = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WaveMix::cmixit(unsigned __int8* lpDest, unsigned __int8** rgWaveSrc, volume_struct* volume, int iNumWaves,
|
||||
unsigned __int16 length)
|
||||
{
|
||||
@ -755,3 +1586,13 @@ LRESULT WaveMix::WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
Pump();
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT_PTR WaveMix::SettingsDlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (Msg == 272)
|
||||
return Settings_OnInitDialog(hWnd, wParam, (MIXCONFIG*)lParam);
|
||||
if (Msg != 273)
|
||||
return 0;
|
||||
Settings_OnCommand(hWnd, static_cast<unsigned __int16>(wParam), lParam, HIWORD(wParam));
|
||||
return 1;
|
||||
}
|
||||
|
@ -58,13 +58,13 @@ struct MIXCONFIG
|
||||
DWORD dwFlags;
|
||||
WORD wChannels;
|
||||
WORD wSamplingRate;
|
||||
__int16 WaveBlockCount;
|
||||
__int16 WaveBlockLen;
|
||||
unsigned __int16 WaveBlockCount;
|
||||
unsigned __int16 WaveBlockLen;
|
||||
__int16 CmixPtrDefaultFlag;
|
||||
unsigned __int16 ResetMixDefaultFlag;
|
||||
unsigned __int16 GoodWavePos;
|
||||
unsigned __int16 wDeviceID;
|
||||
__int16 PauseBlocks;
|
||||
unsigned __int16 PauseBlocks;
|
||||
__int16 ShowDebugDialogs;
|
||||
HKEY RegistryKey;
|
||||
};
|
||||
@ -88,20 +88,13 @@ struct GLOBALS
|
||||
{
|
||||
WORD wMagic1;
|
||||
__int16 unknown0;
|
||||
int unknown1;
|
||||
HWND hWndApp;
|
||||
int unknown2;
|
||||
HWAVEOUT hWaveOut;
|
||||
int fActive;
|
||||
int SettingsDialogActiveFlag;
|
||||
unsigned int wDeviceID;
|
||||
int unknown7;
|
||||
int unknown8;
|
||||
int unknown9;
|
||||
int unknown10;
|
||||
int unknown11;
|
||||
int unknown12;
|
||||
int unknown13;
|
||||
int unknown14;
|
||||
char szDevicePName[32];
|
||||
int unknown15;
|
||||
int unknown16;
|
||||
int unknown17;
|
||||
@ -156,23 +149,39 @@ struct GLOBALS
|
||||
int unknown93;
|
||||
int unknown94;
|
||||
PCMWAVEFORMAT PCM;
|
||||
int WaveBlockLen;
|
||||
DWORD dwWaveBlockLen;
|
||||
int WaveBlockCount;
|
||||
int PauseBlocks;
|
||||
XWAVEHDR** WaveBlockArray;
|
||||
DWORD dwCurrentSample;
|
||||
DWORD dwBaseTime;
|
||||
int fGoodGetPos;
|
||||
int dwWaveOutPos;
|
||||
DWORD dwWaveOutPos;
|
||||
void (*CmixPtr)(unsigned __int8* lpDest, unsigned __int8** rgWaveSrc, volume_struct* volume, int iNumWaves,
|
||||
unsigned __int16 length);
|
||||
int (* pfnRemix)(DWORD, CHANNELNODE*);
|
||||
int (* pfnSampleAdjust)(int, int);
|
||||
DWORD (* pfnSampleAdjust)(DWORD, DWORD);
|
||||
int unknown110;
|
||||
__int16 wMagic2;
|
||||
__int16 unknown112;
|
||||
};
|
||||
|
||||
struct dialog_template
|
||||
{
|
||||
DLGTEMPLATE Dialog;
|
||||
WORD menu;
|
||||
WORD windowClass;
|
||||
WCHAR Header[1];
|
||||
};
|
||||
|
||||
struct dialog_item_template
|
||||
{
|
||||
DLGITEMTEMPLATE Item;
|
||||
WORD sysClass;
|
||||
WORD idClass;
|
||||
WCHAR Header[1];
|
||||
};
|
||||
|
||||
|
||||
class WaveMix
|
||||
{
|
||||
@ -204,7 +213,7 @@ private:
|
||||
static int DefaultPauseBlocks(int waveBlocks);
|
||||
static int Configure(GLOBALS* hMixSession, HWND hWndParent, MIXCONFIG* lpConfig, int* flag1Ptr, int saveConfigFlag);
|
||||
static int GetConfig(HANDLE hMixSession, MIXCONFIG* lpConfig);
|
||||
static unsigned MyWaveOutGetPosition(HWAVEOUT hwo, int fGoodGetPos);
|
||||
static unsigned MyWaveOutGetPosition(HWAVEOUT hWaveOut, int fGoodGetPos);
|
||||
static void FreeChannelNode(CHANNELNODE* channel);
|
||||
static int ResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel);
|
||||
static XWAVEHDR* RemoveFromPlayingQueue(XWAVEHDR* lpXWH);
|
||||
@ -213,9 +222,35 @@ private:
|
||||
static XWAVEHDR* GetWaveBlock();
|
||||
static int MixerPlay(XWAVEHDR* lpXWH, int fWriteBlocks);
|
||||
static XWAVEHDR* AddToPlayingQueue(XWAVEHDR* lpXWH);
|
||||
static void MyWaveOutReset(HWAVEOUT hWaveOut);
|
||||
static void SetWaveOutPosition(unsigned int newPosition);
|
||||
static DWORD SubFactor(DWORD a1, DWORD a2);
|
||||
static DWORD AddFactor(DWORD a1, DWORD a2);
|
||||
static dialog_template* MakeSettingsDlgTemplate();
|
||||
static dialog_template* MakeDlgTemplate(unsigned* totalSize, unsigned style, __int16 x, __int16 y, __int16 cx,
|
||||
__int16 cy,
|
||||
const wchar_t* String);
|
||||
static dialog_template* AddDlgControl(unsigned int* totalSize, dialog_template* dlgTemplate, __int16 idClass,
|
||||
unsigned style,
|
||||
WORD id, __int16 x, __int16 y, __int16 cx, __int16 cy,
|
||||
const wchar_t* String);
|
||||
static void DestroySettingsDlgTemplate(LPCVOID pMem);
|
||||
static int Settings_OnInitDialog(HWND hWnd, int wParam, MIXCONFIG* lpMixconfig);
|
||||
static int Settings_OnCommand(HWND hWnd, int command, int lParam, int wParam);
|
||||
static int ReadRegistryToGetMachineSpecificInfSection(unsigned wDeviceId, LPSTR lpString1, int maxLength);
|
||||
static const char* GetOperatingSystemPrefix();
|
||||
static unsigned int FigureOutDMABufferSize(unsigned int waveBlockLen, PCMWAVEFORMAT* pcm);
|
||||
static int NoResetRemix(DWORD dwRemixSamplePos, CHANNELNODE* channel);
|
||||
static void SaveConfigSettings(unsigned dwFlags);
|
||||
static void ShowCurrentSettings();
|
||||
static unsigned int GetWaveDevice();
|
||||
static void FreeWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks);
|
||||
static int AllocWaveBlocks(HWAVEOUT hwo, XWAVEHDR** waveBlocks);
|
||||
static void ReleaseWaveDevice(GLOBALS* globals);
|
||||
static void cmixit(unsigned __int8* lpDest, unsigned __int8** rgWaveSrc, volume_struct* volume, int iNumWaves,
|
||||
unsigned __int16 length);
|
||||
static LRESULT __stdcall WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
static INT_PTR __stdcall SettingsDlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static int initialized_flag;
|
||||
static char FileName[276];
|
||||
|
Loading…
Reference in New Issue
Block a user