1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-12 16:14:25 +02:00

#9 add simple sound mixing for a PCM, MS ADPCM (from TR3 cdaudio.wad), MP3 (via minimp3 lib) & OGG (via stb_vorbis lib)

This commit is contained in:
XProger
2016-10-04 04:00:22 +03:00
parent e16f25f94d
commit be5dae6e2d
15 changed files with 8682 additions and 34 deletions

View File

@@ -166,8 +166,9 @@ struct Controller {
if (b.chance == 0 || (rand() & 0x7fff) <= b.chance) {
uint32 c = level->soundOffsets[b.offset + rand() % ((b.flags & 0xFF) >> 2)];
void *p = &level->soundData[c];
#ifdef WIN32
PlaySound((LPSTR)p, NULL, SND_ASYNC | SND_MEMORY);
#ifdef WIN32
Sound::play(new Stream(p, 1024 * 1024), b.volume / 255.0f, 0.0f, Sound::Flags::PAN);
// PlaySound((LPSTR)p, NULL, SND_ASYNC | SND_MEMORY);
#endif
}
}

View File

@@ -16,6 +16,7 @@
#include "utils.h"
#include "input.h"
#include "sound.h"
#ifdef WIN32
#if defined(_MSC_VER) // Visual Studio
@@ -119,10 +120,11 @@ namespace Core {
GetProcOGL(glBindBuffer);
GetProcOGL(glBufferData);
#endif
Sound::init();
}
void free() {
//
Sound::free();
}
void clear(const vec4 &color) {

View File

@@ -525,7 +525,7 @@ namespace Debug {
void info(const TR::Level &level, const TR::Entity &entity) {
char buf[255];
sprintf(buf, "DIP = %d, TRI = %d", Core::stats.dips, Core::stats.tris);
sprintf(buf, "DIP = %d, TRI = %d, SND = %d", Core::stats.dips, Core::stats.tris, Sound::channelsCount);
Debug::Draw::text(vec2(16, 16), vec4(1.0f), buf);
sprintf(buf, "pos = (%d, %d, %d), room = %d", entity.x, entity.y, entity.z, entity.room);
Debug::Draw::text(vec2(16, 32), vec4(1.0f), buf);

View File

@@ -14,6 +14,10 @@ namespace Game {
Core::init();
Stream stream("LEVEL2_DEMO.PHD");
level = new Level(stream);
//Sound::play(Sound::openWAD("05_Lara's_Themes.wav"), 1, 1, 0);
Sound::play(new Stream("05.ogg"), 1, 1, 0);
//Sound::play(new Stream("03.mp3"), 1, 1, 0);
}
void free() {

90
src/libs/minimp3/libc.h Normal file
View File

@@ -0,0 +1,90 @@
// a libc replacement (more or less) for the Microsoft Visual C compiler
// this file is public domain -- do with it whatever you want!
#ifndef __LIBC_H_INCLUDED__
#define __LIBC_H_INCLUDED__
#ifdef _MSC_VER
#define INLINE __forceinline
#define FASTCALL __fastcall
#ifdef NOLIBC
#ifdef MAIN_PROGRAM
int _fltused=0;
#endif
#endif
#else
#define INLINE inline
#define FASTCALL __attribute__((fastcall))
#include <stdint.h>
#endif
#ifdef _WIN32
#ifndef WIN32
#define WIN32
#endif
#endif
#ifdef WIN32
#include <windows.h>
#endif
#if !NEED_MINILIBC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include <math.h>
#ifndef __int8_t_defined
#define __int8_t_defined
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
#ifdef _MSC_VER
typedef unsigned __int64 uint64_t;
typedef signed __int64 int64_t;
#else
typedef unsigned long long uint64_t;
typedef signed long long int64_t;
#endif
#endif
#ifndef NULL
#define NULL 0
#endif
#ifndef M_PI
#define M_PI 3.14159265358979
#endif
#define libc_malloc malloc
#define libc_calloc calloc
#define libc_realloc realloc
#define libc_free free
#define libc_memset memset
#define libc_memcpy memcpy
#define libc_memmove memmove
#if defined(_MSC_VER) && !defined(_DEBUG)
static INLINE double libc_frexp(double x, int *e) {
double res = -9999.999;
unsigned __int64 i = *(unsigned __int64*)(&x);
if (!(i & 0x7F00000000000000UL)) {
*e = 0;
return x;
}
*e = ((i << 1) >> 53) - 1022;
i &= 0x800FFFFFFFFFFFFFUL;
i |= 0x3FF0000000000000UL;
return *(double*)(&i) * 0.5;
}
#else
#define libc_frexp frexp
#endif
#define libc_exp exp
#define libc_pow pow
#endif//__LIBC_H_INCLUDED__

2666
src/libs/minimp3/minimp3.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
#ifndef __MINIMP3_H_INCLUDED__
#define __MINIMP3_H_INCLUDED__
typedef struct _mp3_info {
int sample_rate;
int channels;
int audio_bytes; // generated amount of audio per frame
} mp3_info_t;
typedef void* mp3_decoder_t;
mp3_decoder_t mp3_create(void);
extern int mp3_decode(mp3_decoder_t dec, void *buf, int bytes, signed short *out, mp3_info_t *info);
void mp3_done(mp3_decoder_t dec);
int mp3_decode_init();
void mp3_decode_free();
#endif//__MINIMP3_H_INCLUDED__

File diff suppressed because it is too large Load Diff

356
src/sound.h Normal file
View File

@@ -0,0 +1,356 @@
#ifndef H_SOUND
#define H_SOUND
#include "utils.h"
#include "libs/minimp3/minimp3.h"
#define STB_VORBIS_HEADER_ONLY
#include "libs/stb_vorbis/stb_vorbis.c"
#define SND_CHANNELS_MAX 32
#define BUFFER_SIZE_MP3 8192
namespace Sound {
struct Frame {
short L, R;
};
struct Decoder {
Stream *stream;
int channels, offset;
Decoder(Stream *stream, int channels) : stream(stream), channels(channels), offset(stream->pos) {}
virtual ~Decoder() { delete stream; }
virtual int decode(Frame *frames, int count) { return 0; }
};
struct PCM : Decoder {
int freq, size, bits;
PCM(Stream *stream, int channels, int freq, int size, int bits) : Decoder(stream, channels), freq(freq), size(size), bits(bits) {}
virtual int decode(Frame *frames, int count) {
if (stream->pos - offset >= size) return 0;
if (bits == 16) {
int16 value;
if (channels == 2) {
frames[0].L = stream->read(value);
frames[0].R = stream->read(value);
} else
frames[0].L = frames[0].R = stream->read(value);
} else if (bits == 8) {
uint8 value;
if (channels == 2) {
frames[0].L = stream->read(value) * 257 - 32768;
frames[0].R = stream->read(value) * 257 - 32768;
} else
frames[0].L = frames[0].R = stream->read(value) * 257 - 32768;
} else {
ASSERT(false);
return 0;
}
int k = 44100 / freq;
for (int i = 1; i < k; i++) frames[i] = frames[0];
return k;
}
};
struct ADPCM : Decoder { // https://wiki.multimedia.cx/?title=Microsoft_ADPCM
int size, block;
ADPCM(Stream *stream, int channels, int size, int block) : Decoder(stream, channels), size(size), block(block) {}
struct Channel {
int16 c1, c2;
int16 delta;
int16 sample1;
int16 sample2;
int predicate(uint8 nibble) {
static const int table[] = { 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230 };
int8 ns = nibble;
if (ns & 8) ns -= 16;
int sample = (sample1 * c1 + sample2 * c2) / 256 + ns * delta;
sample = clamp(sample, -32768, 32767);
sample2 = sample1;
sample1 = sample;
delta = max(table[nibble] * delta / 256, 16);
return sample;
}
} channel[2];
virtual int decode(Frame *frames, int count) {
static const int coeff1[] = { 256, 512, 0, 192, 240, 460, 392 };
static const int coeff2[] = { 0, -256, 0, 64, 0, -208, -232 };
int seek = stream->pos - offset;
if (seek >= size) return 0;
if (seek % block == 0) {
for (int i = 0; i < channels; i++) {
char index;
stream->read(index);
channel[i].c1 = coeff1[index];
channel[i].c2 = coeff2[index];
}
for (int i = 0; i < channels; i++) stream->read(channel[i].delta);
for (int i = 0; i < channels; i++) stream->read(channel[i].sample1);
for (int i = 0; i < channels; i++) stream->read(channel[i].sample2);
if (channels == 1) {
frames[0].L = frames[0].R = channel[0].sample2;
frames[1].L = frames[1].R = channel[0].sample1;
} else {
frames[0].L = channel[0].sample2;
frames[0].R = channel[1].sample2;
frames[1].L = channel[0].sample1;
frames[1].R = channel[1].sample1;
}
return 2;
} else {
uint8 value;
stream->read(value);
uint8 n1 = value >> 4, n2 = value & 0xF;
if (channels == 1) {
frames[0].L = frames[0].R = channel[0].predicate(n1);
frames[1].L = frames[1].R = channel[0].predicate(n2);
return 2;
} else {
frames[0].L = channel[0].predicate(n1);
frames[0].R = channel[1].predicate(n2);
return 1;
}
}
}
};
struct MP3 : Decoder {
mp3_decoder_t mp3;
char *buffer;
int size, pos;
MP3(Stream *stream, int channels) : Decoder(stream, channels), size(stream->size), pos(0) {
mp3 = mp3_create();
buffer = new char[size]; // TODO: file streaming
stream->raw(buffer, size);
}
virtual ~MP3() {
delete[] buffer;
mp3_done(mp3);
}
virtual int decode(Frame *frames, int count) {
mp3_info_t info;
int i = 0;
char *ptr = (char*)frames;
while (ptr < (char*)&frames[count]) {
int res = mp3_decode(mp3, buffer + pos, size - pos, (short*)ptr, &info);
if (res) {
pos += res;
ptr += info.audio_bytes;
i += info.audio_bytes;
} else
break;
}
return i;
}
};
struct OGG : Decoder {
stb_vorbis *ogg;
stb_vorbis_alloc alloc;
char *buffer;
int size, pos;
OGG(Stream *stream, int channels) : Decoder(stream, channels), size(stream->size), pos(0) {
buffer = new char[size]; // TODO: file streaming
stream->raw(buffer, size);
int error;
alloc.alloc_buffer_length_in_bytes = 256 * 1024;
alloc.alloc_buffer = new char[alloc.alloc_buffer_length_in_bytes];
ogg = stb_vorbis_open_memory((unsigned char*)buffer, size, &error, &alloc);
stb_vorbis_info info = stb_vorbis_get_info(ogg);
channels = info.channels;
}
virtual ~OGG() {
stb_vorbis_close(ogg);
delete[] alloc.alloc_buffer;
delete[] buffer;
}
virtual int decode(Frame *frames, int count) {
int i = 0;
while (i < count) {
int res = stb_vorbis_get_samples_short_interleaved(ogg, channels, (short*)frames + i, (count - i) * 2);
if (!res) break;
i += res;
}
return i;
}
};
struct Listener {
mat4 matrix;
vec3 velocity;
} listener;
enum Flags {
LOOP = 1,
PAN = 2,
REVERB_NEAR = 4,
REVERB_MIDDLE = 8,
REVERB_FAR = 16,
};
struct Sample {
Decoder *decoder;
float volume;
float pitch;
int flags;
bool isPlaying;
Sample(Stream *stream, float volume, float pitch, int flags) : decoder(NULL), volume(volume), pitch(pitch), flags(flags), isPlaying(true) {
uint32 fourcc;
stream->read(fourcc);
if (fourcc == FOURCC("RIFF")) { // wav
struct {
uint16 format;
uint16 channels;
uint32 samplesPerSec;
uint32 bytesPerSec;
uint16 block;
uint16 sampleBits;
} waveFmt;
stream->seek(8);
while (stream->pos < stream->size) {
uint32 type, size;
stream->read(type);
stream->read(size);
if (type == FOURCC("fmt ")) {
stream->read(waveFmt);
stream->seek(size - sizeof(waveFmt));
} else if (type == FOURCC("data")) {
if (waveFmt.format == 1) decoder = new PCM(stream, waveFmt.channels, waveFmt.samplesPerSec, size, waveFmt.sampleBits);
if (waveFmt.format == 2) decoder = new ADPCM(stream, waveFmt.channels, size, waveFmt.block);
break;
} else
stream->seek(size);
}
} else if (fourcc == FOURCC("OggS")) { // ogg
stream->seek(-4);
decoder = new OGG(stream, 2);
} else if (fourcc == FOURCC("ID3\3")) { // mp3
decoder = new MP3(stream, 2);
}
ASSERT(decoder != NULL);
}
~Sample() {
delete decoder;
}
bool render(Frame *frames, int count) {
int i = 0;
while (i < count) {
int res = decoder->decode(&frames[i], count - i);
if (res == 0) {
if (i == 0) isPlaying = false;
break;
}
i += res;
}
return true;
}
} *channels[SND_CHANNELS_MAX];
int channelsCount;
void init() {
channelsCount = 0;
mp3_decode_init();
}
void free() {
for (int i = 0; i < channelsCount; i++)
delete channels[i];
mp3_decode_free();
}
void fill(Frame *frames, int count) {
struct FrameHI {
int L, R;
};
FrameHI *result = new FrameHI[count];
memset(result, 0, sizeof(FrameHI) * count);
Frame *buffer = new Frame[count];
for (int i = 0; i < channelsCount; i++) {
memset(buffer, 0, sizeof(Frame) * count);
channels[i]->render(buffer, count);
for (int j = 0; j < count; j++) {
result[j].L += buffer[j].L;
result[j].R += buffer[j].R;
}
}
for (int i = 0; i < count; i++) {
frames[i].L = clamp(result[i].L, -32768, 32767);
frames[i].R = clamp(result[i].R, -32768, 32767);
}
delete[] buffer;
delete[] result;
for (int i = 0; i < channelsCount; i++)
if (!channels[i]->isPlaying) {
delete channels[i];
channels[i] = channels[--channelsCount];
i--;
}
}
Stream *openWAD(const char *name) {
Stream *stream = new Stream("cdaudio.wad");
if (stream->size) {
struct Item {
char name[260];
int size;
int offset;
} entity;
for (int i = 0; i < 130; i++) {
stream->read(entity);
if (strcmp(name, entity.name) == 0) {
stream->setPos(entity.offset);
return stream;
}
}
}
delete stream;
return NULL;
}
void play(Stream *stream, float volume, float pitch, int flags) {
if (!stream) return;
if (channelsCount < SND_CHANNELS_MAX)
channels[channelsCount++] = new Sample(stream, volume, pitch, flags);
else
LOG("! no free channels\n");
}
}
#endif

View File

@@ -36,6 +36,8 @@ typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
#define FOURCC(str) (*((uint32*)str))
struct ubyte4 {
uint8 x, y, z, w;
};
@@ -473,9 +475,12 @@ struct mat4 {
struct Stream {
FILE *f;
int size, pos;
const char *data;
int size, pos;
Stream(const char *name) : pos(0) {
Stream(const void *data, int size) : f(NULL), data((char*)data), size(size), pos(0) {}
Stream(const char *name) : data(NULL), size(-1), pos(0) {
f = fopen(name, "rb");
if (!f) LOG("error loading file\n");
fseek(f, 0, SEEK_END);
@@ -484,32 +489,36 @@ struct Stream {
}
~Stream() {
fclose(f);
if (f) fclose(f);
}
void setPos(int pos) {
this->pos = pos;
fseek(f, pos, SEEK_SET);
if (f) fseek(f, pos, SEEK_SET);
}
void seek(int offset) {
fseek(f, offset, SEEK_CUR);
if (!offset) return;
if (f) fseek(f, offset, SEEK_CUR);
pos += offset;
}
int raw(void *data, int size) {
pos += size;
return fread(data, 1, size, f);
void raw(void *data, int count) {
if (f)
fread(data, 1, count, f);
else
memcpy(data, this->data + pos, count);
pos += count;
}
template <typename T>
T& read(T &x) {
inline T& read(T &x) {
raw(&x, sizeof(x));
return x;
}
template <typename T>
T* read(T *&a, int count) {
inline T* read(T *&a, int count) {
if (count) {
a = new T[count];
raw(a, count * sizeof(T));

View File

@@ -1,3 +1,3 @@
set SRC=main.cpp
call em++ %SRC% -O2 --llvm-opts 2 --closure 1 -std=c++11 -o OpenLara.js --preload-file ./LEVEL2_DEMO.PHD -I..\
set SRC=main.cpp ../libs/minimp3/minimp3.cpp ../libs/stb_vorbis/stb_vorbis.c
call em++ %SRC% -O2 -s ASSERTIONS=1 -Wno-deprecated-register --llvm-opts 2 --closure 2 -std=c++11 -o OpenLara.js --preload-file ./LEVEL2_DEMO.PHD -I..\
gzip.exe -9 -f OpenLara.data OpenLara.js OpenLara.js.mem

View File

@@ -56,8 +56,10 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>NOMINMAX;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>STB_VORBIS_NO_STDIO;NOMINMAX;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FloatingPointModel>Strict</FloatingPointModel>
<AdditionalOptions>
</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -73,26 +75,30 @@
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NOMINMAX;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>STB_VORBIS_NO_STDIO;NOMINMAX;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FloatingPointModel>Strict</FloatingPointModel>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalOptions>/d2noftol3 %(AdditionalOptions)</AdditionalOptions>
<WholeProgramOptimization>true</WholeProgramOptimization>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>opengl32.lib;winmm.lib;wcrt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>wcrt.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\libs\minimp3\minimp3.cpp" />
<ClCompile Include="..\libs\stb_vorbis\stb_vorbis.c" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
@@ -105,8 +111,11 @@
<ClInclude Include="..\input.h" />
<ClInclude Include="..\lara.h" />
<ClInclude Include="..\level.h" />
<ClInclude Include="..\libs\minimp3\libc.h" />
<ClInclude Include="..\libs\minimp3\minimp3.h" />
<ClInclude Include="..\mesh.h" />
<ClInclude Include="..\shader.h" />
<ClInclude Include="..\sound.h" />
<ClInclude Include="..\texture.h" />
<ClInclude Include="..\format.h" />
<ClInclude Include="..\trigger.h" />

View File

@@ -1,7 +1,13 @@
#ifdef _DEBUG
#include "crtdbg.h"
#endif
/* // VS2015 ?
#include <stdint.h>
void __cdecl operator delete(void *ptr, unsigned int size) {
//
}
*/
#include "game.h"
DWORD getTime() {
@@ -16,6 +22,7 @@ DWORD getTime() {
#endif
}
// common input functions
InputKey keyToInputKey(int code) {
int codes[] = {
VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_SPACE, VK_RETURN, VK_ESCAPE, VK_SHIFT, VK_CONTROL, VK_MENU,
@@ -35,7 +42,8 @@ InputKey mouseToInputKey(int msg) {
(msg >= WM_RBUTTONDOWN && msg <= WM_RBUTTONDBLCLK) ? ikMouseR : ikMouseM;
}
#define JOY_DEAD_ZONE_STICK 0.3f
// joystick
#define JOY_DEAD_ZONE_STICK 0.3f
#define JOY_DEAD_ZONE_TRIGGER 0.01f
bool joyReady;
@@ -99,11 +107,75 @@ void joyUpdate() {
joyFree();
}
// sound
#define SND_SIZE 4608*2
bool sndReady;
char *sndData;
CRITICAL_SECTION sndCS;
HWAVEOUT waveOut;
WAVEFORMATEX waveFmt = { WAVE_FORMAT_PCM, 2, 44100, 44100 * 4, 4, 16, sizeof(waveFmt) };
WAVEHDR waveBuf[2];
void soundFree() {
if (!sndReady) return;
sndReady = false;
EnterCriticalSection(&sndCS);
waveOutUnprepareHeader(waveOut, &waveBuf[0], sizeof(WAVEHDR));
waveOutUnprepareHeader(waveOut, &waveBuf[1], sizeof(WAVEHDR));
waveOutReset(waveOut);
waveOutClose(waveOut);
delete[] sndData;
LeaveCriticalSection(&sndCS);
DeleteCriticalSection(&sndCS);
}
void CALLBACK sndFill(HWAVEOUT waveOut, UINT uMsg, DWORD_PTR dwInstance, LPWAVEHDR waveBuf, DWORD dwParam2) {
if (!sndReady) return;
if (uMsg == MM_WOM_CLOSE) {
soundFree();
return;
}
EnterCriticalSection(&sndCS);
waveOutUnprepareHeader(waveOut, waveBuf, sizeof(WAVEHDR));
Sound::fill((Sound::Frame*)waveBuf->lpData, SND_SIZE / 4);
waveOutPrepareHeader(waveOut, waveBuf, sizeof(WAVEHDR));
waveOutWrite(waveOut, waveBuf, sizeof(WAVEHDR));
LeaveCriticalSection(&sndCS);
}
void soundInit(HWND hwnd) {
InitializeCriticalSection(&sndCS);
if (waveOutOpen(&waveOut, WAVE_MAPPER, &waveFmt, (INT_PTR)sndFill, 0, CALLBACK_FUNCTION) == MMSYSERR_NOERROR) {
sndReady = true;
sndData = new char[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, 0, 0, &waveBuf[i], 0);
}
} else {
sndReady = false;
sndData = NULL;
}
}
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
// window
case WM_ACTIVATE :
Input::reset();
break;
case WM_SIZE:
Core::width = LOWORD(lParam);
Core::height = HIWORD(lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
// keyboard
case WM_KEYDOWN :
case WM_KEYUP :
@@ -134,19 +206,13 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
case WM_MOUSEMOVE :
Input::setPos(ikMouseL, vec2((float)(short)LOWORD(lParam), (float)(short)HIWORD(lParam)));
break;
// gamepad
// joystick
case WM_DEVICECHANGE :
joyInit();
return 1;
// touch
// ...
case WM_SIZE :
Core::width = LOWORD(lParam);
Core::height = HIWORD(lParam);
break;
case WM_DESTROY :
PostQuitMessage(0);
break;
// TODO
// sound
default :
return DefWindowProc(hWnd, msg, wParam, lParam);
}
@@ -187,11 +253,12 @@ int main() {
HWND hWnd = CreateWindow("static", "OpenLara", WS_OVERLAPPEDWINDOW, 0, 0, r.right - r.left, r.bottom - r.top, 0, 0, 0, 0);
joyInit();
HDC hDC = GetDC(hWnd);
HDC hDC = GetDC(hWnd);
HGLRC hRC = initGL(hDC);
Game::init();
joyInit();
soundInit(hWnd);
Game::init();
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)&WndProc);
ShowWindow(hWnd, SW_SHOWDEFAULT);
@@ -211,11 +278,13 @@ int main() {
continue;
float delta = (time - lastTime) * 0.001f;
EnterCriticalSection(&sndCS);
while (delta > EPS) {
Core::deltaTime = min(delta, 1.0f / 30.0f);
Game::update();
delta -= Core::deltaTime;
}
LeaveCriticalSection(&sndCS);
lastTime = time;
Core::stats.dips = 0;
@@ -232,7 +301,9 @@ int main() {
}
} while (msg.message != WM_QUIT);
soundFree();
Game::free();
freeGL(hRC);
ReleaseDC(hWnd, hDC);