180 lines
3.6 KiB
C
180 lines
3.6 KiB
C
#include <SDL_audio.h>
|
|
#include <SDL_error.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include "sound.h"
|
|
|
|
#ifndef DATADIR
|
|
#define DATADIR "data"
|
|
#endif
|
|
|
|
int sound_enabled = 1;
|
|
|
|
static char dirlist[] = DATADIR;
|
|
|
|
static int readsound(int num);
|
|
|
|
#define NUMSOUNDS ((int) (sizeof(soundnames) / sizeof(char*)))
|
|
#define MIXMAX 16
|
|
|
|
#define SOUND_QUIET -1
|
|
|
|
static const char* soundnames[] = {
|
|
"bomb1.raw",
|
|
"power1.raw",
|
|
"death.raw",
|
|
"drop.raw",
|
|
"bomb2.raw",
|
|
"power2.raw",
|
|
};
|
|
|
|
typedef struct sample {
|
|
char* data;
|
|
int len;
|
|
} sample;
|
|
|
|
#define SNDFRAGMENT 1024
|
|
|
|
static sample samples[NUMSOUNDS];
|
|
|
|
static int soundworking = 0;
|
|
static int fragment;
|
|
// static int soundwrite,soundread;
|
|
static int* soundbuffer;
|
|
static int soundbufferlen;
|
|
static unsigned char sndclip[8192];
|
|
|
|
#define MAXSOUNDCOMMANDS 32
|
|
static char soundcommands[MAXSOUNDCOMMANDS];
|
|
static int soundtake, soundput;
|
|
|
|
static int sndplaying[MIXMAX], sndposition[MIXMAX];
|
|
static void fillaudio(void* udata, Uint8* buffer, int len) {
|
|
char com, *p;
|
|
int i, j, *ip;
|
|
int which;
|
|
(void) udata;
|
|
|
|
while (soundtake != soundput) {
|
|
com = soundcommands[soundtake];
|
|
soundtake = (soundtake + 1) & (MAXSOUNDCOMMANDS - 1);
|
|
if (com == SOUND_QUIET) {
|
|
memset(sndposition, 0, sizeof(sndposition));
|
|
continue;
|
|
}
|
|
if (com < NUMSOUNDS) {
|
|
for (i = 0; i < MIXMAX; ++i)
|
|
if (!sndposition[i]) {
|
|
sndposition[i] = 1;
|
|
sndplaying[i] = com;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
memset(soundbuffer, 0, soundbufferlen);
|
|
for (i = 0; i < MIXMAX; ++i) {
|
|
if (!sndposition[i]) continue;
|
|
which = sndplaying[i];
|
|
if (sndposition[i] == samples[which].len) {
|
|
sndposition[i] = 0;
|
|
continue;
|
|
}
|
|
p = samples[which].data;
|
|
if (!p) continue;
|
|
p += len * (sndposition[i]++ - 1);
|
|
ip = soundbuffer;
|
|
j = len;
|
|
while (j--) *ip++ += *p++;
|
|
}
|
|
j = len;
|
|
ip = soundbuffer;
|
|
;
|
|
while (j--) *buffer++ = sndclip[4096 + *ip++];
|
|
}
|
|
|
|
|
|
int soundopen(void) {
|
|
SDL_AudioSpec wanted;
|
|
int i, j;
|
|
|
|
soundtake = soundput = 0;
|
|
memset(sndposition, 0, sizeof(sndposition));
|
|
memset(sndplaying, 0, sizeof(sndplaying));
|
|
fragment = SNDFRAGMENT << 1;
|
|
soundbufferlen = fragment * sizeof(int);
|
|
soundbuffer = malloc(soundbufferlen);
|
|
if (!soundbuffer) return -2;
|
|
|
|
memset(&wanted, 0, sizeof(wanted));
|
|
wanted.freq = 22050;
|
|
wanted.channels = 2;
|
|
wanted.format = AUDIO_U8;
|
|
wanted.samples = fragment >> 1;
|
|
wanted.callback = fillaudio;
|
|
wanted.userdata = 0;
|
|
|
|
if (SDL_OpenAudio(&wanted, 0) < 0) {
|
|
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
|
|
return -1;
|
|
}
|
|
soundworking = 1;
|
|
|
|
for (i = 0; i < 8192; i++) {
|
|
j = i - 4096;
|
|
sndclip[i] = j > 127 ? 255 : (j < -128 ? 0 : j + 128);
|
|
}
|
|
|
|
for (i = 0; i < NUMSOUNDS; ++i) readsound(i);
|
|
|
|
SDL_PauseAudio(0);
|
|
return 0;
|
|
}
|
|
void soundclose(void) {
|
|
if (soundworking) {
|
|
SDL_CloseAudio();
|
|
soundworking = 0;
|
|
}
|
|
}
|
|
|
|
|
|
int readsound(int num) {
|
|
char name[256], *p1, *p2, ch;
|
|
int file, size, len;
|
|
p1 = dirlist;
|
|
for (;;) {
|
|
p2 = name;
|
|
while (*p1 && (ch = *p1++) != ',') *p2++ = ch;
|
|
if (p2 > name && p2[-1] != '/') *p2++ = '/';
|
|
strcpy(p2, soundnames[num]);
|
|
file = open(name, O_RDONLY);
|
|
if (file >= 0) break;
|
|
if (!*p1) {
|
|
samples[num].len = -1;
|
|
return 0;
|
|
}
|
|
}
|
|
size = lseek(file, 0, SEEK_END);
|
|
lseek(file, 0, SEEK_SET);
|
|
len = samples[num].len = (size + fragment - 1) / fragment;
|
|
len *= fragment;
|
|
p1 = samples[num].data = malloc(len);
|
|
if (p1) {
|
|
read(file, p1, size);
|
|
if (len - size) memset(p1 + size, 0, len - size);
|
|
while (size--) *p1++ ^= 0x80;
|
|
} else
|
|
samples[num].data = 0;
|
|
close(file);
|
|
return 0;
|
|
}
|
|
|
|
void playsound(int n) {
|
|
if (sound_enabled) {
|
|
soundcommands[soundput] = n;
|
|
soundput = (soundput + 1) & (MAXSOUNDCOMMANDS - 1);
|
|
}
|
|
}
|