PageRenderTime 20ms CodeModel.GetById 1ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/src/sound/sound.cpp

https://bitbucket.org/vivkin/gam3b00bs/
C++ | 206 lines | 171 code | 35 blank | 0 comment | 10 complexity | d3fd4a573c14ea4a55d250ce44574f88 MD5 | raw file
  1#include <xaudio2.h>
  2#include <mmsystem.h>
  3#include <stb_vorbis/stb_vorbis.h>
  4#include "common.h"
  5#include "sound.h"
  6
  7namespace snd
  8{
  9	static tlsf_pool gs_sound_heap;
 10	IXAudio2* g_xaudio2 = NULL;
 11	IXAudio2MasteringVoice* g_mastering_voice = NULL;
 12	stb_vorbis_alloc vorbis_alloc;
 13
 14	struct sound
 15	{
 16		XAUDIO2_BUFFER buffer;
 17		IXAudio2SourceVoice* source_voice;
 18		WAVEFORMATEX* wfx;
 19		uint32 wave_data_size; 
 20		void* wave_data;
 21
 22	};
 23
 24
 25
 26	inline void* snd_alloc(size_t size)
 27	{
 28		return tlsf_malloc(gs_sound_heap, size);
 29	}
 30
 31	inline void snd_free(void* ptr)
 32	{
 33		tlsf_free(gs_sound_heap, ptr);
 34	}
 35
 36
 37	bool init(void* memory, size_t size, size_t decoder_size)
 38	{
 39		ASSERT(memory);
 40		ASSERT(size);
 41		gs_sound_heap = tlsf_create(memory, size);
 42		vorbis_alloc.alloc_buffer = (char*)snd_alloc(decoder_size);
 43		vorbis_alloc.alloc_buffer_length_in_bytes = decoder_size;
 44		CoInitializeEx(0,COINIT_MULTITHREADED);
 45		if(XAudio2Create(&g_xaudio2,0,XAUDIO2_DEFAULT_PROCESSOR)!=S_OK)
 46		{
 47			CoUninitialize();
 48			return false;
 49		}
 50		if(g_xaudio2->CreateMasteringVoice( &g_mastering_voice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, 0,0)!=S_OK)
 51		{
 52			g_xaudio2->Release();
 53			g_xaudio2 = NULL;
 54			CoUninitialize();
 55		    return false;
 56		}
 57
 58		return true;
 59	}
 60	
 61	void term()
 62	{
 63		snd_free(vorbis_alloc.alloc_buffer);
 64		vorbis_alloc.alloc_buffer = NULL;
 65		vorbis_alloc.alloc_buffer_length_in_bytes = 0;
 66		g_mastering_voice->DestroyVoice();
 67		g_mastering_voice = NULL;
 68		g_xaudio2->Release();
 69		g_xaudio2 = NULL;
 70	}
 71
 72
 73	void set_master_volume(float volume)
 74	{
 75		ASSERT(g_mastering_voice);
 76		g_mastering_voice->SetVolume(volume);
 77	}
 78
 79	void get_master_volume(float* out)
 80	{
 81		ASSERT(g_mastering_voice && out);
 82		g_mastering_voice->GetVolume(out);
 83	}
 84
 85	sound* load_sound(char* filename)
 86	{
 87		sound* s = (sound*)snd_alloc(sizeof(sound));
 88		memset(s,0,sizeof(sound));
 89
 90		int error = 0;
 91		stb_vorbis* vb_data = stb_vorbis_open_filename(filename,&error,&vorbis_alloc);
 92		if(error != VORBIS__no_error)
 93			return NULL;
 94		stb_vorbis_info vorbis_info = stb_vorbis_get_info(vb_data);
 95		
 96
 97
 98		s->wfx = (WAVEFORMATEX*)snd_alloc(sizeof(WAVEFORMATEX));
 99		memset(s->wfx,0,sizeof(WAVEFORMATEX));
100		s->wfx->wFormatTag = WAVE_FORMAT_PCM;
101		s->wfx->wBitsPerSample = 16;
102		s->wfx->nSamplesPerSec = vorbis_info.sample_rate;
103		s->wfx->nChannels = (WORD)vorbis_info.channels;
104		s->wfx->nBlockAlign = s->wfx->nChannels*2;
105		s->wfx->nAvgBytesPerSec = s->wfx->nBlockAlign * s->wfx->nSamplesPerSec;
106		int samples = stb_vorbis_stream_length_in_samples(vb_data);
107
108
109		s->wave_data = snd_alloc(samples * s->wfx->nChannels *2);
110		int samples_read = 0;
111		short* ptr = (short*)s->wave_data;
112		do
113		{
114			samples_read = stb_vorbis_get_samples_short_interleaved(vb_data,s->wfx->nChannels,ptr,samples);
115			ptr += samples_read*s->wfx->nChannels;
116		}
117		while(samples_read > 0);
118		s->wave_data_size = samples * s->wfx->nChannels *2;
119		stb_vorbis_close(vb_data);
120
121		HRESULT hr = g_xaudio2->CreateSourceVoice(&(s->source_voice), s->wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
122		if(hr != S_OK)
123		{
124			snd_free((void*)s->wave_data);
125			snd_free((void*)s->wfx);
126			snd_free((void*)s);
127			return NULL;
128		}	
129		reset_sound(s);
130		return s;
131	}
132
133	void destroy_sound(sound* s)
134	{
135		snd_free((void*)s->wave_data);
136		snd_free((void*)s->wfx);
137		snd_free((void*)s);
138	}
139
140	void reset_sound(sound* s)
141	{
142		ASSERT(s);
143		memset(&s->buffer, 0, sizeof(XAUDIO2_BUFFER));
144		s->buffer.Flags = XAUDIO2_END_OF_STREAM;
145		s->buffer.AudioBytes = s->wave_data_size;
146		s->buffer.pAudioData = (BYTE*)s->wave_data;
147		HRESULT hr = s->source_voice->SubmitSourceBuffer(&s->buffer);
148		ASSERT(hr == S_OK);
149	}
150
151	void play_sound(sound* s)
152	{
153		HRESULT hr = s->source_voice->Start( 0, XAUDIO2_COMMIT_NOW );
154		ASSERT(hr == S_OK);
155	}
156
157	void stop_sound(sound* s)
158	{
159		ASSERT(s);
160		HRESULT hr = s->source_voice->Stop();
161		ASSERT(hr == S_OK);
162	}
163
164	void set_volume(sound* s, float volume)
165	{
166		ASSERT(s);
167		s->source_voice->SetVolume(volume);
168	}
169
170	void get_volume(sound* s, float* out)
171	{
172		ASSERT(s);
173		s->source_voice->GetVolume(out);
174	}
175
176	bool is_playing(sound* s)
177	{
178		ASSERT(s);
179		static XAUDIO2_VOICE_STATE state;
180		s->source_voice->GetState(&state);
181		return state.BuffersQueued > 0;
182	}
183
184	uint32 get_bytes_per_sample(sound* s)
185	{
186		ASSERT(s);
187		return s->wfx->nChannels * 2;
188	}
189
190	uint32 get_data_size(sound* s)
191	{
192		ASSERT(s);
193		return s->wave_data_size;
194	}
195
196	uint64 get_pos_in_samples(sound* s)
197	{
198		ASSERT(s);
199		XAUDIO2_VOICE_STATE voice_state;
200		s->source_voice->GetState(&voice_state);
201		return voice_state.SamplesPlayed;
202	}
203
204
205
206}