Sound ready.

This commit is contained in:
oz 2021-01-23 19:28:29 +03:00
parent 7d15427dd9
commit b0080fd80a
11 changed files with 363 additions and 21 deletions

1
.gitignore vendored
View file

@ -262,3 +262,4 @@ __pycache__/
/Ida /Ida
/Export /Export
/DrMem /DrMem
/Doc private

Binary file not shown.

View file

@ -1,33 +1,146 @@
#include "pch.h" #include "pch.h"
#include "Sound.h" #include "Sound.h"
int Sound::Init(HINSTANCE hInstance, int voices, void (__stdcall* someFuncPtr)(int, int, int)) #include "pinball.h"
#include "WaveMix.h"
#include "winmain.h"
int Sound::num_channels;
HWND Sound::wavemix_window;
HANDLE Sound::pMem;
unsigned int Sound::enabled_flag;
int Sound::channel_time[8];
MIXWAVE* Sound::channel_wavePtr[8];
void (*Sound::callback_ptr)(int, MIXWAVE*, int);
HMODULE Sound::HInstance;
int Sound::Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWAVE*, int))
{ {
WNDCLASSA WndClass;
char FileName[300];
int channelCount = voices;
if (voices > 8)
channelCount = 8;
num_channels = channelCount;
if (wavemix_window || pMem)
return 0;
enabled_flag = -1;
for (int i = 0; i < channelCount; ++i)
{
channel_time[i] = 0;
channel_wavePtr[i] = nullptr;
}
callback_ptr = someFuncPtr;
if (!someFuncPtr)
callback_ptr = NullCallback;
pinball::make_path_name(FileName, "wavemix.inf", 300);
FILE* wavemixIniFile = nullptr;
fopen_s(&wavemixIniFile, FileName, "r");
if (wavemixIniFile)
{
fclose(wavemixIniFile);
}
else
{
MessageBoxA(winmain::hwnd_frame, pinball::get_rc_string(42, 0), pinball::WindowName, 0x2000u);
}
WndClass.style = 0;
WndClass.lpfnWndProc = SoundCallBackWndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = nullptr;
WndClass.hCursor = nullptr;
WndClass.hbrBackground = nullptr;
WndClass.lpszMenuName = nullptr;
WndClass.lpszClassName = "WaveMixSoundGuy";
RegisterClassA(&WndClass);
wavemix_window = CreateWindowExA(
0,
"WaveMixSoundGuy",
nullptr,
0x80000000,
0x80000000,
0,
0x80000000,
0,
nullptr,
nullptr,
hInstance,
nullptr);
if (!wavemix_window)
return 0;
HInstance = hInstance;
HANDLE hMixSession = WaveMix::Init();
pMem = hMixSession;
if (!hMixSession)
return 0;
WaveMix::OpenChannel(hMixSession, num_channels, 2u);
return 1; return 1;
} }
void Sound::Enable(int a1, int a2, int a3) void Sound::Enable(int channelFrom, int channelTo, int enableFlag)
{ {
} if (pMem)
{
if (channelTo >= num_channels)
channelTo = num_channels - 1;
void Sound::nullsub_1(int a1, int a2, int a3) if (channelFrom >= 0 && channelTo < num_channels)
{ {
for (int index = channelFrom; index <= channelTo; ++index)
{
int channelFlag = 1 << index;
if (enableFlag)
{
enabled_flag |= channelFlag;
}
else
{
enabled_flag &= ~channelFlag;
Flush(index, index);
}
}
}
}
} }
void Sound::Idle() void Sound::Idle()
{ {
if (pMem)
WaveMix::Pump();
} }
void Sound::Activate() void Sound::Activate()
{ {
if (pMem)
WaveMix::Activate(pMem, true);
} }
void Sound::Deactivate() void Sound::Deactivate()
{ {
if (pMem)
WaveMix::Activate(pMem, false);
} }
void Sound::Close() void Sound::Close()
{ {
if (wavemix_window)
{
DestroyWindow(wavemix_window);
wavemix_window = nullptr;
}
if (pMem)
{
WaveMix::CloseChannel(pMem, 0, 1);
WaveMix::CloseSession(pMem);
pMem = nullptr;
}
} }
int Sound::SubFactor(int a1, int a2) int Sound::SubFactor(int a1, int a2)
@ -40,16 +153,124 @@ int Sound::AddFactor(int a1, int a2)
return a1 + a2; return a1 + a2;
} }
void Sound::PlaySoundA(int a1, int a2, int a3, unsigned short a4, short a5) void Sound::PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, __int16 loops)
{
MIXPLAYPARAMS mixParams{};
if (!pMem)
return;
if (maxChannel >= num_channels)
maxChannel = num_channels - 1;
if (!wavePtr || minChannel < 0 || maxChannel >= num_channels)
return;
if ((dwFlags & 0x8000) != 0 && num_channels > 0)
{
int index2 = 0;
bool ok = false;
while (channel_wavePtr[index2] != wavePtr)
{
if (++index2 >= num_channels)
{
ok = true;
break;
}
}
if (!ok)
return;
}
int playChannel = minChannel;
if (minChannel < maxChannel)
{
int curChannel = minChannel;
do
{
++curChannel;
if ((1 << curChannel) & enabled_flag &&
channel_time[curChannel] < channel_time[playChannel])
{
playChannel = curChannel;
}
}
while (curChannel < maxChannel);
}
if ((1 << playChannel) & enabled_flag)
{
mixParams.hMixSession = pMem;
mixParams.hWndNotify = wavemix_window;
mixParams.dwFlags = dwFlags;
mixParams.wSize = 28;
mixParams.wLoops = loops;
mixParams.iChannel = playChannel;
mixParams.lpMixWave = wavePtr;
callback_ptr(1, wavePtr, playChannel);
channel_time[playChannel] = timeGetTime();
channel_wavePtr[playChannel] = wavePtr;
WaveMix::Play(&mixParams);
}
}
MIXWAVE* Sound::LoadWaveFile(LPCSTR lpName)
{
return pMem ? WaveMix::OpenWave(pMem, lpName, HInstance, 1u) : nullptr;
}
void Sound::FreeSound(MIXWAVE* wave)
{
if (wave && pMem)
WaveMix::FreeWave(pMem, wave);
}
void Sound::Flush(int channelFrom, int channelTo)
{
if (pMem)
{
if (channelTo >= num_channels)
channelTo = num_channels - 1;
if (channelFrom >= 0 && channelTo < num_channels)
{
for (auto index = channelFrom; index <= channelTo; index++)
{
WaveMix::FlushChannel(pMem, index, 0);
channel_time[index] = 0;
channel_wavePtr[index] = nullptr;
}
}
}
}
void Sound::NullCallback(int a1, MIXWAVE* a2, int a3)
{ {
} }
CHAR* Sound::LoadWaveFile(LPCSTR lpName) LRESULT Sound::SoundCallBackWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{ {
return nullptr; if (Msg != 957)
} return DefWindowProcA(hWnd, Msg, wParam, lParam);
LPCVOID Sound::FreeSound(LPCVOID pMem) auto wavePtr = reinterpret_cast<MIXWAVE*>(lParam);
{ int channel = -1;
return nullptr; for (auto index = 0; index < num_channels; ++index)
{
if (channel_wavePtr[index] == wavePtr &&
(channel < 0 || channel_time[index] < channel_time[channel]))
{
channel = index;
}
}
if (channel >= 0)
{
channel_time[channel] = 0;
channel_wavePtr[channel] = nullptr;
}
callback_ptr(2, wavePtr, channel);
return 0;
} }

