parent
85c4412584
commit
9fa4c4d7a4
|
|
@ -18,93 +18,93 @@ static float o_off = 0.0;
|
|||
#define HDRSIZE 256
|
||||
|
||||
static void* my_open_aliki(char* fn, int nchannel) {
|
||||
char p[HDRSIZE];
|
||||
FILE* aldfile;
|
||||
if ((aldfile = fopen(fn, "w")) == 0) {
|
||||
fprintf(stderr, "Error: Not able to open output file '%s'\n", fn);
|
||||
controlled_exit(1);
|
||||
}
|
||||
char p[HDRSIZE];
|
||||
FILE* aldfile;
|
||||
if ((aldfile = fopen(fn, "w")) == 0) {
|
||||
fprintf(stderr, "Error: Not able to open output file '%s'\n", fn);
|
||||
controlled_exit(1);
|
||||
}
|
||||
|
||||
strcpy(p, "aliki");
|
||||
p[6] = p[7] = 0;
|
||||
*(uint32_t*)(p + 8) = 2; //_vers
|
||||
*(uint32_t*)(p + 12) = nchannel; // _type;
|
||||
*(uint32_t*)(p + 16) = o_samplerate; //_rate_n;
|
||||
*(uint32_t*)(p + 20) = 1; //_rate_d;
|
||||
*(uint32_t*)(p + 24) = 486239; //_n_fram;
|
||||
*(uint32_t*)(p + 28) = 1; // _n_sect;
|
||||
*(uint32_t*)(p + 32) = 0; // _tref_i;
|
||||
*(uint32_t*)(p + 36) = 0; // _tref_n;
|
||||
*(uint32_t*)(p + 40) = 1; // _tref_d;
|
||||
*(uint32_t*)(p + 44) = 0; // _bits;
|
||||
strcpy(p, "aliki");
|
||||
p[6] = p[7] = 0;
|
||||
*(uint32_t*)(p + 8) = 2; //_vers
|
||||
*(uint32_t*)(p + 12) = nchannel; // _type;
|
||||
*(uint32_t*)(p + 16) = o_samplerate; //_rate_n;
|
||||
*(uint32_t*)(p + 20) = 1; //_rate_d;
|
||||
*(uint32_t*)(p + 24) = 486239; //_n_fram;
|
||||
*(uint32_t*)(p + 28) = 1; // _n_sect;
|
||||
*(uint32_t*)(p + 32) = 0; // _tref_i;
|
||||
*(uint32_t*)(p + 36) = 0; // _tref_n;
|
||||
*(uint32_t*)(p + 40) = 1; // _tref_d;
|
||||
*(uint32_t*)(p + 44) = 0; // _bits;
|
||||
|
||||
memset(p + 48, 0, HDRSIZE - 48);
|
||||
if (fwrite(p, 1, HDRSIZE, aldfile) != HDRSIZE) {
|
||||
fprintf(stderr, "Error: Not able to write aliki header to '%s'\n", fn);
|
||||
fclose(aldfile);
|
||||
controlled_exit(1);
|
||||
}
|
||||
return ((void*)aldfile);
|
||||
memset(p + 48, 0, HDRSIZE - 48);
|
||||
if (fwrite(p, 1, HDRSIZE, aldfile) != HDRSIZE) {
|
||||
fprintf(stderr, "Error: Not able to write aliki header to '%s'\n", fn);
|
||||
fclose(aldfile);
|
||||
controlled_exit(1);
|
||||
}
|
||||
return ((void*)aldfile);
|
||||
}
|
||||
|
||||
static size_t my_write_aliki(void* d, float val) {
|
||||
return(fwrite(&val, sizeof(float), 1, (FILE*)d));
|
||||
return(fwrite(&val, sizeof(float), 1, (FILE*)d));
|
||||
}
|
||||
|
||||
static void my_close_aliki(void* d) {
|
||||
fclose((FILE*)d);
|
||||
fclose((FILE*)d);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////// sndfile //////////////////////////////////
|
||||
|
||||
typedef struct {
|
||||
SNDFILE* outfile;
|
||||
int sf_channels;
|
||||
int sf_bptr;
|
||||
float* sf_buf;
|
||||
SNDFILE* outfile;
|
||||
int sf_channels;
|
||||
int sf_bptr;
|
||||
float* sf_buf;
|
||||
} SSFILE;
|
||||
|
||||
static void* my_open_sf(char* fn, int nchannel) {
|
||||
SSFILE* d = calloc(1, sizeof(SSFILE));
|
||||
SF_INFO sfinfo;
|
||||
SSFILE* d = calloc(1, sizeof(SSFILE));
|
||||
SF_INFO sfinfo;
|
||||
|
||||
sfinfo.samplerate = o_samplerate;
|
||||
sfinfo.channels = nchannel;
|
||||
sfinfo.frames = 0;
|
||||
sfinfo.format = o_sndfmt;
|
||||
sfinfo.samplerate = o_samplerate;
|
||||
sfinfo.channels = nchannel;
|
||||
sfinfo.frames = 0;
|
||||
sfinfo.format = o_sndfmt;
|
||||
|
||||
d->sf_channels = nchannel;
|
||||
d->sf_bptr = 0;
|
||||
d->sf_buf = calloc(nchannel, sizeof(float));
|
||||
d->sf_channels = nchannel;
|
||||
d->sf_bptr = 0;
|
||||
d->sf_buf = calloc(nchannel, sizeof(float));
|
||||
|
||||
if ((d->outfile = sf_open(fn, SFM_WRITE, &sfinfo)) == NULL) {
|
||||
fprintf(stderr, "Error: Not able to open output file '%s'\n", fn);
|
||||
controlled_exit(1);
|
||||
}
|
||||
if ((d->outfile = sf_open(fn, SFM_WRITE, &sfinfo)) == NULL) {
|
||||
fprintf(stderr, "Error: Not able to open output file '%s'\n", fn);
|
||||
controlled_exit(1);
|
||||
}
|
||||
|
||||
#if 1
|
||||
sf_command(d->outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE);
|
||||
sf_command(d->outfile, SFC_SET_CLIPPING, NULL, SF_TRUE);
|
||||
sf_command(d->outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE);
|
||||
sf_command(d->outfile, SFC_SET_CLIPPING, NULL, SF_TRUE);
|
||||
#endif
|
||||
|
||||
return ((void*)d);
|
||||
return ((void*)d);
|
||||
}
|
||||
|
||||
static int my_write_sf(void* d, float val) {
|
||||
SSFILE* p = (SSFILE*)d;
|
||||
p->sf_buf[p->sf_bptr++] = val;
|
||||
if (p->sf_bptr >= p->sf_channels) {
|
||||
sf_writef_float(p->outfile, p->sf_buf, 1);
|
||||
p->sf_bptr = 0;
|
||||
}
|
||||
return (1);
|
||||
SSFILE* p = (SSFILE*)d;
|
||||
p->sf_buf[p->sf_bptr++] = val;
|
||||
if (p->sf_bptr >= p->sf_channels) {
|
||||
sf_writef_float(p->outfile, p->sf_buf, 1);
|
||||
p->sf_bptr = 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void my_close_sf(void* d) {
|
||||
sf_close(((SSFILE*)d)->outfile);
|
||||
free(((SSFILE*)d)->sf_buf);
|
||||
free((SSFILE*)d);
|
||||
sf_close(((SSFILE*)d)->outfile);
|
||||
free(((SSFILE*)d)->sf_buf);
|
||||
free((SSFILE*)d);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -114,8 +114,8 @@ static void my_close_sf(void* d) {
|
|||
////////////////////////////////// spice //////////////////////////////////
|
||||
|
||||
typedef struct SP_BUF {
|
||||
double tme;
|
||||
double* val;
|
||||
double tme;
|
||||
double* val;
|
||||
} SP_BUF;
|
||||
|
||||
static void (*p_close)(void*);
|
||||
|
|
@ -144,174 +144,174 @@ static float* resampled;
|
|||
static int iptr = 0;
|
||||
|
||||
static int resample_wrapper(void* d, float val) {
|
||||
interleaved[iptr++] = val;
|
||||
size_t ibufsize = sp_nchannel * OBUFSIZE * oversampling;
|
||||
size_t obufsize = sp_nchannel * OBUFSIZE;
|
||||
if (iptr == ibufsize) {
|
||||
interleaved[iptr++] = val;
|
||||
size_t ibufsize = sp_nchannel * OBUFSIZE * oversampling;
|
||||
size_t obufsize = sp_nchannel * OBUFSIZE;
|
||||
if (iptr == ibufsize) {
|
||||
|
||||
SRC_DATA src_data;
|
||||
src_data.data_in = interleaved;
|
||||
src_data.data_out = resampled;
|
||||
src_data.input_frames = iptr / sp_nchannel;
|
||||
src_data.output_frames = OBUFSIZE;
|
||||
src_data.end_of_input = 0;
|
||||
src_data.src_ratio = 1.0 / OVERSAMPLING;
|
||||
src_data.input_frames_used = 0;
|
||||
src_data.output_frames_gen = 0;
|
||||
SRC_DATA src_data;
|
||||
src_data.data_in = interleaved;
|
||||
src_data.data_out = resampled;
|
||||
src_data.input_frames = iptr / sp_nchannel;
|
||||
src_data.output_frames = OBUFSIZE;
|
||||
src_data.end_of_input = 0;
|
||||
src_data.src_ratio = 1.0 / OVERSAMPLING;
|
||||
src_data.input_frames_used = 0;
|
||||
src_data.output_frames_gen = 0;
|
||||
|
||||
int procerr = src_process(rabbit, &src_data);
|
||||
if (procerr) {
|
||||
const char* errmsg = src_strerror(procerr);
|
||||
fprintf(stderr, "Error: Process src_process failed with message: %s\n", errmsg);
|
||||
}
|
||||
int procerr = src_process(rabbit, &src_data);
|
||||
if (procerr) {
|
||||
const char* errmsg = src_strerror(procerr);
|
||||
fprintf(stderr, "Error: Process src_process failed with message: %s\n", errmsg);
|
||||
}
|
||||
|
||||
if (src_data.output_frames_gen * sp_nchannel != obufsize) {
|
||||
fprintf(stderr, "resample warning: out %li != %i\n", src_data.output_frames_gen * sp_nchannel, (int)obufsize);
|
||||
}
|
||||
if (src_data.output_frames_gen * sp_nchannel != obufsize) {
|
||||
fprintf(stderr, "resample warning: out %li != %i\n", src_data.output_frames_gen * sp_nchannel, (int)obufsize);
|
||||
}
|
||||
|
||||
if (src_data.input_frames_used * sp_nchannel != iptr) {
|
||||
printf("resample warning: in: %li != %i\n", src_data.input_frames_used * sp_nchannel, iptr);
|
||||
}
|
||||
if (src_data.input_frames_used * sp_nchannel != iptr) {
|
||||
printf("resample warning: in: %li != %i\n", src_data.input_frames_used * sp_nchannel, iptr);
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < src_data.output_frames_gen * sp_nchannel; i++)
|
||||
p_write(d, resampled[i]);
|
||||
int i;
|
||||
for (i = 0; i < src_data.output_frames_gen * sp_nchannel; i++)
|
||||
p_write(d, resampled[i]);
|
||||
|
||||
iptr = 0;
|
||||
return (src_data.output_frames_gen * sp_nchannel);
|
||||
}
|
||||
return (0);
|
||||
iptr = 0;
|
||||
return (src_data.output_frames_gen * sp_nchannel);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void snd_configure(char* fn, int srate, int fmt, double mult, double off, int os) {
|
||||
if (filename) free(filename);
|
||||
filename = strdup(fn);
|
||||
if (filename) free(filename);
|
||||
filename = strdup(fn);
|
||||
|
||||
o_samplerate = srate;
|
||||
o_mult = (float)mult;
|
||||
o_off = (float)off;
|
||||
oversampling = os;
|
||||
if (fmt != 0) {
|
||||
p_close = &my_close_sf;
|
||||
p_open = &my_open_sf;
|
||||
p_write = &my_write_sf;
|
||||
o_sndfmt = (fmt > 0) ? fmt : (SF_FORMAT_WAV | SF_FORMAT_PCM_24);
|
||||
printf("info: opened snd file '%s'\n", filename);
|
||||
}
|
||||
else {
|
||||
p_close = &my_close_aliki;
|
||||
p_open = &my_open_aliki;
|
||||
p_write = &my_write_aliki;
|
||||
printf("info: opened aliki file '%s'\n", filename);
|
||||
}
|
||||
o_samplerate = srate;
|
||||
o_mult = (float)mult;
|
||||
o_off = (float)off;
|
||||
oversampling = os;
|
||||
if (fmt != 0) {
|
||||
p_close = &my_close_sf;
|
||||
p_open = &my_open_sf;
|
||||
p_write = &my_write_sf;
|
||||
o_sndfmt = (fmt > 0) ? fmt : (SF_FORMAT_WAV | SF_FORMAT_PCM_24);
|
||||
printf("info: opened snd file '%s'\n", filename);
|
||||
}
|
||||
else {
|
||||
p_close = &my_close_aliki;
|
||||
p_open = &my_open_aliki;
|
||||
p_write = &my_write_aliki;
|
||||
printf("info: opened aliki file '%s'\n", filename);
|
||||
}
|
||||
}
|
||||
|
||||
int snd_format(char* fmt) {
|
||||
int f = atoi(fmt);
|
||||
if (!strcmp(fmt, "wav")) f = (SF_FORMAT_WAV | SF_FORMAT_PCM_24);
|
||||
if (!strcmp(fmt, "wav16")) f = (SF_FORMAT_WAV | SF_FORMAT_PCM_16);
|
||||
if (!strcmp(fmt, "wav24")) f = (SF_FORMAT_WAV | SF_FORMAT_PCM_24);
|
||||
if (!strcmp(fmt, "wav32")) f = (SF_FORMAT_WAV | SF_FORMAT_PCM_32);
|
||||
if (!strcmp(fmt, "aiff")) f = (SF_FORMAT_AIFF | SF_FORMAT_PCM_16);
|
||||
if (!strcmp(fmt, "aliki")) f = 0;
|
||||
return (f);
|
||||
int f = atoi(fmt);
|
||||
if (!strcmp(fmt, "wav")) f = (SF_FORMAT_WAV | SF_FORMAT_PCM_24);
|
||||
if (!strcmp(fmt, "wav16")) f = (SF_FORMAT_WAV | SF_FORMAT_PCM_16);
|
||||
if (!strcmp(fmt, "wav24")) f = (SF_FORMAT_WAV | SF_FORMAT_PCM_24);
|
||||
if (!strcmp(fmt, "wav32")) f = (SF_FORMAT_WAV | SF_FORMAT_PCM_32);
|
||||
if (!strcmp(fmt, "aiff")) f = (SF_FORMAT_AIFF | SF_FORMAT_PCM_16);
|
||||
if (!strcmp(fmt, "aliki")) f = 0;
|
||||
return (f);
|
||||
}
|
||||
|
||||
void snd_init(int nchannel) {
|
||||
int i;
|
||||
if (!filename) snd_configure("spice.wav", 48000, o_sndfmt, o_mult, o_off, oversampling);
|
||||
outfile = p_open(filename, nchannel);
|
||||
sp_nchannel = nchannel;
|
||||
sp_buf = calloc(nchannel, sizeof(SP_BUF));
|
||||
for (i = 0; i < SP_MAX; i++) {
|
||||
sp_buf[i].tme = 0.0;
|
||||
sp_buf[i].val = calloc(nchannel, sizeof(double));
|
||||
}
|
||||
sample = 0;
|
||||
int i;
|
||||
if (!filename) snd_configure("spice.wav", 48000, o_sndfmt, o_mult, o_off, oversampling);
|
||||
outfile = p_open(filename, nchannel);
|
||||
sp_nchannel = nchannel;
|
||||
sp_buf = calloc(nchannel, sizeof(SP_BUF));
|
||||
for (i = 0; i < SP_MAX; i++) {
|
||||
sp_buf[i].tme = 0.0;
|
||||
sp_buf[i].val = calloc(nchannel, sizeof(double));
|
||||
}
|
||||
sample = 0;
|
||||
#ifdef HAVE_SRC
|
||||
interleaved = calloc(nchannel * OBUFSIZE * oversampling, sizeof(float));
|
||||
resampled = calloc(nchannel * OBUFSIZE, sizeof(float));
|
||||
rabbit = src_new(SRC_SINC_BEST_QUALITY, nchannel, &rabbit_err);
|
||||
src_set_ratio(rabbit, 1.0 / OVERSAMPLING);
|
||||
src_reset(rabbit);
|
||||
interleaved = calloc(nchannel * OBUFSIZE * oversampling, sizeof(float));
|
||||
resampled = calloc(nchannel * OBUFSIZE, sizeof(float));
|
||||
rabbit = src_new(SRC_SINC_BEST_QUALITY, nchannel, &rabbit_err);
|
||||
src_set_ratio(rabbit, 1.0 / OVERSAMPLING);
|
||||
src_reset(rabbit);
|
||||
#endif
|
||||
}
|
||||
|
||||
int snd_send(double tme, int c, double out) {
|
||||
int i;
|
||||
int rv = 0;
|
||||
if (c == 0) for (i = SP_MAX - 1; i > 0; i--) {
|
||||
memcpy(&(sp_buf[i]), &(sp_buf[i - 1]), sizeof(SP_BUF));
|
||||
}
|
||||
sp_buf[0].tme = tme * OVERSAMPLING;
|
||||
sp_buf[0].val[c] = out;
|
||||
int i;
|
||||
int rv = 0;
|
||||
if (c == 0) for (i = SP_MAX - 1; i > 0; i--) {
|
||||
memcpy(&(sp_buf[i]), &(sp_buf[i - 1]), sizeof(SP_BUF));
|
||||
}
|
||||
sp_buf[0].tme = tme * OVERSAMPLING;
|
||||
sp_buf[0].val[c] = out;
|
||||
#ifdef SND_DEBUG
|
||||
printf("INFO : c:%i tme:%f fsmp:%i val:%f\n", c, tme, sample, out);
|
||||
printf("INFO : c:%i tme:%f fsmp:%i val:%f\n", c, tme, sample, out);
|
||||
#endif
|
||||
|
||||
if (sample == 0) {
|
||||
if (c == (sp_nchannel - 1))
|
||||
sample = (uint32_t)ceil(tme * OVERSAMPLING);
|
||||
return (0);
|
||||
}
|
||||
if (sample == 0) {
|
||||
if (c == (sp_nchannel - 1))
|
||||
sample = (uint32_t)ceil(tme * OVERSAMPLING);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((sample) < ceil(tme * OVERSAMPLING)) {
|
||||
if (!(sp_buf[0].tme > sample)) printf("error 1 %f !> %i\n", sp_buf[0].tme, sample);
|
||||
if ((sp_buf[1].tme > sample)) printf("error 2 %f !< %i\n", sp_buf[1].tme, sample);
|
||||
if ((sample) < ceil(tme * OVERSAMPLING)) {
|
||||
if (!(sp_buf[0].tme > sample)) printf("error 1 %f !> %i\n", sp_buf[0].tme, sample);
|
||||
if ((sp_buf[1].tme > sample)) printf("error 2 %f !< %i\n", sp_buf[1].tme, sample);
|
||||
#if 1 // DEBUG
|
||||
if ((sp_buf[0].tme - sample) > 1.0) printf("error 3 large timestep: dv/dt=%e dt:%f dv:%e\n",
|
||||
(sp_buf[0].val[c] - sp_buf[1].val[c]) / (sp_buf[0].tme - sample),
|
||||
(sp_buf[0].tme - sample), (sp_buf[0].val[c] - sp_buf[1].val[c]));
|
||||
if ((sp_buf[0].tme - sample) > 1.0) printf("error 3 large timestep: dv/dt=%e dt:%f dv:%e\n",
|
||||
(sp_buf[0].val[c] - sp_buf[1].val[c]) / (sp_buf[0].tme - sample),
|
||||
(sp_buf[0].tme - sample), (sp_buf[0].val[c] - sp_buf[1].val[c]));
|
||||
#endif
|
||||
|
||||
// linear
|
||||
double p = (sp_buf[0].tme - sample) / (sp_buf[0].tme - sp_buf[1].tme);
|
||||
double val = sp_buf[0].val[c] - p * (sp_buf[0].val[c] - sp_buf[1].val[c]);
|
||||
// linear
|
||||
double p = (sp_buf[0].tme - sample) / (sp_buf[0].tme - sp_buf[1].tme);
|
||||
double val = sp_buf[0].val[c] - p * (sp_buf[0].val[c] - sp_buf[1].val[c]);
|
||||
#ifdef SND_DEBUG
|
||||
printf("DEBUG: writing c:%i p:%f*[%f - %f] v:%f\n", c, p, sp_buf[0].val[c], sp_buf[1].val[c], val);
|
||||
printf("DEBUG: writing c:%i p:%f*[%f - %f] v:%f\n", c, p, sp_buf[0].val[c], sp_buf[1].val[c], val);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SRC
|
||||
rv = resample_wrapper(outfile, o_off + (float)val * o_mult);
|
||||
rv = resample_wrapper(outfile, o_off + (float)val * o_mult);
|
||||
#else
|
||||
p_write(outfile, o_off + val * o_mult);
|
||||
if (c == (sp_nchannel - 1)) rv = 1;
|
||||
p_write(outfile, o_off + val * o_mult);
|
||||
if (c == (sp_nchannel - 1)) rv = 1;
|
||||
#endif
|
||||
if (c == (sp_nchannel - 1)) sample++;
|
||||
if (c == (sp_nchannel - 1)) sample++;
|
||||
|
||||
}
|
||||
else {
|
||||
}
|
||||
else {
|
||||
#ifdef SND_DEBUG
|
||||
printf(" ^^^^^^^^^ SKIPPED ^^^^^^^^^\n");
|
||||
printf(" ^^^^^^^^^ SKIPPED ^^^^^^^^^\n");
|
||||
#endif
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
void snd_close(void) {
|
||||
#ifdef HAVE_SRC
|
||||
while (!resample_wrapper(outfile, 0.0)); // flush buffer.
|
||||
while (!resample_wrapper(outfile, 0.0)); // flush buffer.
|
||||
#endif
|
||||
p_close(outfile);
|
||||
free(filename); filename = NULL;
|
||||
p_close(outfile);
|
||||
free(filename); filename = NULL;
|
||||
#ifdef HAVE_SRC
|
||||
free(interleaved);
|
||||
free(resampled);
|
||||
free(interleaved);
|
||||
free(resampled);
|
||||
#endif
|
||||
/*
|
||||
int i;
|
||||
for (i=0; i< SP_MAX; i){
|
||||
free (sp_buf[i].val);
|
||||
sp_buf[i].val=NULL;
|
||||
}
|
||||
*/
|
||||
free(sp_buf);
|
||||
/*
|
||||
int i;
|
||||
for (i=0; i< SP_MAX; i){
|
||||
free (sp_buf[i].val);
|
||||
sp_buf[i].val=NULL;
|
||||
}
|
||||
*/
|
||||
free(sp_buf);
|
||||
}
|
||||
|
||||
double snd_get_samplerate(void) {
|
||||
return ((double)o_samplerate);
|
||||
return ((double)o_samplerate);
|
||||
}
|
||||
|
||||
/* vi:set ts=8 sts=2 sw=2: */
|
||||
|
|
|
|||
Loading…
Reference in New Issue