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;
|
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_video_decode_callback(ds->plm, render_frame, ds);
|
||||||
plm_set_audio_decode_callback(ds->plm, render_audio, ds);
|
plm_set_audio_decode_callback(ds->plm, render_audio, ds);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,7 +77,13 @@ struct dsp_ammod {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dsp_compressor {
|
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();
|
struct dsp_filter dsp_make_compressor();
|
||||||
|
@ -137,4 +143,8 @@ struct dsp_reverb {
|
||||||
struct dsp_filter make_reverb();
|
struct dsp_filter make_reverb();
|
||||||
void dsp_reverb_fillbuf(struct dsp_reverb *r, short *out, int n);
|
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
|
#endif
|
|
@ -19,14 +19,10 @@ struct bus *first_free_bus(struct dsp_filter in) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void bus_fill_buffers(short *master, int n) {
|
void bus_fill_buffers(short *master, int n) {
|
||||||
//clock_t sa = clock();
|
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
if (bus[i].on != 1) continue;
|
if (bus[i].on != 1) continue;
|
||||||
dsp_run(bus[i].in, bus[i].buf, BUF_FRAMES);
|
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));
|
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];
|
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];
|
short buf[BUF_FRAMES*CHANNELS];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct listener {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
};
|
||||||
|
|
||||||
extern short mastermix[BUF_FRAMES*CHANNELS];
|
extern short mastermix[BUF_FRAMES*CHANNELS];
|
||||||
|
|
||||||
struct bus *first_free_bus(struct dsp_filter in);
|
struct bus *first_free_bus(struct dsp_filter in);
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
struct dsp_filter cursong;
|
struct dsp_filter cursong;
|
||||||
struct dsp_midi_song gsong;
|
struct dsp_midi_song gsong;
|
||||||
|
|
||||||
|
float music_pan = 0.f;
|
||||||
|
|
||||||
void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n)
|
void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n)
|
||||||
{
|
{
|
||||||
short *o = (short*)out;
|
short *o = (short*)out;
|
||||||
|
@ -54,12 +56,14 @@ void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
song->midi = midi;
|
song->midi = midi;
|
||||||
|
|
||||||
|
dsp_pan(&music_pan, out, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_song(const char *midi, const char *sf)
|
void play_song(const char *midi, const char *sf)
|
||||||
{
|
{
|
||||||
gsong.midi = tml_load_filename("sounds/littlewonder.mid");
|
gsong.midi = tml_load_filename("sounds/one-winged-angel.mid");
|
||||||
gsong.sf = tsf_load_filename("sounds/ff7.sf2");
|
gsong.sf = tsf_load_filename("sounds/mario.sf2");
|
||||||
gsong.time = 0.f;
|
gsong.time = 0.f;
|
||||||
|
|
||||||
tsf_set_output(gsong.sf, TSF_STEREO_INTERLEAVED, SAMPLERATE, 0.f);
|
tsf_set_output(gsong.sf, TSF_STEREO_INTERLEAVED, SAMPLERATE, 0.f);
|
||||||
|
|
|
@ -11,6 +11,8 @@ struct dsp_midi_song {
|
||||||
tml_message *midi;
|
tml_message *midi;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern float music_pan;
|
||||||
|
|
||||||
void play_song(const char *midi, const char *sf);
|
void play_song(const char *midi, const char *sf);
|
||||||
void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n);
|
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)
|
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 max = 0;
|
||||||
short *s = w->data;
|
short *s = w->data;
|
||||||
for (int i = 0; i < w->frames; i++) {
|
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)
|
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);
|
void close_audio_device(int device);
|
||||||
int open_device(const char *adriver);
|
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();
|
void audio_init();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue