Mono & pan
This commit is contained in:
parent
a892cb1180
commit
afc38d91c3
|
@ -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);
|
||||
|
|
|
@ -525,4 +525,108 @@ struct dsp_filter make_reverb()
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
@ -180,7 +180,7 @@ void sound_init()
|
|||
dspammod.ina = s600;
|
||||
dspammod.inb = s20;
|
||||
|
||||
// first_free_bus(am_filter);
|
||||
//first_free_bus(am_filter);
|
||||
|
||||
struct dsp_filter wn;
|
||||
wn.filter = gen_pinknoise;
|
||||
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue