added support for ogg audio format; allow enable/disable reverb per sound instance;
This commit is contained in:
+20
-1
@@ -59,7 +59,7 @@ SoundWindow::SoundWindow(EditorComponent* editor) : GUI(&editor->GetGUI())
|
||||
reverbComboBox->AddItem("MEDIUMHALL");
|
||||
reverbComboBox->AddItem("LARGEHALL");
|
||||
reverbComboBox->AddItem("PLATE");
|
||||
reverbComboBox->SetTooltip("Set the global reverb setting. This will affect all the 3D sounds in the scene.");
|
||||
reverbComboBox->SetTooltip("Set the global reverb setting. Sound instances need to enable reverb to take effect!");
|
||||
soundWindow->AddWidget(reverbComboBox);
|
||||
|
||||
y += step;
|
||||
@@ -73,6 +73,7 @@ SoundWindow::SoundWindow(EditorComponent* editor) : GUI(&editor->GetGUI())
|
||||
params.type = wiHelper::FileDialogParams::OPEN;
|
||||
params.description = "Sound";
|
||||
params.extensions.push_back("wav");
|
||||
params.extensions.push_back("ogg");
|
||||
wiHelper::FileDialog(params, [=](std::string fileName) {
|
||||
wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) {
|
||||
Entity entity = GetScene().Entity_CreateSound("editorSound", fileName);
|
||||
@@ -141,6 +142,21 @@ SoundWindow::SoundWindow(EditorComponent* editor) : GUI(&editor->GetGUI())
|
||||
soundWindow->AddWidget(loopedCheckbox);
|
||||
loopedCheckbox->SetEnabled(false);
|
||||
|
||||
reverbCheckbox = new wiCheckBox("Reverb: ");
|
||||
reverbCheckbox->SetTooltip("Enable/disable reverb.");
|
||||
reverbCheckbox->SetPos(XMFLOAT2(x + 240, y));
|
||||
reverbCheckbox->SetSize(XMFLOAT2(hei, hei));
|
||||
reverbCheckbox->OnClick([&](wiEventArgs args) {
|
||||
SoundComponent* sound = GetScene().sounds.GetComponent(entity);
|
||||
if (sound != nullptr)
|
||||
{
|
||||
sound->soundinstance.SetEnableReverb(args.bValue);
|
||||
wiAudio::CreateSoundInstance(sound->soundResource->sound, &sound->soundinstance);
|
||||
}
|
||||
});
|
||||
soundWindow->AddWidget(reverbCheckbox);
|
||||
reverbCheckbox->SetEnabled(false);
|
||||
|
||||
disable3dCheckbox = new wiCheckBox("2D: ");
|
||||
disable3dCheckbox->SetTooltip("Sounds in the scene are 3D spatial by default. Select this to disable 3D effect.");
|
||||
disable3dCheckbox->SetPos(XMFLOAT2(x + 300, y));
|
||||
@@ -227,6 +243,8 @@ void SoundWindow::SetEntity(Entity entity)
|
||||
playstopButton->SetEnabled(true);
|
||||
loopedCheckbox->SetEnabled(true);
|
||||
loopedCheckbox->SetCheck(sound->IsLooped());
|
||||
reverbCheckbox->SetEnabled(true);
|
||||
reverbCheckbox->SetCheck(sound->soundinstance.IsEnableReverb());
|
||||
disable3dCheckbox->SetEnabled(true);
|
||||
disable3dCheckbox->SetCheck(sound->IsDisable3D());
|
||||
volumeSlider->SetEnabled(true);
|
||||
@@ -252,6 +270,7 @@ void SoundWindow::SetEntity(Entity entity)
|
||||
nameField->SetEnabled(false);
|
||||
playstopButton->SetEnabled(false);
|
||||
loopedCheckbox->SetEnabled(false);
|
||||
reverbCheckbox->SetEnabled(false);
|
||||
disable3dCheckbox->SetEnabled(false);
|
||||
volumeSlider->SetEnabled(false);
|
||||
submixComboBox->SetEnabled(false);
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
wiTextInputField* nameField;
|
||||
wiButton* playstopButton;
|
||||
wiCheckBox* loopedCheckbox;
|
||||
wiCheckBox* reverbCheckbox;
|
||||
wiCheckBox* disable3dCheckbox;
|
||||
wiSlider* volumeSlider;
|
||||
wiComboBox* submixComboBox;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -556,6 +556,7 @@
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_msl.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_parser.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\stb_vorbis.c" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\utility_common.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)wiArchive.cpp" />
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)wiAudio.cpp" />
|
||||
|
||||
@@ -1994,6 +1994,9 @@
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)wiSDLInput.cpp">
|
||||
<Filter>ENGINE\Input</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\stb_vorbis.c">
|
||||
<Filter>UTILITY</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="$(MSBuildThisFileDirectory)ArchiveVersionHistory.txt" />
|
||||
|
||||
+72
-33
@@ -4,6 +4,9 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define STB_VORBIS_HEADER_ONLY
|
||||
#include "Utility/stb_vorbis.c"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <wrl/client.h> // ComPtr
|
||||
@@ -12,24 +15,13 @@
|
||||
#include <x3daudio.h>
|
||||
#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
|
||||
//Little-Endian things:
|
||||
#define fourccRIFF 'FFIR'
|
||||
#define fourccDATA 'atad'
|
||||
#define fourccFMT ' tmf'
|
||||
#define fourccWAVE 'EVAW'
|
||||
#define fourccXWMA 'AMWX'
|
||||
#define fourccDPDS 'sdpd'
|
||||
#endif
|
||||
|
||||
namespace wiAudio
|
||||
{
|
||||
@@ -262,6 +254,7 @@ namespace wiAudio
|
||||
bool CreateSound(const std::vector<uint8_t>& data, Sound* sound)
|
||||
{
|
||||
std::shared_ptr<SoundInternal> soundinternal = std::make_shared<SoundInternal>();
|
||||
soundinternal->audio = audio;
|
||||
sound->internal_state = soundinternal;
|
||||
|
||||
DWORD dwChunkSize;
|
||||
@@ -270,23 +263,63 @@ namespace wiAudio
|
||||
bool success;
|
||||
|
||||
success = FindChunk(data.data(), fourccRIFF, dwChunkSize, dwChunkPosition);
|
||||
assert(success);
|
||||
DWORD filetype;
|
||||
memcpy(&filetype, data.data() + dwChunkPosition, sizeof(DWORD));
|
||||
assert(filetype == fourccWAVE);
|
||||
if (success)
|
||||
{
|
||||
// Wav decoder:
|
||||
DWORD filetype;
|
||||
memcpy(&filetype, data.data() + dwChunkPosition, sizeof(DWORD));
|
||||
if (filetype != fourccWAVE)
|
||||
{
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
soundinternal->audio = audio;
|
||||
success = FindChunk(data.data(), fourccFMT, dwChunkSize, dwChunkPosition);
|
||||
if (!success)
|
||||
{
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
memcpy(&soundinternal->wfx, data.data() + dwChunkPosition, dwChunkSize);
|
||||
soundinternal->wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
|
||||
success = FindChunk(data.data(), fourccFMT, dwChunkSize, dwChunkPosition);
|
||||
assert(success);
|
||||
memcpy(&soundinternal->wfx, data.data() + dwChunkPosition, dwChunkSize);
|
||||
soundinternal->wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
success = FindChunk(data.data(), fourccDATA, dwChunkSize, dwChunkPosition);
|
||||
if (!success)
|
||||
{
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
success = FindChunk(data.data(), fourccDATA, dwChunkSize, dwChunkPosition);
|
||||
assert(success);
|
||||
soundinternal->audioData.resize(dwChunkSize);
|
||||
memcpy(soundinternal->audioData.data(), data.data() + dwChunkPosition, dwChunkSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ogg decoder:
|
||||
int channels = 0;
|
||||
int sample_rate = 0;
|
||||
short* output = nullptr;
|
||||
int samples = stb_vorbis_decode_memory(data.data(), (int)data.size(), &channels, &sample_rate, &output);
|
||||
if (samples < 0)
|
||||
{
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
soundinternal->audioData.resize(dwChunkSize);
|
||||
memcpy(soundinternal->audioData.data(), data.data() + dwChunkPosition, dwChunkSize);
|
||||
// WAVEFORMATEX: https://docs.microsoft.com/en-us/previous-versions/dd757713(v=vs.85)?redirectedfrom=MSDN
|
||||
soundinternal->wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
soundinternal->wfx.nChannels = (WORD)channels;
|
||||
soundinternal->wfx.nSamplesPerSec = (DWORD)sample_rate;
|
||||
soundinternal->wfx.wBitsPerSample = sizeof(short) * 8;
|
||||
soundinternal->wfx.nBlockAlign = (WORD)channels * sizeof(short); // is this right?
|
||||
soundinternal->wfx.nAvgBytesPerSec = soundinternal->wfx.nSamplesPerSec * soundinternal->wfx.nBlockAlign;
|
||||
|
||||
size_t output_size = (size_t)samples * sizeof(short);
|
||||
soundinternal->audioData.resize(output_size);
|
||||
memcpy(soundinternal->audioData.data(), output, output_size);
|
||||
|
||||
free(output);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -302,9 +335,12 @@ namespace wiAudio
|
||||
|
||||
XAUDIO2_SEND_DESCRIPTOR SFXSend[] = {
|
||||
{ XAUDIO2_SEND_USEFILTER, audio->submixVoices[instance->type] },
|
||||
{ XAUDIO2_SEND_USEFILTER, audio->reverbSubmix },
|
||||
{ XAUDIO2_SEND_USEFILTER, audio->reverbSubmix }, // this should be last to enable/disable reverb simply
|
||||
};
|
||||
XAUDIO2_VOICE_SENDS SFXSendList = {
|
||||
instance->IsEnableReverb() ? arraysize(SFXSend) : 1,
|
||||
SFXSend
|
||||
};
|
||||
XAUDIO2_VOICE_SENDS SFXSendList = { arraysize(SFXSend), SFXSend };
|
||||
|
||||
hr = audio->audioEngine->CreateSourceVoice(&instanceinternal->sourceVoice, &soundinternal->wfx,
|
||||
0, XAUDIO2_DEFAULT_FREQ_RATIO, NULL, &SFXSendList, NULL);
|
||||
@@ -475,16 +511,19 @@ namespace wiAudio
|
||||
settings.pMatrixCoefficients
|
||||
);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
hr = instanceinternal->sourceVoice->SetOutputMatrix(audio->reverbSubmix, settings.SrcChannelCount, 1, &settings.ReverbLevel);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
XAUDIO2_FILTER_PARAMETERS FilterParametersDirect = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI / 6.0f * settings.LPFDirectCoefficient), 1.0f };
|
||||
hr = instanceinternal->sourceVoice->SetOutputFilterParameters(audio->submixVoices[instance->type], &FilterParametersDirect);
|
||||
assert(SUCCEEDED(hr));
|
||||
XAUDIO2_FILTER_PARAMETERS FilterParametersReverb = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI / 6.0f * settings.LPFReverbCoefficient), 1.0f };
|
||||
hr = instanceinternal->sourceVoice->SetOutputFilterParameters(audio->reverbSubmix, &FilterParametersReverb);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
if (instance->IsEnableReverb())
|
||||
{
|
||||
hr = instanceinternal->sourceVoice->SetOutputMatrix(audio->reverbSubmix, settings.SrcChannelCount, 1, &settings.ReverbLevel);
|
||||
assert(SUCCEEDED(hr));
|
||||
XAUDIO2_FILTER_PARAMETERS FilterParametersReverb = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI / 6.0f * settings.LPFReverbCoefficient), 1.0f };
|
||||
hr = instanceinternal->sourceVoice->SetOutputFilterParameters(audio->reverbSubmix, &FilterParametersReverb);
|
||||
assert(SUCCEEDED(hr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,16 @@ namespace wiAudio
|
||||
SUBMIX_TYPE type = SUBMIX_TYPE_SOUNDEFFECT;
|
||||
float loop_begin = 0; // loop region begin in seconds (0 = from beginning)
|
||||
float loop_length = 0; // loop region legth in seconds (0 = until the end)
|
||||
|
||||
enum FLAGS
|
||||
{
|
||||
EMPTY = 0,
|
||||
ENABLE_REVERB = 1 << 0,
|
||||
};
|
||||
uint32_t _flags = EMPTY;
|
||||
|
||||
inline void SetEnableReverb(bool value = true) { if (value) { _flags |= ENABLE_REVERB; } else { _flags &= ~ENABLE_REVERB; } }
|
||||
inline bool IsEnableReverb() const { return _flags & ENABLE_REVERB; }
|
||||
};
|
||||
|
||||
bool CreateSound(const std::string& filename, Sound* sound);
|
||||
|
||||
@@ -36,7 +36,8 @@ namespace wiResourceManager
|
||||
std::make_pair("PNG", wiResource::IMAGE),
|
||||
std::make_pair("DDS", wiResource::IMAGE),
|
||||
std::make_pair("TGA", wiResource::IMAGE),
|
||||
std::make_pair("WAV", wiResource::SOUND)
|
||||
std::make_pair("WAV", wiResource::SOUND),
|
||||
std::make_pair("OGG", wiResource::SOUND),
|
||||
};
|
||||
|
||||
std::shared_ptr<wiResource> Load(const std::string& name)
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace wiVersion
|
||||
// minor features, major updates, breaking API changes
|
||||
const int minor = 48;
|
||||
// minor bug fixes, alterations, refactors, updates
|
||||
const int revision = 2;
|
||||
const int revision = 3;
|
||||
|
||||
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);
|
||||
|
||||
|
||||
@@ -123,6 +123,7 @@ stb_image
|
||||
stb_image_write
|
||||
stb_truetype
|
||||
stb_rect_pack
|
||||
stb_vorbis
|
||||
|
||||
Sean Barrett 2010-2015 no warranty implied; use at your own risk
|
||||
|
||||
|
||||
Reference in New Issue
Block a user