From ace906907755ed0457d2cfb4421ac3de973416be Mon Sep 17 00:00:00 2001 From: f Date: Mon, 31 Jul 2023 12:17:52 +0200 Subject: [PATCH 1/2] Add windows soundsystem Add Basic functionality to the playAt method only can play sounds in 2D. --- platforms/windows/SoundSystem_windows.cpp | 218 ++++++++++++++++++++++ platforms/windows/SoundSystem_windows.hpp | 49 +++++ source/Sound/SoundEngine.hpp | 9 +- windows_vs/minecraftcpp.vcxproj | 2 + windows_vs/minecraftcpp.vcxproj.filters | 6 + 5 files changed, 282 insertions(+), 2 deletions(-) create mode 100644 platforms/windows/SoundSystem_windows.cpp create mode 100644 platforms/windows/SoundSystem_windows.hpp diff --git a/platforms/windows/SoundSystem_windows.cpp b/platforms/windows/SoundSystem_windows.cpp new file mode 100644 index 0000000..7e3d49e --- /dev/null +++ b/platforms/windows/SoundSystem_windows.cpp @@ -0,0 +1,218 @@ +/******************************************************************** + Minecraft: Pocket Edition - Decompilation Project + Copyright (C) 2023 iProgramInCpp + + The following code is licensed under the BSD 1 clause license. + SPDX-License-Identifier: BSD-1-Clause + ********************************************************************/ + +#include "SoundSystem_windows.hpp" + +SoundSystemWindows::SoundSystemWindows() +{ + printf("Init SoundSystemWindows\n"); + + WNDCLASSA WndClass; + + memset(&WndClass, 0, sizeof(WndClass)); + WndClass.lpfnWndProc = DefWindowProcA; + WndClass.hInstance = GetModuleHandleA(NULL); + WndClass.lpszClassName = "SoundWindow"; + RegisterClassA(&WndClass); + m_hiddenwindow = CreateWindowExA( + 0, + "SoundWindow", + "SoundWindow", + 0x80000000, + 0, + 0, + 0, + 0, + 0, + 0, + WndClass.hInstance, + 0); + if (!m_hiddenwindow) { + printf("SoundSystemWindows cannot create hidden window for directsound8\n"); + return; + } + + initDirectSound(); + +} + +void SoundSystemWindows::initDirectSound() +{ + HRESULT result; + DSBUFFERDESC bufferDesc; + + + result = DirectSoundCreate8(NULL, &m_directsound, NULL); + if (FAILED(result)) + { + printf("SoundSystemWindows failed to create directsound8 handle\n"); + return; + } + + result = m_directsound->SetCooperativeLevel(m_hiddenwindow, DSSCL_NORMAL); + if (FAILED(result)) + { + printf("SoundSystemWindows failed set cooperation level\n"); + return; + } + + bufferDesc.dwSize = sizeof(DSBUFFERDESC); + bufferDesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; + bufferDesc.dwBufferBytes = 0; + bufferDesc.dwReserved = 0; + bufferDesc.lpwfxFormat = NULL; + bufferDesc.guid3DAlgorithm = GUID_NULL; + + // Get control of the primary sound buffer on the default sound device. + result = m_directsound->CreateSoundBuffer(&bufferDesc, &m_primarybuffer, NULL); + if (FAILED(result)) + { + printf("SoundSystemWindows failed to create primary sound buffer\n"); + return; + } + +} + + +SoundSystemWindows::~SoundSystemWindows() +{ + printf("Destroying SoundSystemWindows\n"); +} + + +bool SoundSystemWindows::isAvailable() +{ + return false; +} + +void SoundSystemWindows::setListenerPos(float x, float y, float z) +{ + +} + +void SoundSystemWindows::setListenerAngle(float f) +{ + +} + +void SoundSystemWindows::load(const std::string& sound) +{ +} + +void SoundSystemWindows::play(const std::string& sound) +{ +} + +void SoundSystemWindows::pause(const std::string& sound) +{ +} + +void SoundSystemWindows::stop(const std::string& sound) +{ +} + + +void SoundSystemWindows::playAt(const SoundDesc& sound, float x, float y, float z, float volume, float pitch) +{ + + //Release sounds that finished playing + for (size_t i = 0; i < m_buffers.size(); i++) + { + DWORD status; + (*m_buffers[i])->GetStatus(&status); + if (status != DSBSTATUS_PLAYING) { + (*m_buffers[i])->Release(); + delete m_buffers[i]; + m_buffers.erase(m_buffers.begin() + i); + } + } + + + if (sound.m_pHeader->m_id == 1) //for some reason if the id is 1 you need to pitch the sound down + { + pitch /= 2.f; + } + + HRESULT result; + IDirectSoundBuffer* tempBuffer; + unsigned char* bufferPtr; + unsigned long bufferSize; + + int length = sound.m_pHeader->m_length*sizeof(uint16_t); + + LPDIRECTSOUNDBUFFER* soundbuffer = (LPDIRECTSOUNDBUFFER*)calloc(1, sizeof(LPDIRECTSOUNDBUFFER)); + + WAVEFORMATEX waveFormat; + waveFormat.wFormatTag = WAVE_FORMAT_PCM; + waveFormat.nSamplesPerSec = DWORD(float(sound.m_pHeader->m_sample_rate) * pitch); + waveFormat.wBitsPerSample = 16; + waveFormat.nChannels = sound.m_header.m_channels; + waveFormat.nBlockAlign = (waveFormat.wBitsPerSample / 8) * waveFormat.nChannels; + waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; + waveFormat.cbSize = 0; + + // Set the buffer description of the secondary sound buffer that the wave file will be loaded onto. + DSBUFFERDESC bufferDesc; + bufferDesc.dwSize = sizeof(DSBUFFERDESC); + if (sound.m_header.m_channels == 1) { + bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRL3D; + } + else { + bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS; + } + + bufferDesc.dwBufferBytes = length; + bufferDesc.dwReserved = 0; + bufferDesc.lpwfxFormat = &waveFormat; + bufferDesc.guid3DAlgorithm = GUID_NULL; + + // Create a temporary sound buffer with the specific buffer settings. + result = m_directsound->CreateSoundBuffer(&bufferDesc, &tempBuffer, NULL); + if (FAILED(result)) + { + printf("SoundSystemWindows CreateSoundBuffer failed\n"); + return; + } + + // Test the buffer format against the direct sound 8 interface and create the secondary buffer. + result = tempBuffer->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*)soundbuffer); + if (FAILED(result)) + { + printf("SoundSystemWindows QueryInterface failed\n"); + return; + } + + // Release the temporary buffer. + tempBuffer->Release(); + tempBuffer = 0; + + + // Lock the secondary buffer to write wave data into it. + result = (*soundbuffer)->Lock(0, length, (void**)&bufferPtr, (DWORD*)&bufferSize, NULL, 0, 0); + if (FAILED(result)) + { + printf("SoundSystemWindows lock failed\n"); + return; + //return false; + } + + // Copy the wave data into the buffer. + memcpy(bufferPtr, sound.m_pData, length); + + // Unlock the secondary buffer after the data has been written to it. + result = (*soundbuffer)->Unlock((void*)bufferPtr, bufferSize, NULL, 0); + if (FAILED(result)) + { + printf("SoundSystemWindows unlock failed\n"); + return; + } + + + (*soundbuffer)->Play(0, 0, 0); + m_buffers.push_back(soundbuffer); +} diff --git a/platforms/windows/SoundSystem_windows.hpp b/platforms/windows/SoundSystem_windows.hpp new file mode 100644 index 0000000..c25f29c --- /dev/null +++ b/platforms/windows/SoundSystem_windows.hpp @@ -0,0 +1,49 @@ +/******************************************************************** + Minecraft: Pocket Edition - Decompilation Project + Copyright (C) 2023 iProgramInCpp + + The following code is licensed under the BSD 1 clause license. + SPDX-License-Identifier: BSD-1-Clause + ********************************************************************/ + +#pragma once +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "dsound.lib") +#pragma comment(lib, "dxguid.lib") +#pragma comment(lib, "winmm.lib") + +#include +#include + +#include "SoundData.hpp" + +class SoundSystemWindows +{ +public: + SoundSystemWindows(); + ~SoundSystemWindows(); + virtual bool isAvailable(); + virtual void setListenerPos(float x, float y, float z); + virtual void setListenerAngle(float f); + virtual void load(const std::string& sound); + virtual void play(const std::string& sound); + virtual void pause(const std::string& sound); + virtual void stop(const std::string& sound); + virtual void playAt(const SoundDesc& sound, float x, float y, float z, float a, float b); +private: + HWND m_hiddenwindow; + IDirectSound8* m_directsound; + IDirectSoundBuffer* m_primarybuffer; + + std::vector m_buffers; + + void initDirectSound(); + +}; + diff --git a/source/Sound/SoundEngine.hpp b/source/Sound/SoundEngine.hpp index f6e4565..8e57cd3 100644 --- a/source/Sound/SoundEngine.hpp +++ b/source/Sound/SoundEngine.hpp @@ -14,12 +14,17 @@ #include "Random.hpp" // Platform specific type for the sound system. + +#ifdef _WIN32 +#include "../../platforms/windows/SoundSystem_windows.hpp" +#define SOUND_SYSTEM_TYPE SoundSystemWindows +#else #define SOUND_SYSTEM_TYPE SoundSystem +#endif + //#define SOUND_SYSTEM_TYPE SoundSystemSL -//#define SOUND_SYSTEM_TYPE SoundSystemWindows // @TODO: SoundSystemSL - Use this for the Android port -// @TODO: SoundSystemWindows - Sound system for Windows. class SoundEngine { diff --git a/windows_vs/minecraftcpp.vcxproj b/windows_vs/minecraftcpp.vcxproj index 4ac0808..2d77711 100644 --- a/windows_vs/minecraftcpp.vcxproj +++ b/windows_vs/minecraftcpp.vcxproj @@ -29,6 +29,7 @@ + @@ -318,6 +319,7 @@ + diff --git a/windows_vs/minecraftcpp.vcxproj.filters b/windows_vs/minecraftcpp.vcxproj.filters index 08450cd..b8e7d06 100644 --- a/windows_vs/minecraftcpp.vcxproj.filters +++ b/windows_vs/minecraftcpp.vcxproj.filters @@ -1056,6 +1056,9 @@ Source Files\App + + Source Files\App + @@ -1916,6 +1919,9 @@ Header Files\App + + Header Files\App + From 311ab75ee472b6e3ac9d335e37e9d3884fa60e7e Mon Sep 17 00:00:00 2001 From: f Date: Mon, 31 Jul 2023 12:58:45 +0200 Subject: [PATCH 2/2] Make windows soundsystem use GetHWND made invisible window before, was not needed --- platforms/windows/SoundSystem_windows.cpp | 39 ++++------------------- platforms/windows/SoundSystem_windows.hpp | 4 --- 2 files changed, 6 insertions(+), 37 deletions(-) diff --git a/platforms/windows/SoundSystem_windows.cpp b/platforms/windows/SoundSystem_windows.cpp index 7e3d49e..7dc6255 100644 --- a/platforms/windows/SoundSystem_windows.cpp +++ b/platforms/windows/SoundSystem_windows.cpp @@ -6,43 +6,14 @@ SPDX-License-Identifier: BSD-1-Clause ********************************************************************/ + +#include "../../source/Base/Utils.hpp" #include "SoundSystem_windows.hpp" SoundSystemWindows::SoundSystemWindows() { printf("Init SoundSystemWindows\n"); - WNDCLASSA WndClass; - - memset(&WndClass, 0, sizeof(WndClass)); - WndClass.lpfnWndProc = DefWindowProcA; - WndClass.hInstance = GetModuleHandleA(NULL); - WndClass.lpszClassName = "SoundWindow"; - RegisterClassA(&WndClass); - m_hiddenwindow = CreateWindowExA( - 0, - "SoundWindow", - "SoundWindow", - 0x80000000, - 0, - 0, - 0, - 0, - 0, - 0, - WndClass.hInstance, - 0); - if (!m_hiddenwindow) { - printf("SoundSystemWindows cannot create hidden window for directsound8\n"); - return; - } - - initDirectSound(); - -} - -void SoundSystemWindows::initDirectSound() -{ HRESULT result; DSBUFFERDESC bufferDesc; @@ -54,7 +25,7 @@ void SoundSystemWindows::initDirectSound() return; } - result = m_directsound->SetCooperativeLevel(m_hiddenwindow, DSSCL_NORMAL); + result = m_directsound->SetCooperativeLevel(GetHWND(), DSSCL_NORMAL); if (FAILED(result)) { printf("SoundSystemWindows failed set cooperation level\n"); @@ -75,13 +46,15 @@ void SoundSystemWindows::initDirectSound() printf("SoundSystemWindows failed to create primary sound buffer\n"); return; } - + } + SoundSystemWindows::~SoundSystemWindows() { printf("Destroying SoundSystemWindows\n"); + m_directsound->Release(); } diff --git a/platforms/windows/SoundSystem_windows.hpp b/platforms/windows/SoundSystem_windows.hpp index c25f29c..f3842b1 100644 --- a/platforms/windows/SoundSystem_windows.hpp +++ b/platforms/windows/SoundSystem_windows.hpp @@ -37,13 +37,9 @@ public: virtual void stop(const std::string& sound); virtual void playAt(const SoundDesc& sound, float x, float y, float z, float a, float b); private: - HWND m_hiddenwindow; IDirectSound8* m_directsound; IDirectSoundBuffer* m_primarybuffer; std::vector m_buffers; - - void initDirectSound(); - };