View file

@ -1,17 +1,30 @@
#pragma once #pragma once
#include "WaveMix.h"
class Sound class Sound
{ {
public: public:
static int Init(HINSTANCE hInstance, int voices, void (__stdcall* someFuncPtr)(int, int, int)); static int Init(HINSTANCE hInstance, int voices, void (* someFuncPtr)(int, MIXWAVE*, int));
static void Enable(int a1, int a2, int a3); static void Enable(int channelFrom, int channelTo, int enableFlag);
static void nullsub_1(int a1, int a2, int a3);
static void Idle(); static void Idle();
static void Activate(); static void Activate();
static void Deactivate(); static void Deactivate();
static void Close(); static void Close();
static int SubFactor(int a1, int a2); static int SubFactor(int a1, int a2);
static int AddFactor(int a1, int a2); static int AddFactor(int a1, int a2);
static void PlaySound(int a1, int a2, int a3, unsigned __int16 a4, __int16 a5); static void PlaySound(MIXWAVE* wavePtr, int minChannel, int maxChannel, unsigned int dwFlags, __int16 loops);
static CHAR* LoadWaveFile(LPCSTR lpName); static MIXWAVE* LoadWaveFile(LPCSTR lpName);
static LPCVOID FreeSound(LPCVOID pMem); static void FreeSound(MIXWAVE* wave);
static void Flush(int channelFrom, int channelTo);
static void NullCallback(int a1, MIXWAVE* a2, int a3);
static LRESULT __stdcall SoundCallBackWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
private:
static int num_channels;
static HWND wavemix_window;
static HANDLE pMem;
static unsigned int enabled_flag;
static int channel_time[8];
static MIXWAVE* channel_wavePtr[8];
static void (* callback_ptr)(int, MIXWAVE*, int);
static HMODULE HInstance;
}; };

