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:
@@ -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
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
30
src/sound.h
30
src/sound.h
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user