/src/sound/sound.cpp
https://bitbucket.org/vivkin/gam3b00bs/ · C++ · 206 lines · 171 code · 35 blank · 0 comment · 11 complexity · d3fd4a573c14ea4a55d250ce44574f88 MD5 · raw file
- #include <xaudio2.h>
- #include <mmsystem.h>
- #include <stb_vorbis/stb_vorbis.h>
- #include "common.h"
- #include "sound.h"
-
- namespace snd
- {
- static tlsf_pool gs_sound_heap;
- IXAudio2* g_xaudio2 = NULL;
- IXAudio2MasteringVoice* g_mastering_voice = NULL;
- stb_vorbis_alloc vorbis_alloc;
-
- struct sound
- {
- XAUDIO2_BUFFER buffer;
- IXAudio2SourceVoice* source_voice;
- WAVEFORMATEX* wfx;
- uint32 wave_data_size;
- void* wave_data;
-
- };
-
-
-
- inline void* snd_alloc(size_t size)
- {
- return tlsf_malloc(gs_sound_heap, size);
- }
-
- inline void snd_free(void* ptr)
- {
- tlsf_free(gs_sound_heap, ptr);
- }
-
-
- bool init(void* memory, size_t size, size_t decoder_size)
- {
- ASSERT(memory);
- ASSERT(size);
- gs_sound_heap = tlsf_create(memory, size);
- vorbis_alloc.alloc_buffer = (char*)snd_alloc(decoder_size);
- vorbis_alloc.alloc_buffer_length_in_bytes = decoder_size;
- CoInitializeEx(0,COINIT_MULTITHREADED);
- if(XAudio2Create(&g_xaudio2,0,XAUDIO2_DEFAULT_PROCESSOR)!=S_OK)
- {
- CoUninitialize();
- return false;
- }
- if(g_xaudio2->CreateMasteringVoice( &g_mastering_voice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, 0,0)!=S_OK)
- {
- g_xaudio2->Release();
- g_xaudio2 = NULL;
- CoUninitialize();
- return false;
- }
-
- return true;
- }
-
- void term()
- {
- snd_free(vorbis_alloc.alloc_buffer);
- vorbis_alloc.alloc_buffer = NULL;
- vorbis_alloc.alloc_buffer_length_in_bytes = 0;
- g_mastering_voice->DestroyVoice();
- g_mastering_voice = NULL;
- g_xaudio2->Release();
- g_xaudio2 = NULL;
- }
-
-
- void set_master_volume(float volume)
- {
- ASSERT(g_mastering_voice);
- g_mastering_voice->SetVolume(volume);
- }
-
- void get_master_volume(float* out)
- {
- ASSERT(g_mastering_voice && out);
- g_mastering_voice->GetVolume(out);
- }
-
- sound* load_sound(char* filename)
- {
- sound* s = (sound*)snd_alloc(sizeof(sound));
- memset(s,0,sizeof(sound));
-
- int error = 0;
- stb_vorbis* vb_data = stb_vorbis_open_filename(filename,&error,&vorbis_alloc);
- if(error != VORBIS__no_error)
- return NULL;
- stb_vorbis_info vorbis_info = stb_vorbis_get_info(vb_data);
-
-
-
- s->wfx = (WAVEFORMATEX*)snd_alloc(sizeof(WAVEFORMATEX));
- memset(s->wfx,0,sizeof(WAVEFORMATEX));
- s->wfx->wFormatTag = WAVE_FORMAT_PCM;
- s->wfx->wBitsPerSample = 16;
- s->wfx->nSamplesPerSec = vorbis_info.sample_rate;
- s->wfx->nChannels = (WORD)vorbis_info.channels;
- s->wfx->nBlockAlign = s->wfx->nChannels*2;
- s->wfx->nAvgBytesPerSec = s->wfx->nBlockAlign * s->wfx->nSamplesPerSec;
- int samples = stb_vorbis_stream_length_in_samples(vb_data);
-
-
- s->wave_data = snd_alloc(samples * s->wfx->nChannels *2);
- int samples_read = 0;
- short* ptr = (short*)s->wave_data;
- do
- {
- samples_read = stb_vorbis_get_samples_short_interleaved(vb_data,s->wfx->nChannels,ptr,samples);
- ptr += samples_read*s->wfx->nChannels;
- }
- while(samples_read > 0);
- s->wave_data_size = samples * s->wfx->nChannels *2;
- stb_vorbis_close(vb_data);
-
- HRESULT hr = g_xaudio2->CreateSourceVoice(&(s->source_voice), s->wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
- if(hr != S_OK)
- {
- snd_free((void*)s->wave_data);
- snd_free((void*)s->wfx);
- snd_free((void*)s);
- return NULL;
- }
- reset_sound(s);
- return s;
- }
-
- void destroy_sound(sound* s)
- {
- snd_free((void*)s->wave_data);
- snd_free((void*)s->wfx);
- snd_free((void*)s);
- }
-
- void reset_sound(sound* s)
- {
- ASSERT(s);
- memset(&s->buffer, 0, sizeof(XAUDIO2_BUFFER));
- s->buffer.Flags = XAUDIO2_END_OF_STREAM;
- s->buffer.AudioBytes = s->wave_data_size;
- s->buffer.pAudioData = (BYTE*)s->wave_data;
- HRESULT hr = s->source_voice->SubmitSourceBuffer(&s->buffer);
- ASSERT(hr == S_OK);
- }
-
- void play_sound(sound* s)
- {
- HRESULT hr = s->source_voice->Start( 0, XAUDIO2_COMMIT_NOW );
- ASSERT(hr == S_OK);
- }
-
- void stop_sound(sound* s)
- {
- ASSERT(s);
- HRESULT hr = s->source_voice->Stop();
- ASSERT(hr == S_OK);
- }
-
- void set_volume(sound* s, float volume)
- {
- ASSERT(s);
- s->source_voice->SetVolume(volume);
- }
-
- void get_volume(sound* s, float* out)
- {
- ASSERT(s);
- s->source_voice->GetVolume(out);
- }
-
- bool is_playing(sound* s)
- {
- ASSERT(s);
- static XAUDIO2_VOICE_STATE state;
- s->source_voice->GetState(&state);
- return state.BuffersQueued > 0;
- }
-
- uint32 get_bytes_per_sample(sound* s)
- {
- ASSERT(s);
- return s->wfx->nChannels * 2;
- }
-
- uint32 get_data_size(sound* s)
- {
- ASSERT(s);
- return s->wave_data_size;
- }
-
- uint64 get_pos_in_samples(sound* s)
- {
- ASSERT(s);
- XAUDIO2_VOICE_STATE voice_state;
- s->source_voice->GetState(&voice_state);
- return voice_state.SamplesPlayed;
- }
-
-
-
- }