From cd2778adcfc307ecca47157042c15d778b9a23d3 Mon Sep 17 00:00:00 2001 From: XProger Date: Mon, 7 Jan 2019 01:56:45 +0300 Subject: [PATCH] play ogg from memory, #15 move sound fill to separated thread --- src/platform/win/main.cpp | 52 ++++++++++++++++++++++++++++----------- src/sound.h | 30 ++++++++++++++-------- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/src/platform/win/main.cpp b/src/platform/win/main.cpp index 2955e54..29f635c 100644 --- a/src/platform/win/main.cpp +++ b/src/platform/win/main.cpp @@ -121,8 +121,7 @@ InputKey mouseToInputKey(int msg) { } // joystick -typedef struct _XINPUT_GAMEPAD -{ +typedef struct _XINPUT_GAMEPAD { WORD wButtons; BYTE bLeftTrigger; BYTE bRightTrigger; @@ -132,14 +131,12 @@ typedef struct _XINPUT_GAMEPAD SHORT sThumbRY; } XINPUT_GAMEPAD, *PXINPUT_GAMEPAD; -typedef struct _XINPUT_STATE -{ +typedef struct _XINPUT_STATE { DWORD dwPacketNumber; XINPUT_GAMEPAD Gamepad; } XINPUT_STATE, *PXINPUT_STATE; -typedef struct _XINPUT_VIBRATION -{ +typedef struct _XINPUT_VIBRATION { WORD wLeftMotorSpeed; WORD wRightMotorSpeed; } XINPUT_VIBRATION, *PXINPUT_VIBRATION; @@ -354,10 +351,16 @@ char *sndData; HWAVEOUT waveOut; WAVEFORMATEX waveFmt = { WAVE_FORMAT_PCM, 2, 44100, 44100 * 4, 4, 16, sizeof(waveFmt) }; WAVEHDR waveBuf[2]; +HANDLE sndThread; +HANDLE sndSema; void sndFree() { if (!sndReady) return; sndReady = false; + ReleaseSemaphore(sndSema, 1, NULL); + WaitForSingleObject(sndThread, INFINITE); + CloseHandle(sndThread); + CloseHandle(sndSema); waveOutUnprepareHeader(waveOut, &waveBuf[0], sizeof(WAVEHDR)); waveOutUnprepareHeader(waveOut, &waveBuf[1], sizeof(WAVEHDR)); waveOutReset(waveOut); @@ -365,24 +368,43 @@ void sndFree() { delete[] sndData; } -void sndFill(HWAVEOUT waveOut, LPWAVEHDR waveBuf) { +DWORD WINAPI sndPrep(void* arg) { + int idx = 0; + while (1) { + WaitForSingleObject(sndSema, INFINITE); + if (!sndReady) break; + + WAVEHDR *hdr = waveBuf + idx; + waveOutUnprepareHeader(waveOut, hdr, sizeof(WAVEHDR)); + Sound::fill((Sound::Frame*)hdr->lpData, SND_SIZE / 4); + waveOutPrepareHeader(waveOut, hdr, sizeof(WAVEHDR)); + waveOutWrite(waveOut, hdr, sizeof(WAVEHDR)); + + idx ^= 1; + } + return 0; +} + +void sndFill(HWAVEOUT waveOut, LPWAVEHDR waveBufPrev) { if (!sndReady) return; - waveOutUnprepareHeader(waveOut, waveBuf, sizeof(WAVEHDR)); - Sound::fill((Sound::Frame*)waveBuf->lpData, SND_SIZE / 4); - waveOutPrepareHeader(waveOut, waveBuf, sizeof(WAVEHDR)); - waveOutWrite(waveOut, waveBuf, sizeof(WAVEHDR)); + ReleaseSemaphore(sndSema, 1, NULL); } void sndInit(HWND hwnd) { if (waveOutOpen(&waveOut, WAVE_MAPPER, &waveFmt, (INT_PTR)hwnd, 0, CALLBACK_WINDOW) == MMSYSERR_NOERROR) { sndReady = true; sndData = new char[SND_SIZE * 2]; + memset(sndData, 0, SND_SIZE * 2); memset(&waveBuf, 0, sizeof(waveBuf)); for (int i = 0; i < 2; i++) { - waveBuf[i].dwBufferLength = SND_SIZE; - waveBuf[i].lpData = sndData + SND_SIZE * i; - sndFill(waveOut, &waveBuf[i]); + WAVEHDR *hdr = waveBuf + i; + hdr->dwBufferLength = SND_SIZE; + hdr->lpData = sndData + SND_SIZE * i; + waveOutPrepareHeader(waveOut, hdr, sizeof(WAVEHDR)); + waveOutWrite(waveOut, hdr, sizeof(WAVEHDR)); } + sndSema = CreateSemaphore(NULL, 0, 2, NULL); + sndThread = CreateThread(NULL, 0, sndPrep, NULL, 0, NULL); } else { sndReady = false; sndData = NULL; @@ -775,7 +797,7 @@ int main(int argc, char** argv) { ContextSwap(); } #ifdef _DEBUG - Sleep(20); + Sleep(10); #endif } }; diff --git a/src/sound.h b/src/sound.h index 2dbdfee..16ea3ee 100644 --- a/src/sound.h +++ b/src/sound.h @@ -72,7 +72,9 @@ namespace Sound { float out; float process(float x, float gain, float damping) { - return out = out * damping + x * gain * (1.0f - damping); + out = out * damping + x * gain * (1.0f - damping); + if (out < EPS) out = 0.0f; + return out; } }; @@ -99,6 +101,9 @@ namespace Sound { panCoeff[i][1] = panCoeff[i + 1][1] = k; } + memset(df, 0, sizeof(df)); + memset(af, 0, sizeof(af)); + setRoomSize(vec3(1.0f)); } @@ -120,8 +125,8 @@ namespace Sound { for (int i = 0; i < count; i++) { FrameHI &frame = frames[i]; - float L = frame.L * (1.0f / 32768.0f); - float R = frame.R * (1.0f / 32768.0f); + float L = frame.L * (1.0f / 32767.0f); + float R = frame.R * (1.0f / 32767.0f); float in = (L + R) * 0.5f; float out = 0.0f; @@ -137,14 +142,13 @@ namespace Sound { // apply pan for (int j = 0; j < MAX_FDN; j++) { output[j] = out - buffer[(j + MAX_FDN - 1) % MAX_FDN]; - if (output[j] < EPS) - output[j] = 0.0f; + if (output[j] < EPS) output[j] = 0.0f; L += buffer[j] * panCoeff[j][0]; R += buffer[j] * panCoeff[j][1]; } - frame.L = int(L * 32768.0f); - frame.R = int(R * 32768.0f); + frame.L = int(L * 32767.0f); + frame.R = int(R * 32767.0f); } } }; @@ -635,14 +639,19 @@ namespace Sound { stb_vorbis *ogg; stb_vorbis_alloc alloc; + uint8 *data; + OGG(Stream *stream, int channels) : Decoder(stream, channels, 0), ogg(NULL) { char buf[255]; strcpy(buf, contentDir); strcat(buf, stream->name); + data = new uint8[stream->size]; + stream->raw(data, stream->size); + alloc.alloc_buffer_length_in_bytes = 256 * 1024; alloc.alloc_buffer = new char[alloc.alloc_buffer_length_in_bytes]; - ogg = stb_vorbis_open_filename(buf, NULL, &alloc); + ogg = stb_vorbis_open_memory(data, stream->size, NULL, &alloc); ASSERT(ogg); stb_vorbis_info info = stb_vorbis_get_info(ogg); this->channels = info.channels; @@ -652,6 +661,7 @@ namespace Sound { virtual ~OGG() { stb_vorbis_close(ogg); delete[] alloc.alloc_buffer; + delete[] data; } virtual int decode(Frame *frames, int count) { @@ -946,8 +956,8 @@ namespace Sound { void convFrames(FrameHI *from, Frame *to, int count) { for (int i = 0; i < count; i++) { - to[i].L = clamp(from[i].L, -32768, 32767); - to[i].R = clamp(from[i].R, -32768, 32767); + to[i].L = clamp(from[i].L, -32767, 32767); + to[i].R = clamp(from[i].R, -32767, 32767); } }