#ifdef WITHSOUND
#include "snd.h"
ALCdevice *adev;
ALCcontext *actx;
void sndInit() {
if (adev) return;
adev = alcOpenDevice(NULL);
if (!adev) LOGWRN("sndInit: cannot open device");
actx = alcCreateContext(adev, NULL);
if (!actx) LOGWRN("sndInit: cannot create context");
alcMakeContextCurrent(actx);
}
void sndDeinit() {
alcMakeContextCurrent(NULL);
if (actx) alcDestroyContext(actx);
if (adev) alcCloseDevice(adev);
actx = NULL;
adev = NULL;
}
void sndFree(Sound *snd) {
if (!snd) return;
if (snd->src) alDeleteSources(1, &snd->src);
if (snd->buf) alDeleteBuffers(1, &snd->buf);
*snd = (Sound){};
}
Sound sndGen(int rate, int freq, int samples) {
Sound snd = {};
if (rate <= 0 || freq <= 0 || samples <= 0)
return snd;
short *buf = malloc(samples*sizeof(*buf));
if (!buf)
return LOGERR("sndGen: cannot alocate memory for samples (%d)", samples), (Sound){};
for(int i = 0; i < samples; ++i)
buf[i] = (int)(32760*sin(2*3.14159*i*freq/rate));
alGenBuffers(1, &snd.buf);
alBufferData(snd.buf, AL_FORMAT_MONO16, buf, sizeof(*buf)*samples, rate);
free(buf);
alGenSources(1, &snd.src);
alSourcei(snd.src, AL_BUFFER, snd.buf);
return snd;
}
Sound sndLoadRaw(const char *filename, int rate) {
LOGDBG("sndLoadRaw: open: %s", filename);
FILE *f = fopen(filename, "rb");
if (!f)
return LOGERR("sndLoadRaw: cannot open file for read: %s", filename), (Sound){};
fseek(f, 0, SEEK_END);
int samples = ftell(f)/sizeof(short);
fseek(f, 0, SEEK_SET);
if (samples <= 0)
return LOGERR("sndLoadRaw: file is empty: %s", filename), (Sound){};
unsigned short *buf = (unsigned short*)malloc(sizeof(*buf)*samples);
if (!buf)
return LOGERR("sndGen: cannot alocate memory for samples (%d): %s", samples, filename), fclose(f), (Sound){};
for(int i = 0; i < samples; ++i) {
unsigned int a = fgetc(f), b = fgetc(f);
buf[i] = a | (b << 8);
}
fclose(f);
Sound snd = {};
alGenBuffers(1, &snd.buf);
alBufferData(snd.buf, AL_FORMAT_MONO16, buf, sizeof(*buf)*samples, rate);
free(buf);
alGenSources(1, &snd.src);
alSourcei(snd.src, AL_BUFFER, snd.buf);
return snd;
}
void sndPlay(Sound snd) {
LOGDBG("sndPlay: %d", snd.src);
alSourcePlay(snd.src);
}
#endif