NP2kai/sound/pcmmix.c
2020-05-16 05:29:23 +09:00

165 lines
2.9 KiB
C
Executable File

/**
* @file pcmmix.c
* @brief Implementation of the pcm sound
*/
#include <compiler.h>
#include <sound/pcmmix.h>
#include "getsnd/getsnd.h"
#include <dosio.h>
BRESULT pcmmix_regist(PMIXDAT *dat, void *datptr, UINT datsize, UINT rate) {
GETSND gs;
UINT8 tmp[256];
UINT size;
UINT r;
SINT16 *buf;
gs = getsnd_create(datptr, datsize);
if (gs == NULL) {
goto pmr_err1;
}
if (getsnd_setmixproc(gs, rate, 1) != SUCCESS) {
goto pmr_err2;
}
size = 0;
do {
r = getsnd_getpcmbyleng(gs, tmp, sizeof(tmp));
size += r;
} while(r);
getsnd_destroy(gs);
if (size == 0) {
goto pmr_err1;
}
buf = (SINT16 *)_MALLOC(size, "PCM DATA");
if (buf == NULL) {
goto pmr_err1;
}
gs = getsnd_create(datptr, datsize);
if (gs == NULL) {
goto pmr_err1;
}
if (getsnd_setmixproc(gs, rate, 1) != SUCCESS) {
goto pmr_err2;
}
r = getsnd_getpcmbyleng(gs, buf, size);
getsnd_destroy(gs);
dat->sample = buf;
dat->samples = r / 2;
return(SUCCESS);
pmr_err2:
getsnd_destroy(gs);
pmr_err1:
return(FAILURE);
}
BRESULT pcmmix_regfile(PMIXDAT *dat, const OEMCHAR *fname, UINT rate) {
FILEH fh;
UINT size;
UINT8 *ptr;
BRESULT r;
r = FAILURE;
fh = file_open_rb(fname);
if (fh == FILEH_INVALID) {
goto pmrf_err1;
}
size = (UINT)file_getsize(fh);
if (size == 0) {
goto pmrf_err2;
}
ptr = (UINT8 *)_MALLOC(size, fname);
if (ptr == NULL) {
goto pmrf_err2;
}
file_read(fh, ptr, size);
file_close(fh);
r = pcmmix_regist(dat, ptr, size, rate);
_MFREE(ptr);
return(r);
pmrf_err2:
file_close(fh);
pmrf_err1:
return(FAILURE);
}
void SOUNDCALL pcmmix_getpcm(PCMMIX hdl, SINT32 *pcm, UINT count) {
UINT32 bitmap;
PMIXTRK *t;
const SINT16 *s;
UINT srem;
SINT32 *d;
UINT drem;
UINT r;
UINT j;
UINT flag;
SINT32 vol;
SINT32 samp;
if ((hdl->hdr.playing == 0) || (count == 0)) {
return;
}
t = hdl->trk;
bitmap = 1;
do {
if (hdl->hdr.playing & bitmap) {
s = t->pcm;
srem = t->remain;
d = pcm;
drem = count;
flag = t->flag;
vol = t->volume;
do {
r = MIN(srem, drem);
switch(flag & (PMIXFLAG_L | PMIXFLAG_R)) {
case PMIXFLAG_L:
for (j=0; j<r; j++) {
d[j*2+0] += (s[j] * vol) >> 12;
}
break;
case PMIXFLAG_R:
for (j=0; j<r; j++) {
d[j*2+1] += (s[j] * vol) >> 12;
}
break;
case PMIXFLAG_L | PMIXFLAG_R:
for (j=0; j<r; j++) {
samp = (s[j] * vol) >> 12;
d[j*2+0] += samp;
d[j*2+1] += samp;
}
break;
}
s += r;
d += r*2;
srem -= r;
if (srem == 0) {
if (flag & PMIXFLAG_LOOP) {
s = t->data.sample;
srem = t->data.samples;
}
else {
hdl->hdr.playing &= ~bitmap;
break;
}
}
drem -= r;
} while(drem);
t->pcm = s;
t->remain = srem;
}
t++;
bitmap <<= 1;
} while(bitmap < hdl->hdr.enable);
}