View file

@ -217,6 +217,7 @@
<ClInclude Include="TTripwire.h" /> <ClInclude Include="TTripwire.h" />
<ClInclude Include="TWall.h" /> <ClInclude Include="TWall.h" />
<ClInclude Include="TZmapList.h" /> <ClInclude Include="TZmapList.h" />
<ClInclude Include="WaveMix.h" />
<ClInclude Include="winmain.h" /> <ClInclude Include="winmain.h" />
<ClInclude Include="zdrv.h" /> <ClInclude Include="zdrv.h" />
</ItemGroup> </ItemGroup>
@ -286,6 +287,7 @@
<ClCompile Include="TTimer.cpp" /> <ClCompile Include="TTimer.cpp" />
<ClCompile Include="TTripwire.cpp" /> <ClCompile Include="TTripwire.cpp" />
<ClCompile Include="TWall.cpp" /> <ClCompile Include="TWall.cpp" />
<ClCompile Include="WaveMix.cpp" />
<ClCompile Include="winmain.cpp" /> <ClCompile Include="winmain.cpp" />
<ClCompile Include="zdrv.cpp" /> <ClCompile Include="zdrv.cpp" />
</ItemGroup> </ItemGroup>

View file

@ -222,6 +222,9 @@
<ClInclude Include="TFlipperEdge.h"> <ClInclude Include="TFlipperEdge.h">
<Filter>Header Files\TEdgeSegment</Filter> <Filter>Header Files\TEdgeSegment</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="WaveMix.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="pch.cpp"> <ClCompile Include="pch.cpp">
@ -410,6 +413,9 @@
<ClCompile Include="TFlipperEdge.cpp"> <ClCompile Include="TFlipperEdge.cpp">
<Filter>Source Files\TEdgeSegment</Filter> <Filter>Source Files\TEdgeSegment</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="WaveMix.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Natvis Include="NatvisFile.natvis" /> <Natvis Include="NatvisFile.natvis" />

View file

