1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-04 20:27:39 +02:00

play ogg from memory, #15 move sound fill to separated thread

This commit is contained in:
XProger
2019-01-07 01:56:45 +03:00
parent b965ce4ef4
commit cd2778adcf
2 changed files with 57 additions and 25 deletions

View File

@@ -121,8 +121,7 @@ InputKey mouseToInputKey(int msg) {
} }
// joystick // joystick
typedef struct _XINPUT_GAMEPAD typedef struct _XINPUT_GAMEPAD {
{
WORD wButtons; WORD wButtons;
BYTE bLeftTrigger; BYTE bLeftTrigger;
BYTE bRightTrigger; BYTE bRightTrigger;
@@ -132,14 +131,12 @@ typedef struct _XINPUT_GAMEPAD
SHORT sThumbRY; SHORT sThumbRY;
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD; } XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
typedef struct _XINPUT_STATE typedef struct _XINPUT_STATE {
{
DWORD dwPacketNumber; DWORD dwPacketNumber;
XINPUT_GAMEPAD Gamepad; XINPUT_GAMEPAD Gamepad;
} XINPUT_STATE, *PXINPUT_STATE; } XINPUT_STATE, *PXINPUT_STATE;
typedef struct _XINPUT_VIBRATION typedef struct _XINPUT_VIBRATION {
{
WORD wLeftMotorSpeed; WORD wLeftMotorSpeed;
WORD wRightMotorSpeed; WORD wRightMotorSpeed;
} XINPUT_VIBRATION, *PXINPUT_VIBRATION; } XINPUT_VIBRATION, *PXINPUT_VIBRATION;
@@ -354,10 +351,16 @@ char *sndData;
HWAVEOUT waveOut; HWAVEOUT waveOut;
WAVEFORMATEX waveFmt = { WAVE_FORMAT_PCM, 2, 44100, 44100 * 4, 4, 16, sizeof(waveFmt) }; WAVEFORMATEX waveFmt = { WAVE_FORMAT_PCM, 2, 44100, 44100 * 4, 4, 16, sizeof(waveFmt) };
WAVEHDR waveBuf[2]; WAVEHDR waveBuf[2];
HANDLE sndThread;
HANDLE sndSema;
void sndFree() { void sndFree() {
if (!sndReady) return; if (!sndReady) return;
sndReady = false; sndReady = false;
ReleaseSemaphore(sndSema, 1, NULL);
WaitForSingleObject(sndThread, INFINITE);
CloseHandle(sndThread);
CloseHandle(sndSema);
waveOutUnprepareHeader(waveOut, &waveBuf[0], sizeof(WAVEHDR)); waveOutUnprepareHeader(waveOut, &waveBuf[0], sizeof(WAVEHDR));
waveOutUnprepareHeader(waveOut, &waveBuf[1], sizeof(WAVEHDR)); waveOutUnprepareHeader(waveOut, &waveBuf[1], sizeof(WAVEHDR));
waveOutReset(waveOut); waveOutReset(waveOut);
@@ -365,24 +368,43 @@ void sndFree() {
delete[] sndData; 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; if (!sndReady) return;
waveOutUnprepareHeader(waveOut, waveBuf, sizeof(WAVEHDR)); ReleaseSemaphore(sndSema, 1, NULL);
Sound::fill((Sound::Frame*)waveBuf->lpData, SND_SIZE / 4);
waveOutPrepareHeader(waveOut, waveBuf, sizeof(WAVEHDR));
waveOutWrite(waveOut, waveBuf, sizeof(WAVEHDR));
} }
void sndInit(HWND hwnd) { void sndInit(HWND hwnd) {
if (waveOutOpen(&waveOut, WAVE_MAPPER, &waveFmt, (INT_PTR)hwnd, 0, CALLBACK_WINDOW) == MMSYSERR_NOERROR) { if (waveOutOpen(&waveOut, WAVE_MAPPER, &waveFmt, (INT_PTR)hwnd, 0, CALLBACK_WINDOW) == MMSYSERR_NOERROR) {
sndReady = true; sndReady = true;
sndData = new char[SND_SIZE * 2]; sndData = new char[SND_SIZE * 2];
memset(sndData, 0, SND_SIZE * 2);
memset(&waveBuf, 0, sizeof(waveBuf)); memset(&waveBuf, 0, sizeof(waveBuf));
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
waveBuf[i].dwBufferLength = SND_SIZE; WAVEHDR *hdr = waveBuf + i;
waveBuf[i].lpData = sndData + SND_SIZE * i; hdr->dwBufferLength = SND_SIZE;
sndFill(waveOut, &waveBuf[i]); 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 { } else {
sndReady = false; sndReady = false;
sndData = NULL; sndData = NULL;
@@ -775,7 +797,7 @@ int main(int argc, char** argv) {
ContextSwap(); ContextSwap();
} }
#ifdef _DEBUG #ifdef _DEBUG
Sleep(20); Sleep(10);
#endif #endif
} }
}; };

View File

@@ -72,7 +72,9 @@ namespace Sound {
float out; float out;
float process(float x, float gain, float damping) { 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; panCoeff[i][1] = panCoeff[i + 1][1] = k;
} }
memset(df, 0, sizeof(df));
memset(af, 0, sizeof(af));
setRoomSize(vec3(1.0f)); setRoomSize(vec3(1.0f));
} }
@@ -120,8 +125,8 @@ namespace Sound {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
FrameHI &frame = frames[i]; FrameHI &frame = frames[i];
float L = frame.L * (1.0f / 32768.0f); float L = frame.L * (1.0f / 32767.0f);
float R = frame.R * (1.0f / 32768.0f); float R = frame.R * (1.0f / 32767.0f);
float in = (L + R) * 0.5f; float in = (L + R) * 0.5f;
float out = 0.0f; float out = 0.0f;
@@ -137,14 +142,13 @@ namespace Sound {
// apply pan // apply pan
for (int j = 0; j < MAX_FDN; j++) { for (int j = 0; j < MAX_FDN; j++) {
output[j] = out - buffer[(j + MAX_FDN - 1) % MAX_FDN]; output[j] = out - buffer[(j + MAX_FDN - 1) % MAX_FDN];
if (output[j] < EPS) if (output[j] < EPS) output[j] = 0.0f;
output[j] = 0.0f;
L += buffer[j] * panCoeff[j][0]; L += buffer[j] * panCoeff[j][0];
R += buffer[j] * panCoeff[j][1]; R += buffer[j] * panCoeff[j][1];
} }
frame.L = int(L * 32768.0f); frame.L = int(L * 32767.0f);
frame.R = int(R * 32768.0f); frame.R = int(R * 32767.0f);
} }
} }
}; };
@@ -635,14 +639,19 @@ namespace Sound {
stb_vorbis *ogg; stb_vorbis *ogg;
stb_vorbis_alloc alloc; stb_vorbis_alloc alloc;
uint8 *data;
OGG(Stream *stream, int channels) : Decoder(stream, channels, 0), ogg(NULL) { OGG(Stream *stream, int channels) : Decoder(stream, channels, 0), ogg(NULL) {
char buf[255]; char buf[255];
strcpy(buf, contentDir); strcpy(buf, contentDir);
strcat(buf, stream->name); 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_length_in_bytes = 256 * 1024;
alloc.alloc_buffer = new char[alloc.alloc_buffer_length_in_bytes]; 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); ASSERT(ogg);
stb_vorbis_info info = stb_vorbis_get_info(ogg); stb_vorbis_info info = stb_vorbis_get_info(ogg);
this->channels = info.channels; this->channels = info.channels;
@@ -652,6 +661,7 @@ namespace Sound {
virtual ~OGG() { virtual ~OGG() {
stb_vorbis_close(ogg); stb_vorbis_close(ogg);
delete[] alloc.alloc_buffer; delete[] alloc.alloc_buffer;
delete[] data;
} }
virtual int decode(Frame *frames, int count) { virtual int decode(Frame *frames, int count) {
@@ -946,8 +956,8 @@ namespace Sound {
void convFrames(FrameHI *from, Frame *to, int count) { void convFrames(FrameHI *from, Frame *to, int count) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
to[i].L = clamp(from[i].L, -32768, 32767); to[i].L = clamp(from[i].L, -32767, 32767);
to[i].R = clamp(from[i].R, -32768, 32767); to[i].R = clamp(from[i].R, -32767, 32767);
} }
} }