Mono & pan

This commit is contained in:
John Alanbrook 2022-07-12 04:21:57 +00:00
parent a892cb1180
commit afc38d91c3
9 changed files with 161 additions and 13 deletions

View file

@ -91,7 +91,7 @@ void ds_openvideo(struct datastream *ds, const char *video, const char *adriver)
fir->in = astream_filter;
*/
first_free_bus(astream_filter);
//first_free_bus(astream_filter);
plm_set_video_decode_callback(ds->plm, render_frame, ds);
plm_set_audio_decode_callback(ds->plm, render_audio, ds);

View file

@ -526,3 +526,107 @@ void dsp_reverb_fillbuf(struct dsp_reverb *r, short *out, int n)
{
}
struct dsp_filter dsp_make_compressor()
{
struct dsp_filter filter;
struct dsp_compressor new;
new.ratio = 4000;
new.atk = 50;
new.rls = 250;
new.target = 0.f;
new.threshold = -3.f;
new.atk_tau = tau2pole(new.atk / 3000.f);
new.rls_tau = tau2pole(new.rls / 3000.f);
struct dsp_compressor *c = malloc(sizeof(*c));
*c = new;
filter.data = c;
filter.filter = dsp_compressor_fillbuf;
return filter;
}
void dsp_compressor_fillbuf(struct dsp_compressor *comp, short *out, int n)
{
float val;
float db;
db = comp->target * (val - comp->threshold) / comp->ratio;
for (int i = 0; i < n; i++) {
val = short2db(out[i*CHANNELS]);
if (val < comp->threshold) {
comp->target = comp->rls_tau * comp->target;
val += db;
} else {
comp->target = (1 - comp->atk_tau) + comp->atk_tau * comp->target; // TODO: Bake in the 1 - atk_tau
val -= db;
}
// Apply same compression to both channels
out[i*CHANNELS] = out[i*CHANNELS+1] = db2short(val) * ( out[i*CHANNELS] > 0 ? 1 : -1);
}
}
void dsp_pan(float *deg, short *out, int n)
{
if (*deg < -100) *deg = -100.f;
else if (*deg > 100) *deg = 100.f;
if (*deg == 0.f) return;
float db1, db2;
float pct = *deg / 100.f;
if (*deg > 0) {
db1 = pct2db(1 - pct);
db2 = pct2db(pct);
} else {
db1 = pct2db(1 + pct);
db2 = pct2db(-1*pct);
}
for (int i = 0; i < n; i++) {
double pct = *deg / 100.f;
short L = out[i*CHANNELS];
short R = out[i*CHANNELS +1];
if (*deg > 0) {
out[i*CHANNELS] = short_gain(L, db1);
out[i*CHANNELS+1] = (R + short_gain(L, db2)) / 2;
continue;
}
out[i*CHANNELS+1] = short_gain(R, db1);
out[i*CHANNELS] = short_gain(L, db1) + short_gain(R, db2);
}
}
void dsp_mono(void *p, short *out, int n)
{
for (int i = 0; i < n; i++) {
short val = (out[i*CHANNELS] + out[i*CHANNELS+1]) / 2;
for (int j = 0; j < CHANNELS; j++)
out[i*CHANNELS+j] = val;
}
}

View file

@ -77,7 +77,13 @@ struct dsp_ammod {
};
struct dsp_compressor {
double ratio;
double threshold;
float target;
unsigned int atk; /* Milliseconds */
double atk_tau;
unsigned int rls; /* MIlliseconds */
double rls_tau;
};
struct dsp_filter dsp_make_compressor();
@ -137,4 +143,8 @@ struct dsp_reverb {
struct dsp_filter make_reverb();
void dsp_reverb_fillbuf(struct dsp_reverb *r, short *out, int n);
void dsp_pan(float *deg, short *out, int n);
void dsp_mono(void *p, short *out, int n);
#endif

View file

@ -19,14 +19,10 @@ struct bus *first_free_bus(struct dsp_filter in) {
}
void bus_fill_buffers(short *master, int n) {
//clock_t sa = clock();
for (int i = 0; i < 256; i++) {
if (bus[i].on != 1) continue;
dsp_run(bus[i].in, bus[i].buf, BUF_FRAMES);
}
//printf("DSP run took %f.\n", (double)(clock() - sa)/CLOCKS_PER_SEC);
//sa = clock();
memset(master, 0, BUF_FRAMES*CHANNELS*sizeof(short));
@ -36,6 +32,4 @@ void bus_fill_buffers(short *master, int n) {
master[i] += bus[j].buf[i];
}
}
//printf("Mix took %f.\n", (double)(clock() - sa)/CLOCKS_PER_SEC);
}

View file

@ -12,6 +12,12 @@ struct bus {
short buf[BUF_FRAMES*CHANNELS];
};
struct listener {
float x;
float y;
float z;
};
extern short mastermix[BUF_FRAMES*CHANNELS];
struct bus *first_free_bus(struct dsp_filter in);

View file

@ -11,6 +11,8 @@
struct dsp_filter cursong;
struct dsp_midi_song gsong;
float music_pan = 0.f;
void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n)
{
short *o = (short*)out;
@ -54,12 +56,14 @@ void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n)
}
song->midi = midi;
dsp_pan(&music_pan, out, n);
}
void play_song(const char *midi, const char *sf)
{
gsong.midi = tml_load_filename("sounds/littlewonder.mid");
gsong.sf = tsf_load_filename("sounds/ff7.sf2");
gsong.midi = tml_load_filename("sounds/one-winged-angel.mid");
gsong.sf = tsf_load_filename("sounds/mario.sf2");
gsong.time = 0.f;
tsf_set_output(gsong.sf, TSF_STEREO_INTERLEAVED, SAMPLERATE, 0.f);

View file

@ -11,6 +11,8 @@ struct dsp_midi_song {
tml_message *midi;
};
extern float music_pan;
void play_song(const char *midi, const char *sf);
void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n);

View file

@ -91,7 +91,7 @@ static PaStream *stream_def;
void normalize_gain(struct wav *w, double lv)
{
short tarmax = pow(10, lv/20.f) * SHRT_MAX;
short tarmax = db2short(lv);
short max = 0;
short *s = w->data;
for (int i = 0; i < w->frames; i++) {
@ -227,7 +227,7 @@ void sound_init()
//play_song("", "");
play_song("", "");
}
void audio_open(const char *device)
@ -381,3 +381,24 @@ void soundstream_fillbuf(struct soundstream *s, short *buf, int n)
}
}
float short2db(short val)
{
return 20*log10(abs((double)val) / SHRT_MAX);
}
short db2short(float db)
{
return pow(10, db/20.f) * SHRT_MAX;
}
short short_gain(short val, float db)
{
return (short)(pow(10, db/20.f) * val);
}
float pct2db(float pct)
{
if (pct <= 0) return -72.f;
return 10*log2(pct);
}

View file

@ -67,6 +67,13 @@ void soundstream_fillbuf(struct soundstream *stream, short *buf, int n);
void close_audio_device(int device);
int open_device(const char *adriver);
float short2db(short val);
short db2short(float db);
float pct2db(float pct);
short short_gain(short val, float db);
void audio_init();
#endif