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

+## 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