From 40700a2de19093564647ea3fa0ba1213d2dd6ecf Mon Sep 17 00:00:00 2001 From: turanszkij Date: Sat, 5 Oct 2019 18:19:13 +0100 Subject: [PATCH] audio system rewrite, added 3D audio support --- Documentation/ScriptingAPI-Documentation.md | 61 ++- Documentation/WickedEngine-Documentation.md | 9 + README.md | 23 +- Tests/Tests.cpp | 17 +- WickedEngine/CommonInclude.h | 3 + WickedEngine/WickedEngine.h | 2 +- WickedEngine/WickedEngine_SHARED.vcxitems | 8 +- .../WickedEngine_SHARED.vcxitems.filters | 24 +- WickedEngine/wiAudio.cpp | 424 ++++++++++++++++ WickedEngine/wiAudio.h | 59 +++ WickedEngine/wiAudio_BindLua.cpp | 463 ++++++++++++++++++ WickedEngine/wiAudio_BindLua.h | 93 ++++ WickedEngine/wiGraphicsResource.h | 3 - WickedEngine/wiHelper.cpp | 20 - WickedEngine/wiHelper.h | 20 - WickedEngine/wiInitializer.cpp | 2 +- WickedEngine/wiLua.cpp | 14 +- WickedEngine/wiLua.h | 4 + WickedEngine/wiResourceManager.cpp | 16 +- WickedEngine/wiResourceManager.h | 2 +- WickedEngine/wiResourceManager_BindLua.cpp | 18 +- WickedEngine/wiSound.cpp | 356 -------------- WickedEngine/wiSound.h | 100 ---- WickedEngine/wiSound_BindLua.cpp | 152 ------ WickedEngine/wiSound_BindLua.h | 48 -- WickedEngine/wiVersion.cpp | 4 +- features.txt | 2 +- 27 files changed, 1169 insertions(+), 778 deletions(-) create mode 100644 WickedEngine/wiAudio.cpp create mode 100644 WickedEngine/wiAudio.h create mode 100644 WickedEngine/wiAudio_BindLua.cpp create mode 100644 WickedEngine/wiAudio_BindLua.h delete mode 100644 WickedEngine/wiSound.cpp delete mode 100644 WickedEngine/wiSound.h delete mode 100644 WickedEngine/wiSound_BindLua.cpp delete mode 100644 WickedEngine/wiSound_BindLua.h diff --git a/Documentation/ScriptingAPI-Documentation.md b/Documentation/ScriptingAPI-Documentation.md index 423bedfe0..89a9586da 100644 --- a/Documentation/ScriptingAPI-Documentation.md +++ b/Documentation/ScriptingAPI-Documentation.md @@ -16,9 +16,7 @@ The documentation completion is still pending.... 3. MovingTexAnim 4. DrawRecAnim 3. Texture - 4. Sound - 1. SoundEffect - 2. Music + 4. Audio 5. Vector 6. Matrix 7. Scene System (using entity-component system) @@ -280,21 +278,50 @@ Animate sprite frame by frame. Just holds texture information in VRAM. - [void-constructor]Texture() -### Sound -Load a Sound file, either sound effect or music. -- [outer]SoundVolume(opt float volume) -- [outer]MusicVolume(opt float volume) -- [void-constructor]Sound() -- Play(opt int delay) -- Stop() +### Audio +Loads and plays an audio files. +- [outer]audio -- the audio device +- CreateSound(string filename, Sound sound) : bool -- Creates a sound file, returns true if successful, false otherwise +- CreateSoundInstance(Sound sound, SoundInstance soundinstance) : bool -- Creates a sound instance that can be replayed, returns true if successful, false otherwise +- Destroy(Sound sound) +- Destroy(SoundInsance soundinstance) +- Play(SoundInsance soundinstance) +- Pause(SoundInsance soundinstance) +- Stop(SoundInsance soundinstance) +- GetVolume(opt SoundInsance soundinstance) : float -- returns the volume of a soundinstance. If soundinstance is not provided, returns the master volume +- SetVolume(float volume, opt SoundInsance soundinstance) -- sets the volume of a soundinstance. If soundinstance is not provided, sets the master volume +- GetSubmixVolume(int submixtype) : float -- returns the volume of the submix group +- SetSubmixVolume(int submixtype, float volume) -- sets the volume for a submix group +- Update3D(SoundInstance soundinstance, SoundInstance3D instance3D) -- adds 3D effect to the sound instance -#### SoundEffect -Sound Effects are for playing a sound file once. Inherits the methods from Sound. -- [constructor]SoundEffect(string soundFile) +#### Sound +An audio file. Can be instanced several times via SoundInstance. +- [constructor]Sound() -- creates an empty sound. Use the audio device to load sounds from files -#### Music -Music is for playing sound files in the background, along with sound effects. Inherits the methods from Sound. -- [constructor]Music(string soundFile) +#### SoundInstance +An audio file instance that can be played. +- [constructor]SoundInstance() -- creates an empty soundinstance. Use the audio device to clone sounds +- SetSubmixType(int submixtype) -- set a submix type group (default is SUBMIX_TYPE_SOUNDEFFECT) + +#### SoundInstance3D +Describes the relation between a sound instance and a listener in a 3D world +- [constructor]SoundInstance3D() -- creates the 3D relation object. By default, the listener and emitter are on the same position, and that disables the 3D effect +- SetListenerPos(Vector value) +- SetListenerUp(Vector value) +- SetListenerFront(Vector value) +- SetListenerVelocity(Vector value) +- SetEmitterPos(Vector value) +- SetEmitterUp(Vector value) +- SetEmitterFront(Vector value) +- SetEmitterVelocity(Vector value) +- SetEmitterRadius(float radius) + +#### Submix Types +The submix types group sound instances together to be controlled together +- [outer]SUBMIX_TYPE_SOUNDEFFECT : int -- sound effect group +- [outer]SUBMIX_TYPE_MUSIC : int -- music group +- [outer]SUBMIX_TYPE_USER0 : int -- user submix group +- [outer]SUBMIX_TYPE_USER1 : int -- user submix group ### Vector A four component floating point vector. Provides efficient calculations with SIMD support. @@ -704,7 +731,7 @@ Describes a touch contact point - [outer]GAMEPAD_ANALOG_TRIGGER_R : int ### ResourceManager -Stores and manages resources such as textures, sounds and shaders. +Stores and manages resources such as textures, audio and shaders. - [outer]globalResources : Resource - [void-constructor]Resource() - Get(string name) diff --git a/Documentation/WickedEngine-Documentation.md b/Documentation/WickedEngine-Documentation.md index 57c5dc8bb..1b3e6454a 100644 --- a/Documentation/WickedEngine-Documentation.md +++ b/Documentation/WickedEngine-Documentation.md @@ -98,6 +98,15 @@ The following quick reference shows an overview of common resource formats and s ![InformationSheet](information_sheet.png) +## Audio +The audio system handles audio playback and spatial audio. +- wiAudio + - The namespace that is a collection of audio related functionality +- Sound + - Represents a sound file in memory. Load a sound file via wiAudio interface. +- SoundInstance + - An instance of a sound file that can be played and controlled in various ways through the wiAudio interface. + ## Helpers A collection of engine-level helper classes diff --git a/README.md b/README.md index 0390dbbc2..c26f2d6d5 100644 --- a/README.md +++ b/README.md @@ -115,13 +115,13 @@ main.ActivatePath(&myMenuScreen); // activate the menu, the previous path (myGam wiSprite mySprite("image.png"); // There are many utilities, such as a "sprite" helper class myMenuScreen.addSprite(&mySprite); // The 2D render path is ready to handle sprite and font rendering for you -wiSoundEffect soundEffect("explosion.wav"); // you can load sound effects, or music -soundEffect.Play(); // you can play sounds -soundEffect.Stop(); // you can stop sounds - -wiMusic myMusic("music.wav"); // music is the same as sound effects, but they can be controlled independently -myMusic.Play(); // plays a music -wiMusic::SetVolume(0.5f); // set volume for every music, but don't modify sound effect volume +wiAudio::Sound mySound; +wiAudio::CreateSound("explosion.wav", &mySound); // Loads a sound file +wiAudio::SoundInstance mySoundInstance; +wiAudio::CreateSoundInstance(&mySound, &mySoundInstance); // Instances the sound file, it can be played now +wiAudio::Play(&mySoundInstance); // Play the sound instance +wiAudio::SetVolume(0.6, &mySoundInstance); // Set the volume of this soundinstance +wiAudio::SetVolume(0.2); // Set the master volume if (wiInputManager::press(VK_SPACE)) { soundEffect.Stop(); } // You can check if a button is pressed or not (this only triggers once) if (wiInputManager::down(VK_SPACE)) { soundEffect.Play(); } // You can check if a button is pushed down or not (this triggers repeatedly) @@ -159,8 +159,13 @@ getprops(scene); -- prints the Scene class methods getprops(path); -- prints the deferred render path methods -- Play a sound: -sound = SoundEffect("whoosh.wav"); -sound.Play(); +sound = Sound() +audio.CreateSound("explosion.wav", sound) +soundinstance = SoundInstance() +audio.CreateSoundInstance(sound, soundinstance) -- several instances can be created from one file +audio.Play(soundinstance) +audio.SetVolume(0.6, soundinstance) -- sets the volume of this soundinstance +audio.SetVolume(0.2) -- sets the master volume -- Check for input: if(input.press(VK_LEFT)) then diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp index e7ea8c9e1..92bf32667 100644 --- a/Tests/Tests.cpp +++ b/Tests/Tests.cpp @@ -40,6 +40,8 @@ TestsRenderer::TestsRenderer() label->SetPos(XMFLOAT2(screenW / 2.f - label->scale.x / 2.f, screenH*0.95f)); GetGUI().AddWidget(label); + static wiAudio::Sound* sound = nullptr; + static wiAudio::SoundInstance* soundinstance = nullptr; wiButton* audioTest = new wiButton("AudioTest"); audioTest->SetText("Play Test Audio"); @@ -48,17 +50,24 @@ TestsRenderer::TestsRenderer() audioTest->SetColor(wiColor(255, 205, 43, 200), wiWidget::WIDGETSTATE::IDLE); audioTest->SetColor(wiColor(255, 235, 173, 255), wiWidget::WIDGETSTATE::FOCUS); audioTest->OnClick([=](wiEventArgs args) { - static wiMusic music("sound/music.wav"); static bool playing = false; + if (sound == nullptr) + { + sound = new wiAudio::Sound; + wiAudio::CreateSound("sound/music.wav", sound); + soundinstance = new wiAudio::SoundInstance; + wiAudio::CreateSoundInstance(sound, soundinstance); + } + if (playing) { - music.Stop(); + wiAudio::Stop(soundinstance); audioTest->SetText("Play Test Audio"); } else { - music.Play(); + wiAudio::Play(soundinstance); audioTest->SetText("Stop Test Audio"); } @@ -74,7 +83,7 @@ TestsRenderer::TestsRenderer() volume->SetColor(wiColor(255, 205, 43, 200), wiWidget::WIDGETSTATE::IDLE); volume->SetColor(wiColor(255, 235, 173, 255), wiWidget::WIDGETSTATE::FOCUS); volume->OnSlide([](wiEventArgs args) { - wiMusic::SetVolume(args.fValue / 100.0f); + wiAudio::SetVolume(args.fValue / 100.0f, soundinstance); }); GetGUI().AddWidget(volume); diff --git a/WickedEngine/CommonInclude.h b/WickedEngine/CommonInclude.h index 240e79e2a..204997060 100644 --- a/WickedEngine/CommonInclude.h +++ b/WickedEngine/CommonInclude.h @@ -38,5 +38,8 @@ using namespace DirectX::PackedVector; static const XMFLOAT4X4 IDENTITYMATRIX = XMFLOAT4X4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); +typedef uint64_t wiCPUHandle; +static const wiCPUHandle WI_NULL_HANDLE = 0; + #endif //WICKEDENGINE_COMMONINCLUDE_H diff --git a/WickedEngine/WickedEngine.h b/WickedEngine/WickedEngine.h index 722cea52f..3430fc071 100644 --- a/WickedEngine/WickedEngine.h +++ b/WickedEngine/WickedEngine.h @@ -35,7 +35,7 @@ #include "wiXInput.h" #include "wiRawInput.h" #include "wiMath.h" -#include "wiSound.h" +#include "wiAudio.h" #include "wiResourceManager.h" #include "wiTimer.h" #include "wiHelper.h" diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems b/WickedEngine/WickedEngine_SHARED.vcxitems index dcfe16ec8..0b4a21f71 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems +++ b/WickedEngine/WickedEngine_SHARED.vcxitems @@ -259,6 +259,8 @@ + + @@ -357,8 +359,6 @@ - - @@ -522,6 +522,8 @@ + + @@ -687,8 +689,6 @@ - - diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems.filters b/WickedEngine/WickedEngine_SHARED.vcxitems.filters index 9060bd484..1f00dbde2 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems.filters +++ b/WickedEngine/WickedEngine_SHARED.vcxitems.filters @@ -201,9 +201,6 @@ ENGINE\Scripting\LuaBindings - - ENGINE\Scripting\LuaBindings - ENGINE\Scripting\LuaBindings @@ -900,9 +897,6 @@ ENGINE\Network - - ENGINE\Audio - ENGINE\Graphics @@ -1134,6 +1128,12 @@ ENGINE\Graphics\GPUMapping + + ENGINE\Audio + + + ENGINE\Scripting\LuaBindings + @@ -1280,9 +1280,6 @@ ENGINE\Scripting\LuaBindings - - ENGINE\Scripting\LuaBindings - ENGINE\Scripting\LuaBindings @@ -1751,9 +1748,6 @@ ENGINE\Network - - ENGINE\Audio - ENGINE\Graphics @@ -1907,6 +1901,12 @@ ENGINE\Scripting\LuaBindings + + ENGINE\Audio + + + ENGINE\Scripting\LuaBindings + diff --git a/WickedEngine/wiAudio.cpp b/WickedEngine/wiAudio.cpp new file mode 100644 index 000000000..c9a9fc09e --- /dev/null +++ b/WickedEngine/wiAudio.cpp @@ -0,0 +1,424 @@ +#include "wiAudio.h" +#include "wiBackLog.h" +#include "wiHelper.h" + +#include + +#include +#include +#pragma comment(lib,"xaudio2.lib") + +#ifdef _XBOX //Big-Endian +#define fourccRIFF 'RIFF' +#define fourccDATA 'data' +#define fourccFMT 'fmt ' +#define fourccWAVE 'WAVE' +#define fourccXWMA 'XWMA' +#define fourccDPDS 'dpds' +#endif + +#ifndef _XBOX //Little-Endian +#define fourccRIFF 'FFIR' +#define fourccDATA 'atad' +#define fourccFMT ' tmf' +#define fourccWAVE 'EVAW' +#define fourccXWMA 'AMWX' +#define fourccDPDS 'sdpd' +#endif + +namespace wiAudio +{ + IXAudio2* audioEngine = nullptr; + IXAudio2MasteringVoice* masteringVoice = nullptr; + XAUDIO2_VOICE_DETAILS masteringVoiceDetails = {}; + X3DAUDIO_HANDLE audio3D = {}; + IXAudio2SubmixVoice* submixVoices[SUBMIX_TYPE_COUNT] = {}; + + Sound::~Sound() + { + Destroy(this); + } + SoundInstance::~SoundInstance() + { + Destroy(this); + } + struct SoundInternal + { + WAVEFORMATEX wfx = {}; + XAUDIO2_BUFFER buffer = {}; + }; + struct SoundInstanceInternal + { + IXAudio2SourceVoice* sourceVoice = nullptr; + XAUDIO2_VOICE_DETAILS voiceDetails = {}; + std::vector outputMatrix; + const SoundInternal* soundinternal = nullptr; + }; + + void Initialize() + { + HRESULT hr; + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + assert(SUCCEEDED(hr)); + + hr = XAudio2Create(&audioEngine, 0, XAUDIO2_DEFAULT_PROCESSOR); + assert(SUCCEEDED(hr)); + +#ifdef _DEBUG + XAUDIO2_DEBUG_CONFIGURATION debugConfig = {}; + debugConfig.TraceMask = XAUDIO2_LOG_ERRORS | XAUDIO2_LOG_WARNINGS; + debugConfig.BreakMask = XAUDIO2_LOG_ERRORS | XAUDIO2_LOG_WARNINGS; + audioEngine->SetDebugConfiguration(&debugConfig); +#endif // _DEBUG + + hr = audioEngine->CreateMasteringVoice(&masteringVoice); + assert(SUCCEEDED(hr)); + + masteringVoice->GetVoiceDetails(&masteringVoiceDetails); + + DWORD channelMask; + masteringVoice->GetChannelMask(&channelMask); + hr = X3DAudioInitialize(channelMask, X3DAUDIO_SPEED_OF_SOUND, audio3D); + assert(SUCCEEDED(hr)); + + for (int i = 0; i < SUBMIX_TYPE_COUNT; ++i) + { + audioEngine->CreateSubmixVoice( + &submixVoices[i], + masteringVoiceDetails.InputChannels, + masteringVoiceDetails.InputSampleRate, + 0, 0, 0, 0); + } + + if (SUCCEEDED(hr)) + { + wiBackLog::post("wiAudio Initialized"); + } + } + void CleanUp() + { + if (masteringVoice != nullptr) masteringVoice->DestroyVoice(); + SAFE_DELETE(masteringVoice); + SAFE_RELEASE(audioEngine); + SAFE_DELETE(audioEngine); + } + + HRESULT FindChunk(HANDLE hFile, DWORD fourcc, DWORD& dwChunkSize, DWORD& dwChunkDataPosition) + { + HRESULT hr = S_OK; + if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hFile, LARGE_INTEGER(), NULL, FILE_BEGIN)) + return HRESULT_FROM_WIN32(GetLastError()); + + DWORD dwChunkType; + DWORD dwChunkDataSize; + DWORD dwRIFFDataSize = 0; + DWORD dwFileType; + DWORD bytesRead = 0; + DWORD dwOffset = 0; + + while (hr == S_OK) + { + DWORD dwRead; + if (0 == ReadFile(hFile, &dwChunkType, sizeof(DWORD), &dwRead, NULL)) + hr = HRESULT_FROM_WIN32(GetLastError()); + + if (0 == ReadFile(hFile, &dwChunkDataSize, sizeof(DWORD), &dwRead, NULL)) + hr = HRESULT_FROM_WIN32(GetLastError()); + + switch (dwChunkType) + { + case fourccRIFF: + dwRIFFDataSize = dwChunkDataSize; + dwChunkDataSize = 4; + if (0 == ReadFile(hFile, &dwFileType, sizeof(DWORD), &dwRead, NULL)) + hr = HRESULT_FROM_WIN32(GetLastError()); + break; + + default: + LARGE_INTEGER li = LARGE_INTEGER(); + li.QuadPart = dwChunkDataSize; + if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hFile, li, NULL, FILE_CURRENT)) + return HRESULT_FROM_WIN32(GetLastError()); + } + + dwOffset += sizeof(DWORD) * 2; + + if (dwChunkType == fourcc) + { + dwChunkSize = dwChunkDataSize; + dwChunkDataPosition = dwOffset; + return S_OK; + } + + dwOffset += dwChunkDataSize; + + if (bytesRead >= dwRIFFDataSize) return S_FALSE; + + } + + return S_OK; + + } + HRESULT ReadChunkData(HANDLE hFile, void* buffer, DWORD buffersize, DWORD bufferoffset) + { + HRESULT hr = S_OK; + + LARGE_INTEGER li = LARGE_INTEGER(); + li.QuadPart = bufferoffset; + if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hFile, li, NULL, FILE_BEGIN)) + return HRESULT_FROM_WIN32(GetLastError()); + DWORD dwRead; + if (0 == ReadFile(hFile, buffer, buffersize, &dwRead, NULL)) + hr = HRESULT_FROM_WIN32(GetLastError()); + return hr; + } + + HRESULT CreateSound(const std::string& filename, Sound* sound) + { + Destroy(sound); + + std::wstring wfilename; + wiHelper::StringConvert(filename, wfilename); + + HANDLE hFile = CreateFile2( + wfilename.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + nullptr + ); + + HRESULT hr; + if (INVALID_HANDLE_VALUE == hFile) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + return hr; + } + + if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hFile, LARGE_INTEGER(), NULL, FILE_BEGIN)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + return hr; + } + + DWORD dwChunkSize; + DWORD dwChunkPosition; + + FindChunk(hFile, fourccRIFF, dwChunkSize, dwChunkPosition); + DWORD filetype; + hr = ReadChunkData(hFile, &filetype, sizeof(DWORD), dwChunkPosition); + assert(SUCCEEDED(hr)); + assert(filetype == fourccWAVE); + + SoundInternal* soundinternal = new SoundInternal; + + hr = FindChunk(hFile, fourccFMT, dwChunkSize, dwChunkPosition); + assert(SUCCEEDED(hr)); + hr = ReadChunkData(hFile, &soundinternal->wfx, dwChunkSize, dwChunkPosition); + assert(SUCCEEDED(hr)); + soundinternal->wfx.wFormatTag = WAVE_FORMAT_PCM; + + hr = FindChunk(hFile, fourccDATA, dwChunkSize, dwChunkPosition); + assert(SUCCEEDED(hr)); + + BYTE* pDataBuffer = new BYTE[dwChunkSize]; + hr = ReadChunkData(hFile, pDataBuffer, dwChunkSize, dwChunkPosition); + assert(SUCCEEDED(hr)); + + soundinternal->buffer.AudioBytes = dwChunkSize; + soundinternal->buffer.pAudioData = pDataBuffer; + soundinternal->buffer.Flags = XAUDIO2_END_OF_STREAM; + + sound->handle = (wiCPUHandle)soundinternal; + + return S_OK; + } + HRESULT CreateSoundInstance(const Sound* sound, SoundInstance* instance) + { + Destroy(instance); + + HRESULT hr; + const SoundInternal* soundinternal = (const SoundInternal*)sound->handle; + SoundInstanceInternal* instanceinternal = new SoundInstanceInternal; + instanceinternal->soundinternal = soundinternal; + + XAUDIO2_SEND_DESCRIPTOR SFXSend = { 0, submixVoices[instance->type] }; + XAUDIO2_VOICE_SENDS SFXSendList = { 1, &SFXSend }; + + hr = audioEngine->CreateSourceVoice(&instanceinternal->sourceVoice, &soundinternal->wfx, + XAUDIO2_VOICE_USEFILTER, XAUDIO2_DEFAULT_FREQ_RATIO, NULL, &SFXSendList, NULL); + if (FAILED(hr)) + { + assert(0); + return hr; + } + + instanceinternal->sourceVoice->GetVoiceDetails(&instanceinternal->voiceDetails); + + instanceinternal->outputMatrix.resize(masteringVoiceDetails.InputChannels); + + hr = instanceinternal->sourceVoice->SubmitSourceBuffer(&soundinternal->buffer); + if (FAILED(hr)) + { + assert(0); + return hr; + } + + instance->handle = (wiCPUHandle)instanceinternal; + + return S_OK; + } + void Destroy(Sound* sound) + { + if (sound != nullptr && sound->handle != WI_NULL_HANDLE) + { + SoundInternal* soundinternal = (SoundInternal*)sound->handle; + delete[] soundinternal->buffer.pAudioData; + delete soundinternal; + sound->handle = WI_NULL_HANDLE; + } + } + void Destroy(SoundInstance* instance) + { + if (instance != nullptr && instance->handle != WI_NULL_HANDLE) + { + SoundInstanceInternal* instanceinternal = (SoundInstanceInternal*)instance->handle; + instanceinternal->sourceVoice->Stop(); + instanceinternal->sourceVoice->DestroyVoice(); + delete instanceinternal; + instance->handle = WI_NULL_HANDLE; + } + } + void Play(SoundInstance* instance) + { + if (instance != nullptr && instance->handle != WI_NULL_HANDLE) + { + SoundInstanceInternal* instanceinternal = (SoundInstanceInternal*)instance->handle; + HRESULT hr = instanceinternal->sourceVoice->Start(); + assert(SUCCEEDED(hr)); + } + } + void Pause(SoundInstance* instance) + { + if (instance != nullptr && instance->handle != WI_NULL_HANDLE) + { + SoundInstanceInternal* instanceinternal = (SoundInstanceInternal*)instance->handle; + HRESULT hr = instanceinternal->sourceVoice->Stop(); // preserves cursor position + assert(SUCCEEDED(hr)); + } + } + void Stop(SoundInstance* instance) + { + if (instance != nullptr && instance->handle != WI_NULL_HANDLE) + { + SoundInstanceInternal* instanceinternal = (SoundInstanceInternal*)instance->handle; + HRESULT hr = instanceinternal->sourceVoice->Stop(); // preserves cursor position + assert(SUCCEEDED(hr)); + hr = instanceinternal->sourceVoice->FlushSourceBuffers(); // reset submitted audio buffer + assert(SUCCEEDED(hr)); + hr = instanceinternal->sourceVoice->SubmitSourceBuffer(&instanceinternal->soundinternal->buffer); // resubmit + assert(SUCCEEDED(hr)); + } + } + void SetVolume(float volume, SoundInstance* instance) + { + if (instance == nullptr || instance->handle == WI_NULL_HANDLE) + { + HRESULT hr = masteringVoice->SetVolume(volume); + assert(SUCCEEDED(hr)); + } + else + { + SoundInstanceInternal* instanceinternal = (SoundInstanceInternal*)instance->handle; + HRESULT hr = instanceinternal->sourceVoice->SetVolume(volume); + assert(SUCCEEDED(hr)); + } + } + float GetVolume(const SoundInstance* instance) + { + float volume = 0; + if (instance == nullptr || instance->handle == WI_NULL_HANDLE) + { + masteringVoice->GetVolume(&volume); + } + else + { + const SoundInstanceInternal* instanceinternal = (const SoundInstanceInternal*)instance->handle; + instanceinternal->sourceVoice->GetVolume(&volume); + } + return volume; + } + + void SetSubmixVolume(SUBMIX_TYPE type, float volume) + { + submixVoices[type]->SetVolume(volume); + } + float GetSubmixVolume(SUBMIX_TYPE type) + { + float volume; + submixVoices[type]->GetVolume(&volume); + return volume; + } + + void Update3D(SoundInstance* instance, const SoundInstance3D& instance3D) + { + if (instance != nullptr && instance->handle != WI_NULL_HANDLE) + { + SoundInstanceInternal* instanceinternal = (SoundInstanceInternal*)instance->handle; + + X3DAUDIO_LISTENER listener = {}; + listener.Position = instance3D.listenerPos; + listener.OrientFront = instance3D.listenerFront; + listener.OrientTop = instance3D.listenerUp; + listener.Velocity = instance3D.listenerVelocity; + + X3DAUDIO_EMITTER emitter = {}; + emitter.Position = instance3D.emitterPos; + emitter.OrientFront = instance3D.emitterFront; + emitter.OrientTop = instance3D.emitterUp; + emitter.Velocity = instance3D.emitterVelocity; + emitter.CurveDistanceScaler = 1; + emitter.ChannelCount = 1; + emitter.InnerRadius = instance3D.emitterRadius; + + UINT32 flags = 0; + flags |= X3DAUDIO_CALCULATE_MATRIX; + flags |= X3DAUDIO_CALCULATE_LPF_DIRECT; + flags |= X3DAUDIO_CALCULATE_REVERB; + flags |= X3DAUDIO_CALCULATE_DOPPLER; + //flags |= X3DAUDIO_CALCULATE_DELAY; + //flags |= X3DAUDIO_CALCULATE_LPF_REVERB; + //flags |= X3DAUDIO_CALCULATE_EMITTER_ANGLE; + //flags |= X3DAUDIO_CALCULATE_ZEROCENTER; + //flags |= X3DAUDIO_CALCULATE_REDIRECT_TO_LFE; + + X3DAUDIO_DSP_SETTINGS settings = {}; + settings.SrcChannelCount = instanceinternal->voiceDetails.InputChannels; + settings.DstChannelCount = masteringVoiceDetails.InputChannels; + settings.pMatrixCoefficients = instanceinternal->outputMatrix.data(); + + X3DAudioCalculate(audio3D, &listener, &emitter, flags, &settings); + + HRESULT hr; + hr = instanceinternal->sourceVoice->SetOutputMatrix( + submixVoices[instance->type], + settings.SrcChannelCount, + settings.DstChannelCount, + settings.pMatrixCoefficients + ); + assert(SUCCEEDED(hr)); + + hr = instanceinternal->sourceVoice->SetFrequencyRatio(settings.DopplerFactor); + assert(SUCCEEDED(hr)); + + XAUDIO2_FILTER_PARAMETERS filterParams = + { + LowPassFilter, + 2.0f * sinf(X3DAUDIO_PI / 6.0f * settings.LPFDirectCoefficient), + 1.0f + }; + hr = instanceinternal->sourceVoice->SetFilterParameters(&filterParams); + assert(SUCCEEDED(hr)); + } + } +} diff --git a/WickedEngine/wiAudio.h b/WickedEngine/wiAudio.h new file mode 100644 index 000000000..f6dea5f4d --- /dev/null +++ b/WickedEngine/wiAudio.h @@ -0,0 +1,59 @@ +#pragma once +#include "CommonInclude.h" + +#include + +namespace wiAudio +{ + void Initialize(); + void CleanUp(); + + enum SUBMIX_TYPE + { + SUBMIX_TYPE_SOUNDEFFECT, + SUBMIX_TYPE_MUSIC, + SUBMIX_TYPE_USER0, + SUBMIX_TYPE_USER1, + SUBMIX_TYPE_COUNT, + }; + + struct Sound + { + wiCPUHandle handle = WI_NULL_HANDLE; + ~Sound(); + }; + struct SoundInstance + { + SUBMIX_TYPE type = SUBMIX_TYPE_SOUNDEFFECT; + wiCPUHandle handle = WI_NULL_HANDLE; + ~SoundInstance(); + }; + + HRESULT CreateSound(const std::string& filename, Sound* sound); + HRESULT CreateSoundInstance(const Sound* sound, SoundInstance* instance); + void Destroy(Sound* sound); + void Destroy(SoundInstance* instance); + + void Play(SoundInstance* instance); + void Pause(SoundInstance* instance); + void Stop(SoundInstance* instance); + void SetVolume(float volume, SoundInstance* instance = nullptr); + float GetVolume(const SoundInstance* instance = nullptr); + + void SetSubmixVolume(SUBMIX_TYPE type, float volume); + float GetSubmixVolume(SUBMIX_TYPE type); + + struct SoundInstance3D + { + XMFLOAT3 listenerPos = XMFLOAT3(0, 0, 0); + XMFLOAT3 listenerUp = XMFLOAT3(0, 1, 0); + XMFLOAT3 listenerFront = XMFLOAT3(0, 0, 1); + XMFLOAT3 listenerVelocity = XMFLOAT3(0, 0, 0); + XMFLOAT3 emitterPos = XMFLOAT3(0, 0, 0); + XMFLOAT3 emitterUp = XMFLOAT3(0, 1, 0); + XMFLOAT3 emitterFront = XMFLOAT3(0, 0, 1); + XMFLOAT3 emitterVelocity = XMFLOAT3(0, 0, 0); + float emitterRadius = 0; + }; + void Update3D(SoundInstance* instance, const SoundInstance3D& instance3D); +} diff --git a/WickedEngine/wiAudio_BindLua.cpp b/WickedEngine/wiAudio_BindLua.cpp new file mode 100644 index 000000000..9066b179f --- /dev/null +++ b/WickedEngine/wiAudio_BindLua.cpp @@ -0,0 +1,463 @@ +#include "wiAudio_BindLua.h" +#include "wiAudio.h" +#include "Vector_BindLua.h" + +const char wiAudio_BindLua::className[] = "Audio"; + +Luna::FunctionType wiAudio_BindLua::methods[] = { + lunamethod(wiAudio_BindLua, CreateSound), + lunamethod(wiAudio_BindLua, CreateSoundInstance), + lunamethod(wiAudio_BindLua, Destroy), + lunamethod(wiAudio_BindLua, Play), + lunamethod(wiAudio_BindLua, Pause), + lunamethod(wiAudio_BindLua, Stop), + lunamethod(wiAudio_BindLua, GetVolume), + lunamethod(wiAudio_BindLua, SetVolume), + lunamethod(wiAudio_BindLua, GetSubmixVolume), + lunamethod(wiAudio_BindLua, SetSubmixVolume), + lunamethod(wiAudio_BindLua, Update3D), + { NULL, NULL } +}; +Luna::PropertyType wiAudio_BindLua::properties[] = { + { NULL, NULL } +}; + +int wiAudio_BindLua::CreateSound(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + wiSound_BindLua* sound = Luna::lightcheck(L, 2); + if (sound != nullptr) + { + HRESULT hr = wiAudio::CreateSound(wiLua::SGetString(L, 1), sound->sound); + wiLua::SSetBool(L, SUCCEEDED(hr)); + } + else + { + wiLua::SError(L, "CreateSound(string filename, Sound sound) second argument is not a Sound!"); + } + } + else + wiLua::SError(L, "CreateSound(string filename, Sound sound) not enough arguments!"); + return 0; +} +int wiAudio_BindLua::CreateSoundInstance(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + wiSound_BindLua* sound = Luna::lightcheck(L, 1); + wiSoundInstance_BindLua* soundinstance = Luna::lightcheck(L, 2); + if (sound != nullptr && soundinstance != nullptr) + { + HRESULT hr = wiAudio::CreateSoundInstance(sound->sound, &soundinstance->soundinstance); + wiLua::SSetBool(L, SUCCEEDED(hr)); + return 1; + } + else + { + wiLua::SError(L, "CreateSoundInstance(Sound sound, SoundInstance soundinstance) argument types don't match!"); + } + } + else + wiLua::SError(L, "CreateSoundInstance(Sound sound, SoundInstance soundinstance) not enough arguments!"); + return 0; +} +int wiAudio_BindLua::Destroy(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + wiSound_BindLua* sound = Luna::lightcheck(L, 1); + if (sound != nullptr) + { + wiAudio::Destroy(sound->sound); + } + else + { + wiSoundInstance_BindLua* soundinstance = Luna::lightcheck(L, 1); + if (soundinstance != nullptr) + { + wiAudio::Destroy(&soundinstance->soundinstance); + } + else + { + wiLua::SError(L, "Destroy(Sound sound); Destroy(SoundInstance soundinstance) argument types mismatch!"); + } + } + } + else + wiLua::SError(L, "Destroy(Sound sound); Destroy(SoundInstance soundinstance) not enough arguments!"); + return 0; +} +int wiAudio_BindLua::Play(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + wiSoundInstance_BindLua* soundinstance = Luna::lightcheck(L, 1); + if (soundinstance != nullptr) + { + wiAudio::Play(&soundinstance->soundinstance); + } + else + { + wiLua::SError(L, "Play(SoundInstance soundinstance) argument is not a SoundInstance!"); + } + } + else + wiLua::SError(L, "Play(SoundInstance soundinstance) not enough arguments!"); + return 0; +} +int wiAudio_BindLua::Pause(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + wiSoundInstance_BindLua* soundinstance = Luna::lightcheck(L, 1); + if (soundinstance != nullptr) + { + wiAudio::Pause(&soundinstance->soundinstance); + } + else + { + wiLua::SError(L, "Pause(SoundInstance soundinstance) argument is not a SoundInstance!"); + } + } + else + wiLua::SError(L, "Pause(SoundInstance soundinstance) not enough arguments!"); + return 0; +} +int wiAudio_BindLua::Stop(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + wiSoundInstance_BindLua* soundinstance = Luna::lightcheck(L, 1); + if (soundinstance != nullptr) + { + wiAudio::Stop(&soundinstance->soundinstance); + } + else + { + wiLua::SError(L, "Stop(SoundInstance soundinstance) argument is not a SoundInstance!"); + } + } + else + wiLua::SError(L, "Stop(SoundInstance soundinstance) not enough arguments!"); + return 0; +} +int wiAudio_BindLua::GetVolume(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + wiSoundInstance_BindLua* soundinstance = Luna::lightcheck(L, 1); + float volume = wiAudio::GetVolume(soundinstance == nullptr ? nullptr : &soundinstance->soundinstance); + wiLua::SSetFloat(L, volume); + return 1; + } + else + wiLua::SError(L, "GetVolume(opt SoundInstance soundinstance) not enough arguments!"); + return 0; +} +int wiAudio_BindLua::SetVolume(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + float volume = wiLua::SGetFloat(L, 1); + wiSoundInstance_BindLua* soundinstance = Luna::lightcheck(L, 2); + wiAudio::SetVolume(volume, soundinstance == nullptr ? nullptr : &soundinstance->soundinstance); + return 0; + } + else + wiLua::SError(L, "SetVolume(float volume, opt SoundInstance soundinstance) not enough arguments!"); + return 0; +} +int wiAudio_BindLua::GetSubmixVolume(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + wiAudio::SUBMIX_TYPE type = (wiAudio::SUBMIX_TYPE)wiLua::SGetInt(L, 1); + float volume = wiAudio::GetSubmixVolume(type); + wiLua::SSetFloat(L, volume); + return 1; + } + else + wiLua::SError(L, "GetSubmixVolume(int submixtype) not enough arguments!"); + return 0; +} +int wiAudio_BindLua::SetSubmixVolume(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 1) + { + wiAudio::SUBMIX_TYPE type = (wiAudio::SUBMIX_TYPE)wiLua::SGetInt(L, 1); + float volume = wiLua::SGetFloat(L, 2); + wiAudio::SetSubmixVolume(type, volume); + return 0; + } + else + wiLua::SError(L, "SetSubmixVolume(int submixtype, float volume) not enough arguments!"); + return 0; +} +int wiAudio_BindLua::Update3D(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 1) + { + wiSoundInstance_BindLua* soundinstance = Luna::lightcheck(L, 1); + wiSoundInstance3D_BindLua* soundinstance3D = Luna::lightcheck(L, 2); + if (soundinstance != nullptr && soundinstance3D != nullptr) + { + wiAudio::Update3D(&soundinstance->soundinstance, soundinstance3D->soundinstance3D); + } + else + { + wiLua::SError(L, "Update3D(SoundInstance soundinstance, SoundInstance3D instance3D) argument types mismatch!"); + } + } + else + wiLua::SError(L, "Update3D(SoundInstance soundinstance, SoundInstance3D instance3D) not enough arguments!"); + return 0; +} + +void wiAudio_BindLua::Bind() +{ + static bool initialized = false; + if (!initialized) + { + initialized = true; + Luna::Register(wiLua::GetGlobal()->GetLuaState()); + wiLua::GetGlobal()->RunText("audio = Audio()"); + + wiSound_BindLua::Bind(); + wiSoundInstance_BindLua::Bind(); + wiSoundInstance3D_BindLua::Bind(); + } +} + + + + +const char wiSound_BindLua::className[] = "Sound"; + +Luna::FunctionType wiSound_BindLua::methods[] = { + { NULL, NULL } +}; +Luna::PropertyType wiSound_BindLua::properties[] = { + { NULL, NULL } +}; + +void wiSound_BindLua::Bind() +{ + static bool initialized = false; + if (!initialized) + { + initialized = true; + Luna::Register(wiLua::GetGlobal()->GetLuaState()); + } +} + + + + +const char wiSoundInstance_BindLua::className[] = "SoundInstance"; + +Luna::FunctionType wiSoundInstance_BindLua::methods[] = { + lunamethod(wiSoundInstance_BindLua, SetSubmixType), + { NULL, NULL } +}; +Luna::PropertyType wiSoundInstance_BindLua::properties[] = { + { NULL, NULL } +}; + +int wiSoundInstance_BindLua::SetSubmixType(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + wiAudio::SUBMIX_TYPE type = (wiAudio::SUBMIX_TYPE)wiLua::SGetInt(L, 1); + soundinstance.type = type; + } + else + wiLua::SError(L, "SetSubmixType(int submixtype) not enough arguments!"); + return 0; +} + +void wiSoundInstance_BindLua::Bind() +{ + static bool initialized = false; + if (!initialized) + { + initialized = true; + Luna::Register(wiLua::GetGlobal()->GetLuaState()); + } +} + + + + +const char wiSoundInstance3D_BindLua::className[] = "SoundInstance3D"; + +Luna::FunctionType wiSoundInstance3D_BindLua::methods[] = { + lunamethod(wiSoundInstance3D_BindLua, SetListenerPos), + lunamethod(wiSoundInstance3D_BindLua, SetListenerUp), + lunamethod(wiSoundInstance3D_BindLua, SetListenerFront), + lunamethod(wiSoundInstance3D_BindLua, SetListenerVelocity), + lunamethod(wiSoundInstance3D_BindLua, SetEmitterPos), + lunamethod(wiSoundInstance3D_BindLua, SetEmitterUp), + lunamethod(wiSoundInstance3D_BindLua, SetEmitterFront), + lunamethod(wiSoundInstance3D_BindLua, SetEmitterVelocity), + lunamethod(wiSoundInstance3D_BindLua, SetEmitterRadius), + { NULL, NULL } +}; +Luna::PropertyType wiSoundInstance3D_BindLua::properties[] = { + { NULL, NULL } +}; + +int wiSoundInstance3D_BindLua::SetListenerPos(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec != nullptr) + { + XMStoreFloat3(&soundinstance3D.listenerPos, vec->vector); + } + } + else + wiLua::SError(L, "SetListenerPos(Vector value) not enough arguments!"); + return 0; +} +int wiSoundInstance3D_BindLua::SetListenerUp(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec != nullptr) + { + XMStoreFloat3(&soundinstance3D.listenerUp, vec->vector); + } + } + else + wiLua::SError(L, "SetListenerUp(Vector value) not enough arguments!"); + return 0; +} +int wiSoundInstance3D_BindLua::SetListenerFront(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec != nullptr) + { + XMStoreFloat3(&soundinstance3D.listenerFront, vec->vector); + } + } + else + wiLua::SError(L, "SetListenerFront(Vector value) not enough arguments!"); + return 0; +} +int wiSoundInstance3D_BindLua::SetListenerVelocity(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec != nullptr) + { + XMStoreFloat3(&soundinstance3D.listenerVelocity, vec->vector); + } + } + else + wiLua::SError(L, "SetListenerVelocity(Vector value) not enough arguments!"); + return 0; +} + +int wiSoundInstance3D_BindLua::SetEmitterPos(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec != nullptr) + { + XMStoreFloat3(&soundinstance3D.emitterPos, vec->vector); + } + } + else + wiLua::SError(L, "SetEmitterPos(Vector value) not enough arguments!"); + return 0; +} +int wiSoundInstance3D_BindLua::SetEmitterUp(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec != nullptr) + { + XMStoreFloat3(&soundinstance3D.emitterUp, vec->vector); + } + } + else + wiLua::SError(L, "SetEmitterUp(Vector value) not enough arguments!"); + return 0; +} +int wiSoundInstance3D_BindLua::SetEmitterFront(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec != nullptr) + { + XMStoreFloat3(&soundinstance3D.emitterFront, vec->vector); + } + } + else + wiLua::SError(L, "SetEmitterFront(Vector value) not enough arguments!"); + return 0; +} +int wiSoundInstance3D_BindLua::SetEmitterVelocity(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Vector_BindLua* vec = Luna::lightcheck(L, 1); + if (vec != nullptr) + { + XMStoreFloat3(&soundinstance3D.emitterVelocity, vec->vector); + } + } + else + wiLua::SError(L, "SetEmitterVelocity(Vector value) not enough arguments!"); + return 0; +} +int wiSoundInstance3D_BindLua::SetEmitterRadius(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + soundinstance3D.emitterRadius = wiLua::SGetFloat(L, 1); + } + else + wiLua::SError(L, "SetEmitterVelocity(Vector value) not enough arguments!"); + return 0; +} + +void wiSoundInstance3D_BindLua::Bind() +{ + static bool initialized = false; + if (!initialized) + { + initialized = true; + Luna::Register(wiLua::GetGlobal()->GetLuaState()); + } +} diff --git a/WickedEngine/wiAudio_BindLua.h b/WickedEngine/wiAudio_BindLua.h new file mode 100644 index 000000000..8baa98e7e --- /dev/null +++ b/WickedEngine/wiAudio_BindLua.h @@ -0,0 +1,93 @@ +#pragma once +#include "wiLua.h" +#include "wiLuna.h" +#include "wiAudio.h" + +class wiAudio_BindLua +{ +public: + static const char className[]; + static Luna::FunctionType methods[]; + static Luna::PropertyType properties[]; + + wiAudio_BindLua(lua_State* L) {} + ~wiAudio_BindLua() {} + + int CreateSound(lua_State* L); + int CreateSoundInstance(lua_State* L); + int Destroy(lua_State* L); + int Play(lua_State* L); + int Pause(lua_State* L); + int Stop(lua_State* L); + int GetVolume(lua_State* L); + int SetVolume(lua_State* L); + + int GetSubmixVolume(lua_State* L); + int SetSubmixVolume(lua_State* L); + + int Update3D(lua_State* L); + + static void Bind(); +}; + +class wiSound_BindLua +{ +public: + wiAudio::Sound* sound = nullptr; + bool owned = false; + + static const char className[]; + static Luna::FunctionType methods[]; + static Luna::PropertyType properties[]; + + wiSound_BindLua(lua_State* L) { sound = new wiAudio::Sound; owned = true; } + wiSound_BindLua(wiAudio::Sound* sound) :sound(sound) {} + ~wiSound_BindLua() { if (owned) delete sound; } + + static void Bind(); +}; + +class wiSoundInstance_BindLua +{ +public: + wiAudio::SoundInstance soundinstance; + + static const char className[]; + static Luna::FunctionType methods[]; + static Luna::PropertyType properties[]; + + wiSoundInstance_BindLua(lua_State* L) { } + wiSoundInstance_BindLua(const wiAudio::SoundInstance& soundinstance) : soundinstance(soundinstance) {} + ~wiSoundInstance_BindLua() { } + + int SetSubmixType(lua_State* L); + + static void Bind(); +}; + +class wiSoundInstance3D_BindLua +{ +public: + wiAudio::SoundInstance3D soundinstance3D; + bool owned = false; + + static const char className[]; + static Luna::FunctionType methods[]; + static Luna::PropertyType properties[]; + + wiSoundInstance3D_BindLua(lua_State* L) { } + wiSoundInstance3D_BindLua(const wiAudio::SoundInstance3D& soundinstance3D) : soundinstance3D(soundinstance3D) {} + ~wiSoundInstance3D_BindLua() { } + + int SetListenerPos(lua_State* L); + int SetListenerUp(lua_State* L); + int SetListenerFront(lua_State* L); + int SetListenerVelocity(lua_State* L); + int SetEmitterPos(lua_State* L); + int SetEmitterUp(lua_State* L); + int SetEmitterFront(lua_State* L); + int SetEmitterVelocity(lua_State* L); + int SetEmitterRadius(lua_State* L); + + static void Bind(); +}; diff --git a/WickedEngine/wiGraphicsResource.h b/WickedEngine/wiGraphicsResource.h index 8bae24e8c..504c57cd0 100644 --- a/WickedEngine/wiGraphicsResource.h +++ b/WickedEngine/wiGraphicsResource.h @@ -6,9 +6,6 @@ namespace wiGraphics { - typedef uint64_t wiCPUHandle; - static const wiCPUHandle WI_NULL_HANDLE = 0; - class GraphicsDevice; struct GraphicsDeviceChild diff --git a/WickedEngine/wiHelper.cpp b/WickedEngine/wiHelper.cpp index 383134a70..4444582f1 100644 --- a/WickedEngine/wiHelper.cpp +++ b/WickedEngine/wiHelper.cpp @@ -17,26 +17,6 @@ using namespace std; namespace wiHelper { - DataBlob::DataBlob(const string& fileName) : DATA(nullptr), dataSize(0), dataPos(0) - { - ifstream file(fileName, ios::binary | ios::ate); - - if (file.is_open()) - { - dataSize = static_cast(file.tellg()); - file.seekg(0, file.beg); - DATA = new char[dataSize]; - file.read(DATA, dataSize); - file.close(); - - dataPos = reinterpret_cast(DATA); - } - } - DataBlob::~DataBlob() - { - SAFE_DELETE_ARRAY(DATA); - } - string toUpper(const std::string& s) { std::string result; diff --git a/WickedEngine/wiHelper.h b/WickedEngine/wiHelper.h index 4d9f5f3d1..b39d84d1c 100644 --- a/WickedEngine/wiHelper.h +++ b/WickedEngine/wiHelper.h @@ -14,26 +14,6 @@ namespace wiHelper seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } - // Simple binary reader utility - struct DataBlob - { - char* DATA; - size_t dataSize; - size_t dataPos; - - DataBlob(const std::string& fileName = ""); - ~DataBlob(); - - template - void read(T& data) - { - assert(DATA != nullptr); - assert(dataPos - (size_t)DATA < dataSize); - memcpy(&data, reinterpret_cast(dataPos), sizeof(T)); - dataPos += sizeof(T); - } - }; - std::string toUpper(const std::string& s); bool readByteData(const std::string& fileName, std::vector& data); diff --git a/WickedEngine/wiInitializer.cpp b/WickedEngine/wiInitializer.cpp index ee595ead7..46c92c67f 100644 --- a/WickedEngine/wiInitializer.cpp +++ b/WickedEngine/wiInitializer.cpp @@ -28,7 +28,7 @@ namespace wiInitializer wiJobSystem::Execute(ctx, [] { wiImage::Initialize(); }); wiJobSystem::Execute(ctx, [] { wiInputManager::Initialize(); }); wiJobSystem::Execute(ctx, [] { wiRenderer::Initialize(); wiWidget::LoadShaders(); }); - wiJobSystem::Execute(ctx, [] { wiSoundEffect::Initialize(); wiMusic::Initialize(); }); + wiJobSystem::Execute(ctx, [] { wiAudio::Initialize(); }); wiJobSystem::Execute(ctx, [] { wiTextureHelper::Initialize(); }); wiJobSystem::Execute(ctx, [] { wiSceneSystem::wiHairParticle::Initialize(); }); wiJobSystem::Execute(ctx, [] { wiSceneSystem::wiEmittedParticle::Initialize(); }); diff --git a/WickedEngine/wiLua.cpp b/WickedEngine/wiLua.cpp index 7bee4015b..89a30a215 100644 --- a/WickedEngine/wiLua.cpp +++ b/WickedEngine/wiLua.cpp @@ -12,7 +12,7 @@ #include "RenderPath3D_TiledDeferred_BindLua.h" #include "Texture_BindLua.h" #include "wiRenderer_BindLua.h" -#include "wiSound_BindLua.h" +#include "wiAudio_BindLua.h" #include "wiSprite_BindLua.h" #include "wiImageParams_BindLua.h" #include "SpriteAnim_BindLua.h" @@ -64,9 +64,7 @@ wiLua* wiLua::GetGlobal() RenderPath3D_TiledDeferred_BindLua::Bind(); Texture_BindLua::Bind(); wiRenderer_BindLua::Bind(); - wiSound_BindLua::Bind(); - wiSoundEffect_BindLua::Bind(); - wiMusic_BindLua::Bind(); + wiAudio_BindLua::Bind(); wiSprite_BindLua::Bind(); wiImageParams_BindLua::Bind(); SpriteAnim_BindLua::Bind(); @@ -377,6 +375,14 @@ void wiLua::SSetInt(lua_State* L, int data) { lua_pushinteger(L, (lua_Integer)data); } +void wiLua::SSetLong(lua_State* L, long data) +{ + lua_pushinteger(L, (lua_Integer)data); +} +void wiLua::SSetLongLong(lua_State* L, long long data) +{ + lua_pushinteger(L, (lua_Integer)data); +} void wiLua::SSetFloat(lua_State* L, float data) { lua_pushnumber(L, (lua_Number)data); diff --git a/WickedEngine/wiLua.h b/WickedEngine/wiLua.h index 08ae1ffa8..35a76c846 100644 --- a/WickedEngine/wiLua.h +++ b/WickedEngine/wiLua.h @@ -110,6 +110,10 @@ public: //push int to lua stack static void SSetInt(lua_State* L, int data); + //push long to lua stack + static void SSetLong(lua_State* L, long data); + //push long long to lua stack + static void SSetLongLong(lua_State* L, long long data); //push float to lua stack static void SSetFloat(lua_State* L, float data); //push float2 to lua stack diff --git a/WickedEngine/wiResourceManager.cpp b/WickedEngine/wiResourceManager.cpp index 16cc1f524..d1d1f4989 100644 --- a/WickedEngine/wiResourceManager.cpp +++ b/WickedEngine/wiResourceManager.cpp @@ -1,6 +1,6 @@ #include "wiResourceManager.h" #include "wiRenderer.h" -#include "wiSound.h" +#include "wiAudio.h" #include "wiHelper.h" #include "wiTextureHelper.h" @@ -287,12 +287,11 @@ const void* wiResourceManager::add(const wiHashString& name, Data_Type newType) break; case Data_Type::SOUND: { - success = new wiSoundEffect(name.GetString()); - } - break; - case Data_Type::MUSIC: - { - success = new wiMusic(name.GetString()); + wiAudio::Sound* sound = new wiAudio::Sound; + if (SUCCEEDED(wiAudio::CreateSound(name.GetString(), sound))) + { + success = sound; + } } break; case Data_Type::VERTEXSHADER: @@ -425,8 +424,7 @@ bool wiResourceManager::del(const wiHashString& name, bool forceDelete) SAFE_DELETE(reinterpret_cast(res.data)); break; case Data_Type::SOUND: - case Data_Type::MUSIC: - SAFE_DELETE(reinterpret_cast(res.data)); + SAFE_DELETE(reinterpret_cast(res.data)); break; default: success = false; diff --git a/WickedEngine/wiResourceManager.h b/WickedEngine/wiResourceManager.h index d8138f74a..2b55d69f0 100644 --- a/WickedEngine/wiResourceManager.h +++ b/WickedEngine/wiResourceManager.h @@ -16,7 +16,7 @@ public: IMAGE_1D, IMAGE_2D, IMAGE_3D, - SOUND,MUSIC, + SOUND, VERTEXSHADER, PIXELSHADER, GEOMETRYSHADER, diff --git a/WickedEngine/wiResourceManager_BindLua.cpp b/WickedEngine/wiResourceManager_BindLua.cpp index 8009504b3..e8d489eb6 100644 --- a/WickedEngine/wiResourceManager_BindLua.cpp +++ b/WickedEngine/wiResourceManager_BindLua.cpp @@ -1,7 +1,7 @@ #include "wiResourceManager_BindLua.h" -#include "wiSound_BindLua.h" #include "wiHelper.h" #include "Texture_BindLua.h" +#include "wiAudio_BindLua.h" #include "wiRenderer.h" #include @@ -53,9 +53,8 @@ int wiResourceManager_BindLua::Get(lua_State *L) Luna::push(L, new Texture_BindLua((Texture2D*)data.data)); return 1; break; - case wiResourceManager::Data_Type::MUSIC: case wiResourceManager::Data_Type::SOUND: - Luna::push(L, new wiSound_BindLua((wiSound*)data.data)); + Luna::push(L, new wiSound_BindLua((wiAudio::Sound*)data.data)); return 1; break; default: @@ -86,22 +85,13 @@ int wiResourceManager_BindLua::Add(lua_State *L) if (argc > 0) { string name = wiLua::SGetString(L, 1); - wiResourceManager::Data_Type type = wiResourceManager::Data_Type::DYNAMIC; - if (argc > 1) //type info also provided in this case - { - string typeStr = wiHelper::toUpper( wiLua::SGetString(L, 2) ); - if (!typeStr.compare("SOUND")) - type = wiResourceManager::Data_Type::SOUND; - else if (!typeStr.compare("MUSIC")) - type = wiResourceManager::Data_Type::MUSIC; - } - const void* data = resources->add(name, type); + const void* data = resources->add(name); wiLua::SSetString(L, (data != nullptr ? "ok" : "not found")); return 1; } else { - wiLua::SError(L, "Resource:Add(string name, (opt) string type) not enough arguments!"); + wiLua::SError(L, "Resource:Add(string name) not enough arguments!"); } return 0; } diff --git a/WickedEngine/wiSound.cpp b/WickedEngine/wiSound.cpp deleted file mode 100644 index 37800b60e..000000000 --- a/WickedEngine/wiSound.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#include "wiSound.h" -#include "wiBackLog.h" - -using namespace std; - -wiAudioEngine* wiSoundEffect::audioEngine = nullptr; -wiAudioEngine* wiMusic::audioEngine = nullptr; - - -wiAudioEngine::wiAudioEngine() -{ - INITIALIZED = false; - pXAudio2 = nullptr; - pMasterVoice = nullptr; - Initialize(); -} -wiAudioEngine::~wiAudioEngine() -{ - if (pMasterVoice != nullptr) pMasterVoice->DestroyVoice(); - if (pXAudio2 != nullptr) pXAudio2->Release(); - SAFE_DELETE(pMasterVoice); - SAFE_DELETE(pXAudio2); - INITIALIZED = false; -} -HRESULT wiAudioEngine::Initialize() -{ - if (INITIALIZED) - return S_OK; - - CoInitializeEx(NULL, COINIT_MULTITHREADED); - - HRESULT hr; - pXAudio2 = nullptr; - if (FAILED(hr = XAudio2Create(&pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR))) - return hr; - pMasterVoice = nullptr; - if (FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasterVoice))) - return hr; - - INITIALIZED = true; - return EXIT_SUCCESS; -} -void wiAudioEngine::SetVolume(float vol) { - if (INITIALIZED && pMasterVoice != nullptr) - pMasterVoice->SetVolume(vol); -} -float wiAudioEngine::GetVolume() { - float vol; - if (pMasterVoice != nullptr) - pMasterVoice->GetVolume(&vol); - return vol; -} - - - - - - - -wiSound::wiSound() -{ - pSourceVoice = nullptr; -} -wiSound::~wiSound() -{ - //if (pSourceVoice != nullptr) pSourceVoice->DestroyVoice(); - //SAFE_DELETE(pSourceVoice); -} - -HRESULT wiSound::FindChunk(HANDLE hFile, DWORD fourcc, DWORD & dwChunkSize, DWORD & dwChunkDataPosition) -{ - HRESULT hr = S_OK; - if( INVALID_SET_FILE_POINTER == SetFilePointerEx( hFile, LARGE_INTEGER(), NULL, FILE_BEGIN ) ) - return HRESULT_FROM_WIN32( GetLastError() ); - - DWORD dwChunkType; - DWORD dwChunkDataSize; - DWORD dwRIFFDataSize = 0; - DWORD dwFileType; - DWORD bytesRead = 0; - DWORD dwOffset = 0; - - while (hr == S_OK) - { - DWORD dwRead; - if( 0 == ReadFile( hFile, &dwChunkType, sizeof(DWORD), &dwRead, NULL ) ) - hr = HRESULT_FROM_WIN32( GetLastError() ); - - if( 0 == ReadFile( hFile, &dwChunkDataSize, sizeof(DWORD), &dwRead, NULL ) ) - hr = HRESULT_FROM_WIN32( GetLastError() ); - - switch (dwChunkType) - { - case fourccRIFF: - dwRIFFDataSize = dwChunkDataSize; - dwChunkDataSize = 4; - if( 0 == ReadFile( hFile, &dwFileType, sizeof(DWORD), &dwRead, NULL ) ) - hr = HRESULT_FROM_WIN32( GetLastError() ); - break; - - default: - LARGE_INTEGER li = LARGE_INTEGER(); - li.QuadPart = dwChunkDataSize; - if( INVALID_SET_FILE_POINTER == SetFilePointerEx( hFile, li, NULL, FILE_CURRENT ) ) - return HRESULT_FROM_WIN32( GetLastError() ); - } - - dwOffset += sizeof(DWORD) * 2; - - if (dwChunkType == fourcc) - { - dwChunkSize = dwChunkDataSize; - dwChunkDataPosition = dwOffset; - return S_OK; - } - - dwOffset += dwChunkDataSize; - - if (bytesRead >= dwRIFFDataSize) return S_FALSE; - - } - - return S_OK; - -} -HRESULT wiSound::ReadChunkData(HANDLE hFile, void * buffer, DWORD buffersize, DWORD bufferoffset) -{ - HRESULT hr = S_OK; - - LARGE_INTEGER li = LARGE_INTEGER(); - li.QuadPart=bufferoffset; - if( INVALID_SET_FILE_POINTER == SetFilePointerEx( hFile, li, NULL, FILE_BEGIN ) ) - return HRESULT_FROM_WIN32( GetLastError() ); - DWORD dwRead; - if( 0 == ReadFile( hFile, buffer, buffersize, &dwRead, NULL ) ) - hr = HRESULT_FROM_WIN32( GetLastError() ); - return hr; -} -HRESULT wiSound::OpenFile(const TCHAR* strFileName) -{ - HRESULT hr; - - wfx = WAVEFORMATEX(); - buffer = XAUDIO2_BUFFER(); - - // Open the file - HANDLE hFile; - - hFile = CreateFile2( - strFileName, - GENERIC_READ, - FILE_SHARE_READ, - OPEN_EXISTING, - nullptr - ); - - if (INVALID_HANDLE_VALUE == hFile) - return HRESULT_FROM_WIN32(GetLastError()); - - if (INVALID_SET_FILE_POINTER == SetFilePointerEx(hFile, LARGE_INTEGER(), NULL, FILE_BEGIN)) - return HRESULT_FROM_WIN32(GetLastError()); - - DWORD dwChunkSize; - DWORD dwChunkPosition; - //check the file type, should be fourccWAVE or 'XWMA' - FindChunk(hFile,fourccRIFF,dwChunkSize, dwChunkPosition ); - DWORD filetype; - if(FAILED( hr = ReadChunkData(hFile,&filetype,sizeof(DWORD),dwChunkPosition) )) - return hr; - if (filetype != fourccWAVE) - return S_FALSE; - - - - if(FAILED( hr = FindChunk(hFile,fourccFMT, dwChunkSize, dwChunkPosition ) )) - return hr; - if(FAILED( hr = ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition ) )) - return hr; - wfx.wFormatTag=WAVE_FORMAT_PCM; - - - //fill out the audio data buffer with the contents of the fourccDATA chunk - if(FAILED( hr = FindChunk(hFile,fourccDATA,dwChunkSize, dwChunkPosition ) )) - return hr; - BYTE * pDataBuffer = new BYTE[dwChunkSize]; - if(FAILED( hr = ReadChunkData(hFile, pDataBuffer, dwChunkSize, dwChunkPosition) )) - return hr; - - - buffer.AudioBytes = dwChunkSize; //buffer containing audio data - buffer.pAudioData = pDataBuffer; //size of the audio buffer in bytes - buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer - - - return EXIT_SUCCESS; -} -HRESULT wiSound::Load(wstring filename) -{ - return OpenFile(filename.data()); -} -HRESULT wiSound::Load(string filename) -{ - return OpenFile(wstring(filename.begin(),filename.end()).data()); -} -void wiSound::Stop(){ - StopSound(); -} -void wiSound::Initialize() -{ - pSourceVoice = nullptr; -} -HRESULT wiSound::PlaySound(wiAudioEngine* engine) -{ - if (engine == nullptr) - return E_FAIL; - - if (!engine->INITIALIZED) - return E_FAIL; - - HRESULT hr; - pSourceVoice = nullptr; - - if (FAILED(hr = engine->pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx))) - return hr; - - if (FAILED(hr = pSourceVoice->SubmitSourceBuffer(&buffer))) - return hr; - - if (FAILED(hr = pSourceVoice->Start(0))) - return hr; - - return EXIT_SUCCESS; -} -void wiSound::StopSound() -{ - if (pSourceVoice != nullptr) { - pSourceVoice->Stop(); - } -} - - -void wiSoundEffect::SetVolume(float vol) { - if (audioEngine == nullptr) - return; - audioEngine->SetVolume(vol); -} -float wiSoundEffect::GetVolume() { - if (audioEngine == nullptr) - return 0; - return audioEngine->GetVolume(); -} -wiSoundEffect::wiSoundEffect() -{ - wiSound::Initialize(); -} -wiSoundEffect::wiSoundEffect(wstring filename) -{ - wiSound::Initialize(); - Load(filename); -} -wiSoundEffect::wiSoundEffect(string filename) -{ - wiSound::Initialize(); - Load(filename); -} -wiSoundEffect::~wiSoundEffect() -{ -} -HRESULT wiSoundEffect::Initialize() -{ - if (audioEngine == nullptr) - { - audioEngine = new wiAudioEngine; - } - - if (audioEngine->INITIALIZED) - { - wiBackLog::post("wiSoundEffect Initialized"); - return S_OK; - } - else - { - wiBackLog::post("wiSoundEffect Initialization FAILED!"); - return E_FAIL; - } -} -HRESULT wiSoundEffect::Play(DWORD delay) -{ - if (delay > 0) { - thread([=] { - Sleep(delay); - PlaySound(audioEngine); - }).detach(); - return S_OK; - } - return PlaySound(audioEngine); -} - - -void wiMusic::SetVolume(float vol){ - if (audioEngine == nullptr) - return; - audioEngine->SetVolume(vol); -} -float wiMusic::GetVolume(){ - if (audioEngine == nullptr) - return 0; - return audioEngine->GetVolume(); -} -wiMusic::wiMusic() -{ - wiSound::Initialize(); - pSourceVoice = nullptr; -} -wiMusic::wiMusic(wstring filename) -{ - wiSound::Initialize(); - Load(filename); -} -wiMusic::wiMusic(string filename) -{ - wiSound::Initialize(); - Load(filename); -} -wiMusic::~wiMusic() -{ -} -HRESULT wiMusic::Initialize() -{ - if (audioEngine == nullptr) - { - audioEngine = new wiAudioEngine; - } - - if (audioEngine->INITIALIZED) - { - wiBackLog::post("wiMusic Initialized"); - return S_OK; - } - else - { - wiBackLog::post("wiMusic Initialization FAILED!"); - return E_FAIL; - } -} -HRESULT wiMusic::Play(DWORD delay) -{ - if (delay > 0) { - thread([=] { - Sleep(delay); - PlaySound(audioEngine); - }).detach(); - return S_OK; - } - return PlaySound(audioEngine); -} diff --git a/WickedEngine/wiSound.h b/WickedEngine/wiSound.h deleted file mode 100644 index d34144d6d..000000000 --- a/WickedEngine/wiSound.h +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once -#include "CommonInclude.h" - -#include -#pragma comment(lib,"xaudio2.lib") - -#include -#include - - -#ifdef _XBOX //Big-Endian -#define fourccRIFF 'RIFF' -#define fourccDATA 'data' -#define fourccFMT 'fmt ' -#define fourccWAVE 'WAVE' -#define fourccXWMA 'XWMA' -#define fourccDPDS 'dpds' -#endif - -#ifndef _XBOX //Little-Endian -#define fourccRIFF 'FFIR' -#define fourccDATA 'atad' -#define fourccFMT ' tmf' -#define fourccWAVE 'EVAW' -#define fourccXWMA 'AMWX' -#define fourccDPDS 'sdpd' -#endif - -class wiAudioEngine -{ -public: - wiAudioEngine(); - ~wiAudioEngine(); - - IXAudio2MasteringVoice* pMasterVoice; - IXAudio2* pXAudio2; - bool INITIALIZED; - - void SetVolume(float); - float GetVolume(); - - HRESULT Initialize(); -}; - -class wiSound -{ -protected: - WAVEFORMATEX wfx; - XAUDIO2_BUFFER buffer; - IXAudio2SourceVoice* pSourceVoice; - - HRESULT FindChunk(HANDLE hFile, DWORD fourcc, DWORD & dwChunkSize, DWORD & dwChunkDataPosition); - HRESULT ReadChunkData(HANDLE hFile, void * buffer, DWORD buffersize, DWORD bufferoffset); - HRESULT OpenFile(const TCHAR*); - - HRESULT PlaySound(wiAudioEngine* engine); - void StopSound(); -public: - wiSound(); - virtual ~wiSound(); - virtual void Initialize(); - - HRESULT Load(std::wstring); - HRESULT Load(std::string); - virtual HRESULT Play(DWORD delay = 0) = 0; - void Stop(); -}; - -class wiSoundEffect : public wiSound -{ -private: - static wiAudioEngine* audioEngine; -public: - wiSoundEffect(); - wiSoundEffect(std::wstring); - wiSoundEffect(std::string); - ~wiSoundEffect(); - static HRESULT Initialize(); - - static void SetVolume(float); - static float GetVolume(); - HRESULT Play(DWORD delay = 0) override; -}; - -class wiMusic : public wiSound -{ -private: - static wiAudioEngine* audioEngine; -public: - wiMusic(); - wiMusic(std::wstring); - wiMusic(std::string); - ~wiMusic(); - static HRESULT Initialize(); - - static void SetVolume(float); - static float GetVolume(); - HRESULT Play(DWORD delay = 0) override; -}; - diff --git a/WickedEngine/wiSound_BindLua.cpp b/WickedEngine/wiSound_BindLua.cpp deleted file mode 100644 index f2ba4c2dc..000000000 --- a/WickedEngine/wiSound_BindLua.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "wiSound_BindLua.h" - - -const char wiSound_BindLua::className[] = "Sound"; - -Luna::FunctionType wiSound_BindLua::methods[] = { - lunamethod(wiSound_BindLua, Play), - lunamethod(wiSound_BindLua, Stop), - { NULL, NULL } -}; -Luna::PropertyType wiSound_BindLua::properties[] = { - { NULL, NULL } -}; - -wiSound_BindLua::wiSound_BindLua(wiSound* sound) :sound(sound) -{ -} -wiSound_BindLua::wiSound_BindLua(lua_State *L) -{ - sound = nullptr; -} - - -wiSound_BindLua::~wiSound_BindLua() -{ -} - -int wiSound_BindLua::Play(lua_State* L) -{ - if (sound == nullptr) - { - wiLua::SError(L, "Play(opt int delay) sound resource not loaded!"); - return 0; - } - - int argc = wiLua::SGetArgCount(L); - if (argc > 0) - sound->Play((DWORD)wiLua::SGetInt(L, 2)); - else - sound->Play(); - return 0; -} - -int wiSound_BindLua::Stop(lua_State *L) -{ - if (sound == nullptr) - { - wiLua::SError(L, "Stop() sound resource not loaded!"); - return 0; - } - - sound->Stop(); - return 0; -} - -void wiSound_BindLua::Bind() -{ - static bool initialized = false; - if (!initialized) - { - initialized = true; - Luna::Register(wiLua::GetGlobal()->GetLuaState()); - - wiLua::GetGlobal()->RegisterFunc("SoundVolume", SoundVolume); - wiLua::GetGlobal()->RegisterFunc("MusicVolume", MusicVolume); - } -} - -int wiSound_BindLua::SoundVolume(lua_State *L) -{ - int argc = wiLua::SGetArgCount(L); - if (argc > 0) - { - wiSoundEffect::SetVolume(wiLua::SGetFloat(L, 1)); - } - wiLua::SSetFloat(L, wiSoundEffect::GetVolume()); - return 1; -} -int wiSound_BindLua::MusicVolume(lua_State *L) -{ - int argc = wiLua::SGetArgCount(L); - if (argc > 0) - { - wiMusic::SetVolume(wiLua::SGetFloat(L, 1)); - } - wiLua::SSetFloat(L, wiMusic::GetVolume()); - return 1; -} - - - -const char wiSoundEffect_BindLua::className[] = "SoundEffect"; - -Luna::FunctionType wiSoundEffect_BindLua::methods[] = { - lunamethod(wiSoundEffect_BindLua, Play), - lunamethod(wiSoundEffect_BindLua, Stop), - { NULL, NULL } -}; -Luna::PropertyType wiSoundEffect_BindLua::properties[] = { - { NULL, NULL } -}; - -wiSoundEffect_BindLua::wiSoundEffect_BindLua(lua_State *L) :wiSound_BindLua() -{ - int argc = wiLua::SGetArgCount(L); - if (argc > 0) - { - sound = new wiSoundEffect(wiLua::SGetString(L, 1)); - } -} - -void wiSoundEffect_BindLua::Bind() -{ - static bool initialized = false; - if (!initialized) - { - initialized = true; - Luna::Register(wiLua::GetGlobal()->GetLuaState()); - } -} - - -const char wiMusic_BindLua::className[] = "Music"; - -Luna::FunctionType wiMusic_BindLua::methods[] = { - lunamethod(wiMusic_BindLua, Play), - lunamethod(wiMusic_BindLua, Stop), - { NULL, NULL } -}; -Luna::PropertyType wiMusic_BindLua::properties[] = { - { NULL, NULL } -}; - -wiMusic_BindLua::wiMusic_BindLua(lua_State *L) :wiSound_BindLua() -{ - int argc = wiLua::SGetArgCount(L); - if (argc > 0) - { - sound = new wiMusic(wiLua::SGetString(L, 1)); - } -} - -void wiMusic_BindLua::Bind() -{ - static bool initialized = false; - if (!initialized) - { - initialized = true; - Luna::Register(wiLua::GetGlobal()->GetLuaState()); - } -} - diff --git a/WickedEngine/wiSound_BindLua.h b/WickedEngine/wiSound_BindLua.h deleted file mode 100644 index b7a4aa36b..000000000 --- a/WickedEngine/wiSound_BindLua.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -#include "wiLua.h" -#include "wiLuna.h" -#include "wiSound.h" - -class wiSound_BindLua -{ -public: - wiSound* sound; - static const char className[]; - static Luna::FunctionType methods[]; - static Luna::PropertyType properties[]; - - wiSound_BindLua(wiSound* sound = nullptr); - wiSound_BindLua(lua_State *L); - ~wiSound_BindLua(); - - int Play(lua_State *L); - int Stop(lua_State *L); - - static void Bind(); - - static int SoundVolume(lua_State *L); - static int MusicVolume(lua_State *L); -}; - -class wiSoundEffect_BindLua : public wiSound_BindLua -{ -public: - static const char className[]; - static Luna::FunctionType methods[]; - static Luna::PropertyType properties[]; - wiSoundEffect_BindLua(lua_State *L); - - static void Bind(); -}; - -class wiMusic_BindLua : public wiSound_BindLua -{ -public: - static const char className[]; - static Luna::FunctionType methods[]; - static Luna::PropertyType properties[]; - wiMusic_BindLua(lua_State *L); - - static void Bind(); -}; - diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index d4a4e9268..17d39303c 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -7,9 +7,9 @@ namespace wiVersion // main engine core const int major = 0; // minor features, major updates - const int minor = 28; + const int minor = 29; // minor bug fixes, alterations, refactors, updates - const int revision = 28; + const int revision = 0; long GetVersion() diff --git a/features.txt b/features.txt index 21c904ce3..858524b0c 100644 --- a/features.txt +++ b/features.txt @@ -43,7 +43,7 @@ Soft shadows [removed] Rigid body physics simulation (HAVOK) [PRIVATE] Rigid body physics simulation (BULLET) Soft body physics simulation (BULLET) -Sound (Xaudio2) +3D Audio (Xaudio2) Input: Windows Keyboard,Windows Mouse,DirectInput(Joypad,Keyboard,Mouse),XINPUT(Joypad) Backlog: log,input,scripting Gamma correction