1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-04-22 03:51:58 +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
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
}
};

View File

@ -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);
}
}