Blob Blame History Raw
#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