@ -0,0 +1,51 @@
#include "pch.h"
#include "WaveMix.h"
HANDLE WaveMix::Init()
{
return (HANDLE)1;
}
int WaveMix::CloseSession(HANDLE hMixSession)
{
return 0;
}
int WaveMix::OpenChannel(HANDLE hMixSession, int iChannel, unsigned dwFlags)
{
return 0;
}
int WaveMix::CloseChannel(HANDLE hMixSession, int iChannel, unsigned dwFlags)
{
return 0;
}
int WaveMix::FlushChannel(HANDLE hMixSession, int iChannel, unsigned dwFlags)
{
return 0;
}
MIXWAVE* WaveMix::OpenWave(HANDLE hMixSession, LPCSTR szWaveFilename, HINSTANCE hInst, unsigned dwFlags)
{
return new MIXWAVE{};
}
int WaveMix::FreeWave(HANDLE hMixSession, MIXWAVE* lpMixWave)
{
return 0;
}
int WaveMix::Activate(HANDLE hMixSession, bool fActivate)
{
return 0;
}
void WaveMix::Pump()
{
}
int WaveMix::Play(MIXPLAYPARAMS* lpMixPlayParams)
{
return 0;
}

View file

@ -0,0 +1,44 @@
#pragma once
/* flag values for play params */
#define WMIX_QUEUEWAVE 0x00
#define WMIX_CLEARQUEUE 0x01
#define WMIX_USELRUCHANNEL 0x02
#define WMIX_HIPRIORITY 0x04
#define WMIX_WAIT 0x08
#define MAXCHANNELS 16
struct MIXWAVE
{
PCMWAVEFORMAT pcm;
WAVEHDR wh;
char szWaveFilename[16];
short Unknown0;
};
struct MIXPLAYPARAMS
{
WORD wSize;
HANDLE hMixSession;
int iChannel;
MIXWAVE* lpMixWave;
HWND hWndNotify;
DWORD dwFlags;
WORD wLoops;
};
class WaveMix
{
public:
static HANDLE Init();
static int CloseSession(HANDLE hMixSession);
static int OpenChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags);
static int CloseChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags);
static int FlushChannel(HANDLE hMixSession, int iChannel, unsigned int dwFlags);
static MIXWAVE* OpenWave(HANDLE hMixSession, LPCSTR szWaveFilename, HINSTANCE hInst, unsigned int dwFlags);
static int FreeWave(HANDLE hMixSession, MIXWAVE* lpMixWave);
static int Activate(HANDLE hMixSession, bool fActivate);
static void Pump();
static int Play(MIXPLAYPARAMS* lpMixPlayParams);
};

View file

@ -325,7 +325,7 @@ float loader::play_sound(int soundIndex)
{ {
if (soundIndex <= 0) if (soundIndex <= 0)
return 0.0; return 0.0;
Sound::PlaySound((int)sound_list[soundIndex].WavePtr, 0, 7, 5, 0); Sound::PlaySound(sound_list[soundIndex].WavePtr, 0, 7, WMIX_HIPRIORITY | WMIX_CLEARQUEUE, 0);
return sound_list[soundIndex].Duration; return sound_list[soundIndex].Duration;
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "gdrv.h" #include "gdrv.h"
#include "maths.h" #include "maths.h"
#include "WaveMix.h"
#include "zdrv.h" #include "zdrv.h"
@ -14,7 +15,7 @@ struct errorMsg
struct soundListStruct struct soundListStruct
{ {
char* WavePtr; MIXWAVE* WavePtr;
int GroupIndex; int GroupIndex;
int Loaded; int Loaded;
float Duration; float Duration;

View file

@ -19,7 +19,10 @@
#include <type_traits> /*For control template*/ #include <type_traits> /*For control template*/
//#include <cstdlib> //#include <cstdlib>
// Use (void) to silent unused warnings. /*Use (void) to silent unused warnings.*/
#define assertm(exp, msg) assert(((void)msg, exp)) #define assertm(exp, msg) assert(((void)msg, exp))
/*Sound uses PlaySound*/
#undef PlaySound
#endif //PCH_H #endif //PCH_H