diff options
-rw-r--r-- | deadbeef.h | 16 | ||||
-rw-r--r-- | plugins/dsp_libsrc/src.c | 5 | ||||
-rw-r--r-- | plugins/dsp_soundtouch/plugin.c | 61 | ||||
-rw-r--r-- | plugins/supereq/supereq.c | 2 | ||||
-rw-r--r-- | streamer.c | 20 |
5 files changed, 76 insertions, 28 deletions
@@ -750,6 +750,7 @@ typedef struct DB_output_s { } DB_output_t; // dsp plugin +// see also: examples/dsp_template.c in git #define DDB_INIT_DSP_CONTEXT(var,type,plug) {\ memset(var,0,sizeof(type));\ var->ctx.plugin=plug;\ @@ -775,11 +776,11 @@ typedef struct DB_dsp_s { void (*close) (ddb_dsp_context_t *ctx); // samples are always interleaved floating point - // returned value is number of output frames - // can change channels, samplerate, channelmask - // buffer size should always have reserved space for upsampling/upmixing - // TODO: decide on buffer size - int (*process) (ddb_dsp_context_t *ctx, float *samples, int frames, ddb_waveformat_t *fmt); + // returned value is number of output frames (multichannel samples) + // plugins are allowed to modify channels, samplerate, channelmask in the fmt structure + // buffer size can fit up to maxframes frames + // by default ratio=1, and plugins don't need to touch it unless they have to + int (*process) (ddb_dsp_context_t *ctx, float *samples, int frames, int maxframes, ddb_waveformat_t *fmt, float *ratio); void (*reset) (ddb_dsp_context_t *ctx); @@ -791,11 +792,12 @@ typedef struct DB_dsp_s { // param names are for display-only, and are allowed to contain spaces int (*num_params) (void); const char *(*get_param_name) (int p); - void (*set_param) (ddb_dsp_context_t *ctx, int p, const char *val); void (*get_param) (ddb_dsp_context_t *ctx, int p, char *str, int len); - const char *configdialog; // separate dialog per dsp context + // config dialog implementation uses set/get param, so they must be + // implemented if this is nonzero + const char *configdialog; } DB_dsp_t; // misc plugin diff --git a/plugins/dsp_libsrc/src.c b/plugins/dsp_libsrc/src.c index 09e5897f..9c5e6fdc 100644 --- a/plugins/dsp_libsrc/src.c +++ b/plugins/dsp_libsrc/src.c @@ -87,7 +87,7 @@ ddb_src_set_ratio (ddb_dsp_context_t *_src, float ratio) { } int -ddb_src_process (ddb_dsp_context_t *_src, float *samples, int nframes, ddb_waveformat_t *fmt) { +ddb_src_process (ddb_dsp_context_t *_src, float *samples, int nframes, int maxframes, ddb_waveformat_t *fmt, float *r) { ddb_src_libsamplerate_t *src = (ddb_src_libsamplerate_t*)_src; if (fmt->samplerate == src->samplerate) { @@ -111,6 +111,9 @@ ddb_src_process (ddb_dsp_context_t *_src, float *samples, int nframes, ddb_wavef fmt->samplerate = src->samplerate; int numoutframes = nframes * src->srcdata.src_ratio; + if (numoutframes > maxframes) { + numoutframes = maxframes; + } float outbuf[numoutframes*fmt->channels]; memset (outbuf, 0, sizeof (outbuf)); int buffersize = sizeof (outbuf); diff --git a/plugins/dsp_soundtouch/plugin.c b/plugins/dsp_soundtouch/plugin.c index 9b67a090..6997a629 100644 --- a/plugins/dsp_soundtouch/plugin.c +++ b/plugins/dsp_soundtouch/plugin.c @@ -31,6 +31,7 @@ enum { ST_PARAM_USE_QUICKSEEK, ST_PARAM_SEQUENCE_MS, ST_PARAM_SEEKWINDOW_MS, + ST_PARAM_SET_OUTPUT_SAMPLERATE, ST_PARAM_COUNT }; @@ -48,6 +49,7 @@ typedef struct { int use_quickseek; int sequence_ms; int seekwindow_ms; + int set_output_samplerate; int changed; } ddb_soundtouch_t; @@ -84,10 +86,17 @@ st_reset (ddb_dsp_context_t *_src) { } int -st_process (ddb_dsp_context_t *_src, float *samples, int nframes, ddb_waveformat_t *fmt) { +st_process (ddb_dsp_context_t *_src, float *samples, int nframes, int maxframes, ddb_waveformat_t *fmt, float *ratio) { ddb_soundtouch_t *st = (ddb_soundtouch_t *)_src; if (st->changed) { - st_set_rate_change (st->st, st->rate); + if (st->set_output_samplerate > 0) { + st_set_rate_change (st->st, 0); + st_set_rate (st->st, fmt->samplerate / (float)st->set_output_samplerate); + } + else { + st_set_rate (st->st, 1); + st_set_rate_change (st->st, st->rate); + } st_set_pitch_semi_tones (st->st, st->pitch); st_set_tempo_change (st->st, st->tempo); st_set_setting (st->st, SETTING_USE_AA_FILTER, st->use_aa_filter); @@ -97,17 +106,24 @@ st_process (ddb_dsp_context_t *_src, float *samples, int nframes, ddb_waveformat st_set_setting (st->st, SETTING_SEEKWINDOW_MS, st->seekwindow_ms); st->changed = 0; } + *ratio = (1.f + 0.01f * st->tempo); + + if (st->set_output_samplerate > 0) { + fmt->samplerate = st->set_output_samplerate; + } + else { + *ratio *= (1.f + 0.01f * st->rate); + } st_set_sample_rate (st->st, fmt->samplerate); st_set_channels (st->st, fmt->channels); st_put_samples (st->st, samples, nframes); int nout = 0; - int nmax = nframes * 24; int n = 0; do { - n = st_receive_samples (st->st, samples, nmax); - nmax -= n; + n = st_receive_samples (st->st, samples, maxframes); + maxframes -= n; samples += n * fmt->channels; nout += n; } while (n != 0); @@ -134,6 +150,8 @@ st_get_param_name (int p) { return "Time Stretch Sequence Length (ms)"; case ST_PARAM_SEEKWINDOW_MS: return "Time Stretch Seek Window Length (ms)"; + case ST_PARAM_SET_OUTPUT_SAMPLERATE: + return "Set Output Samplerate"; default: fprintf (stderr, "st_param_name: invalid param index (%d)\n", p); } @@ -175,9 +193,20 @@ st_set_param (ddb_dsp_context_t *ctx, int p, const char *val) { break; case ST_PARAM_SEQUENCE_MS: st->sequence_ms = atoi (val); + st->changed = 1; break; case ST_PARAM_SEEKWINDOW_MS: st->seekwindow_ms = atoi (val); + st->changed = 1; + break; + case ST_PARAM_SET_OUTPUT_SAMPLERATE: + st->set_output_samplerate = atoi (val); + if (st->set_output_samplerate < 8000) { + st->set_output_samplerate = 0; + } + else if (st->set_output_samplerate > 192000) { + st->set_output_samplerate = 192000; + } break; default: fprintf (stderr, "st_param: invalid param index (%d)\n", p); @@ -189,28 +218,31 @@ st_get_param (ddb_dsp_context_t *ctx, int p, char *val, int sz) { ddb_soundtouch_t *st = (ddb_soundtouch_t *)ctx; switch (p) { case ST_PARAM_TEMPO: - snprintf (val, sizeof (val), "%f", st->tempo); + snprintf (val, sz, "%f", st->tempo); break; case ST_PARAM_PITCH: - snprintf (val, sizeof (val), "%f", st->pitch); + snprintf (val, sz, "%f", st->pitch); break; case ST_PARAM_RATE: - snprintf (val, sizeof (val), "%f", st->rate); + snprintf (val, sz, "%f", st->rate); break; case ST_PARAM_USE_AA_FILTER: - snprintf (val, sizeof (val), "%d", st->use_aa_filter); + snprintf (val, sz, "%d", st->use_aa_filter); break; case ST_PARAM_AA_FILTER_LENGTH: - snprintf (val, sizeof (val), "%d", st->aa_filter_length); + snprintf (val, sz, "%d", st->aa_filter_length); break; case ST_PARAM_USE_QUICKSEEK: - snprintf (val, sizeof (val), "%d", st->use_quickseek); + snprintf (val, sz, "%d", st->use_quickseek); break; case ST_PARAM_SEQUENCE_MS: - snprintf (val, sizeof (val), "%d", st->sequence_ms); + snprintf (val, sz, "%d", st->sequence_ms); break; case ST_PARAM_SEEKWINDOW_MS: - snprintf (val, sizeof (val), "%d", st->seekwindow_ms); + snprintf (val, sz, "%d", st->seekwindow_ms); + break; + case ST_PARAM_SET_OUTPUT_SAMPLERATE: + snprintf (val, sz, "%d", st->set_output_samplerate); break; default: fprintf (stderr, "st_get_param: invalid param index (%d)\n", p); @@ -220,7 +252,8 @@ st_get_param (ddb_dsp_context_t *ctx, int p, char *val, int sz) { static const char settings_dlg[] = "property \"Tempo Change (%)\" spinbtn[-200,200,1] 0 0;\n" "property \"Pitch Change (semi-tones)\" spinbtn[-24,24,1] 1 0;\n" - "property \"Rate Change (%)\" spinbtn[-200,200,1] 2 0;\n" + "property \"Playback Rate Change (%)\" spinbtn[-200,200,1] 2 0;\n" + "property \"Absolute Samplerate (overrides Rate Change if nonzero)\" spinbtn[0,192000,1] 8 0;\n" "property \"Use AA Filter\" checkbox 3 0;\n" "property \"AA Filter Length\" spinbtn[16,64,1] 4 32;\n" "property \"Use Quickseek\" checkbox 5 0;\n" diff --git a/plugins/supereq/supereq.c b/plugins/supereq/supereq.c index 7c67abc1..558cbd5d 100644 --- a/plugins/supereq/supereq.c +++ b/plugins/supereq/supereq.c @@ -77,7 +77,7 @@ supereq_plugin_stop (void) { } int -supereq_process (ddb_dsp_context_t *ctx, float *samples, int frames, ddb_waveformat_t *fmt) { +supereq_process (ddb_dsp_context_t *ctx, float *samples, int frames, int maxframes, ddb_waveformat_t *fmt, float *r) { ddb_supereq_ctx_t *supereq = (ddb_supereq_ctx_t *)ctx; if (supereq->enabled != ctx->enabled) { if (ctx->enabled && !supereq->enabled) { @@ -49,6 +49,7 @@ FILE *out; static intptr_t streamer_tid; static ddb_dsp_context_t *dsp_chain; +static float dsp_ratio = 1; static DB_dsp_t *eqplug; static ddb_dsp_context_t *eq; @@ -1074,13 +1075,16 @@ streamer_thread (void *ctx) { } int bytesread = 0; - while (bytesread < sz-100) { + do { int nb = streamer_read_async (readbuffer+bytesread,sz-bytesread); - if (nb == 0) { + struct timeval tm2; + gettimeofday (&tm2, NULL); + int ms = (tm2.tv_sec*1000+tm2.tv_usec/1000) - (tm1.tv_sec*1000+tm1.tv_usec/1000); + if (ms >= alloc_time) { break; } bytesread += nb; - } + } while (bytesread < sz-100); streamer_lock (); if (bytesread > 0) { @@ -1526,12 +1530,18 @@ streamer_read_async (char *bytes, int size) { int nframes = inputsize / inputsamplesize; ddb_dsp_context_t *dsp = dsp_chain; dspfmt.samplerate = fileinfo->fmt.samplerate; + float ratio = 1.f; + int maxframes = sizeof (tempbuf) / dspsamplesize; while (dsp) { if (dsp->enabled) { - nframes = dsp->plugin->process (dsp, (float *)tempbuf, nframes, &dspfmt); + float r = 1; + nframes = dsp->plugin->process (dsp, (float *)tempbuf, nframes, maxframes, &dspfmt, &r); + ratio *= r; } dsp = dsp->next; } + dsp_ratio = ratio; + int n = pcm_convert (&dspfmt, tempbuf, &output->fmt, bytes, nframes * dspsamplesize); bytesread = n; @@ -1622,7 +1632,7 @@ streamer_read (char *bytes, int size) { int sz = min (size, streamer_ringbuf.remaining); if (sz) { ringbuf_read (&streamer_ringbuf, bytes, sz); - playpos += (float)sz/output->fmt.samplerate/((output->fmt.bps>>3)*output->fmt.channels); + playpos += (float)sz/output->fmt.samplerate/((output->fmt.bps>>3)*output->fmt.channels) * dsp_ratio; playing_track->playtime += (float)sz/output->fmt.samplerate/((output->fmt.bps>>3)*output->fmt.channels); if (playlist_track) { playing_track->filetype = playlist_track->filetype; |