diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | premix.c | 21 | ||||
-rw-r--r-- | src.c | 177 | ||||
-rw-r--r-- | src.h | 46 | ||||
-rw-r--r-- | streamer.c | 344 |
5 files changed, 331 insertions, 258 deletions
diff --git a/Makefile.am b/Makefile.am index cab4aa3b..8219b914 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,6 +21,7 @@ deadbeef_SOURCES =\ plugins.c plugins.h moduleconf.h\ playlist.c playlist.h \ streamer.c streamer.h\ + src.c src.h\ premix.c premix.h\ messagepump.c messagepump.h\ conf.c conf.h\ @@ -22,6 +22,7 @@ #include <stdlib.h> #include "deadbeef.h" #include "premix.h" +#include "optmath.h" #define trace(...) { fprintf(stderr, __VA_ARGS__); } //#define trace(fmt,...) @@ -201,6 +202,23 @@ pcm_write_samples_24_to_24 (const ddb_waveformat_t * restrict inputfmt, const ch output += outputsamplesize; } } +static inline void +pcm_write_samples_float_to_16 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) { + fpu_control ctl; + fpu_setround (&ctl); + for (int s = 0; s < nsamples; s++) { + for (int c = 0; c < inputfmt->channels; c++) { + if (channelmap[c] != -1) { + int16_t *out = (int16_t*)(output + (outputfmt->bps >> 3) * channelmap[c]); + float sample = *((float*)input); + *out = (int16_t)ftoi (sample*0x7fff); + } + input += 4; + } + output += outputsamplesize; + } + fpu_restore (ctl); +} int pcm_convert (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int inputsize) { @@ -285,6 +303,9 @@ pcm_convert (const ddb_waveformat_t * restrict inputfmt, const char * restrict i else if (inputfmt->bps == 32 && outputfmt->bps == 32) { pcm_write_samples_32_to_32 (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize); } + else if (inputfmt->is_float && inputfmt->bps == 32 && outputfmt->bps == 16) { + pcm_write_samples_float_to_16 (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize); + } else { trace ("no converter from %d to %d\n", inputfmt->bps, outputfmt->bps); } @@ -0,0 +1,177 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include <samplerate.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "conf.h" +#include "threading.h" +#include "src.h" + +//#define trace(...) { fprintf(stderr, __VA_ARGS__); } +#define trace(fmt,...) + +#define SRC_BUFFER 16000 +#define SRC_MAX_CHANNELS 8 + +typedef struct { + ddb_src_t ddb_src; + + int quality; + SRC_STATE *src; + SRC_DATA srcdata; + int remaining; // number of input samples in SRC buffer + __attribute__((__aligned__(16))) char in_fbuffer[sizeof(float)*SRC_BUFFER*SRC_MAX_CHANNELS]; +// __attribute__((__aligned__(16))) float out_fbuffer[SRC_BUFFER*SRC_MAX_CHANNELS]; + uintptr_t mutex; +} ddb_src_libsamplerate_t; + +ddb_src_t * +ddb_src_init (void) { + ddb_src_libsamplerate_t *src = malloc (sizeof (ddb_src_libsamplerate_t)); + memset (src, 0, sizeof (ddb_src_libsamplerate_t)); + src->mutex = mutex_create (); + src->quality = conf_get_int ("src->quality", 2); + src->src = src_new (src->quality, 2, NULL); + if (!src->src) { + ddb_src_free ((ddb_src_t *)src); + return NULL; + } + return (ddb_src_t *)src; +} + +void +ddb_src_free (ddb_src_t *_src) { + ddb_src_libsamplerate_t *src = (ddb_src_libsamplerate_t*)_src; + if (src->mutex) { + mutex_free (src->mutex); + src->mutex = 0; + } + if (src->src) { + src_delete (src->src); + src->src = NULL; + } + free (src); +} + +void +ddb_src_lock (ddb_src_t *_src) { + ddb_src_libsamplerate_t *src = (ddb_src_libsamplerate_t*)_src; + mutex_lock (src->mutex); +} + +void +ddb_src_unlock (ddb_src_t *_src) { + ddb_src_libsamplerate_t *src = (ddb_src_libsamplerate_t*)_src; + mutex_unlock (src->mutex); +} + +void +ddb_src_reset (ddb_src_t *_src, int full) { + ddb_src_libsamplerate_t *src = (ddb_src_libsamplerate_t*)_src; + src->remaining = 0; + if (full) { + src_reset (src->src); + } +} + +void +ddb_src_confchanged (ddb_src_t *_src) { + ddb_src_libsamplerate_t *src = (ddb_src_libsamplerate_t*)_src; + int q = conf_get_int ("src->quality", 2); + if (q != src->quality && q >= SRC_SINC_BEST_QUALITY && q <= SRC_LINEAR) { + ddb_src_lock (_src); + trace ("changing src->quality from %d to %d\n", src->quality, q); + src->quality = q; + if (src) { + src_delete (src->src); + src->src = NULL; + } + memset (&src->srcdata, 0, sizeof (src->srcdata)); + src->src = src_new (src->quality, 2, NULL); + ddb_src_unlock (_src); + } +} + +int +ddb_src_process (ddb_src_t *_src, const char * restrict input, int nframes, char * restrict output, int buffersize, float ratio, int nchannels) { + ddb_src_libsamplerate_t *src = (ddb_src_libsamplerate_t*)_src; + +extern FILE *out; + int initsize = buffersize; + int samplesize = nchannels * sizeof (float); + + do { + // add more frames to input SRC buffer + int n = nframes; + if (n >= SRC_BUFFER - src->remaining) { + n = SRC_BUFFER - src->remaining; + } + + if (n > 0) { + memcpy (&src->in_fbuffer[src->remaining*samplesize], input, n * samplesize); + + src->remaining += n; + input += n * nchannels; + nframes -= n; + } + if (!src->remaining) { + //trace ("WARNING: SRC input buffer starved\n"); + break; + } + + // call libsamplerate + src->srcdata.data_in = (float *)src->in_fbuffer; + src->srcdata.data_out = (float *)output; + src->srcdata.input_frames = src->remaining; + src->srcdata.output_frames = buffersize/samplesize; + src->srcdata.src_ratio = ratio; + src->srcdata.end_of_input = 0; + ddb_src_lock (_src); + src_set_ratio (src->src, ratio); + trace ("src input: %d, ratio %f, buffersize: %d\n", src->srcdata.input_frames, ratio, buffersize); + int src_err = src_process (src->src, &src->srcdata); + trace ("src output: %d, used: %d\n", src->srcdata.output_frames_gen, src->srcdata.input_frames_used); + + ddb_src_unlock (_src); + if (src_err) { + const char *err = src_strerror (src_err) ; + fprintf (stderr, "src_process error %s\n" + "srcdata.data_in=%p, srcdata.data_out=%p, srcdata.input_frames=%d, srcdata.output_frames=%d, srcdata.src_ratio=%f", err, src->srcdata.data_in, src->srcdata.data_out, (int)src->srcdata.input_frames, (int)src->srcdata.output_frames, ratio); + exit (-1); + } + + buffersize -= src->srcdata.output_frames_gen * samplesize; + output += src->srcdata.output_frames_gen * samplesize; + + // calculate how many unused input samples left + src->remaining -= src->srcdata.input_frames_used; + // copy spare samples for next update + if (src->remaining > 0 && src->srcdata.input_frames_used > 0) { + memmove (src->in_fbuffer, &src->in_fbuffer[src->srcdata.input_frames_used*samplesize], src->remaining * samplesize); + } + if (src->srcdata.output_frames_gen == 0) { + break; + } + } while (nframes > 0); + + trace ("src processed: %d bytes\n", initsize-buffersize); + return initsize - buffersize; +} + @@ -0,0 +1,46 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko <waker@users.sourceforge.net> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef __SRC_H +#define __SRC_H + +typedef struct { +} ddb_src_t; + +ddb_src_t * +ddb_src_init (void); + +void +ddb_src_free (ddb_src_t *src); + +void +ddb_src_lock (ddb_src_t *_src); + +void +ddb_src_unlock (ddb_src_t *src); + +void +ddb_src_reset (ddb_src_t *src, int full); + +void +ddb_src_confchanged (ddb_src_t *src); + +int +ddb_src_process (ddb_src_t *_src, const char * restrict input, int nframes, char * restrict output, int buffersize, float ratio, int nchannels); + +#endif @@ -36,38 +36,28 @@ #include "volume.h" #include "vfs.h" #include "premix.h" +#include "src.h" -#define trace(...) { fprintf(stderr, __VA_ARGS__); } -//#define trace(fmt,...) +//#define trace(...) { fprintf(stderr, __VA_ARGS__); } +#define trace(fmt,...) -#define WRITE_DUMP 1 +//#define WRITE_DUMP 1 #if WRITE_DUMP FILE *out; #endif static intptr_t streamer_tid; -static int src_quality; -static SRC_STATE *src; -static SRC_DATA srcdata; -static int src_remaining; // number of input samples in SRC buffer +static ddb_src_t *src; static int conf_replaygain_mode = 0; static int conf_replaygain_scale = 1; -#define SRC_BUFFER 16000 -static int src_in_remaining = 0; -//static int16_t g_src_in_buffer[SRC_BUFFER*2]; -static __attribute__((__aligned__(16))) float g_src_in_fbuffer[SRC_BUFFER*2]; -static __attribute__((__aligned__(16))) float g_src_out_fbuffer[SRC_BUFFER*2]; - static int streaming_terminate; // buffer up to 3 seconds at 44100Hz stereo #define STREAM_BUFFER_SIZE 0x80000 // slightly more than 3 seconds of 44100 stereo #define STREAM_BUFFER_MASK 0x7ffff -//#define STREAM_BUFFER_SIZE 0x10000 // slightly more than 3 seconds of 44100 stereo -//#define STREAM_BUFFER_MASK 0xffff static int streambuffer_fill; static int streambuffer_pos; @@ -75,7 +65,6 @@ static int bytes_until_next_song = 0; static char streambuffer[STREAM_BUFFER_SIZE]; static uintptr_t mutex; static uintptr_t decodemutex; -static uintptr_t srcmutex; static int nextsong = -1; static int nextsong_pstate = -1; static int badsong = -1; @@ -109,16 +98,6 @@ streamer_unlock (void) { } void -src_lock (void) { - mutex_lock (srcmutex); -} - -void -src_unlock (void) { - mutex_unlock (srcmutex); -} - -void adjust_waveformat (ddb_waveformat_t *fmt) { if (!fmt->is_multichannel) { if (fmt->channels == 1) { @@ -768,7 +747,7 @@ streamer_start_new_song (void) { int initsng = nextsong; int pstate = nextsong_pstate; nextsong = -1; - src_remaining = 0; + ddb_src_reset (src, 0); streamer_unlock (); if (badsong == sng) { trace ("looped to bad file. stopping...\n"); @@ -865,7 +844,7 @@ streamer_thread (void *ctx) { #ifdef __linux__ prctl (PR_SET_NAME, "deadbeef-stream", 0, 0, 0, 0); #endif - src_remaining = 0; + ddb_src_reset (src, 0); while (!streaming_terminate) { struct timeval tm1; @@ -1079,7 +1058,7 @@ streamer_thread (void *ctx) { int channels = output->fmt.channels; int bytes_in_one_second = rate * (output->fmt.bps>>3) * channels; const int blocksize = 4096; - int alloc_time = 1000 / (bytes_in_one_second * 2 / blocksize); + int alloc_time = 1000 / (bytes_in_one_second * output->fmt.channels / blocksize); streamer_lock (); if (streambuffer_fill < (STREAM_BUFFER_SIZE-blocksize)) { @@ -1144,11 +1123,6 @@ streamer_thread (void *ctx) { playing_track = NULL; } mutex_unlock (decodemutex); - - if (src) { - src_delete (src); - src = NULL; - } } int @@ -1158,14 +1132,12 @@ streamer_init (void) { #endif mutex = mutex_create (); decodemutex = mutex_create (); - srcmutex = mutex_create (); - src_quality = conf_get_int ("src_quality", 2); - src = src_new (src_quality, 2, NULL); - conf_replaygain_mode = conf_get_int ("replaygain_mode", 0); - conf_replaygain_scale = conf_get_int ("replaygain_scale", 1); + src = ddb_src_init (); if (!src) { return -1; } + conf_replaygain_mode = conf_get_int ("replaygain_mode", 0); + conf_replaygain_scale = conf_get_int ("replaygain_scale", 1); streamer_tid = thread_start (streamer_thread, NULL); return 0; } @@ -1195,8 +1167,10 @@ streamer_free (void) { decodemutex = 0; mutex_free (mutex); mutex = 0; - mutex_free (srcmutex); - srcmutex = 0; + if (src) { + ddb_src_free (src); + src = NULL; + } } void @@ -1205,15 +1179,14 @@ streamer_reset (int full) { // must be called when current song changes by exter fprintf (stderr, "ERROR: someone called streamer_reset after exit\n"); return; // failsafe, in case someone calls streamer reset after deinit } - src_lock (); + ddb_src_lock (src); if (full) { streamer_lock (); streambuffer_pos = 0; streambuffer_fill = 0; streamer_unlock (); } - src_remaining = 0; - src_reset (src); + ddb_src_reset (src, 1); // reset dsp DB_dsp_t **dsp = deadbeef->plug_get_dsp_list (); //int srate = output->fmt.samplerate; @@ -1222,7 +1195,7 @@ streamer_reset (int full) { // must be called when current song changes by exter dsp[i]->reset (); } } - src_unlock (); + ddb_src_unlock (src); } int replaygain = 1; @@ -1322,194 +1295,6 @@ mono_int16_to_stereo_int16 (int16_t *in, int16_t *out, int nsamples) { } } -#if 0 -static void -int16_to_float32 (int16_t *in, float *out, int nsamples) { - while (nsamples > 0) { - *out++ = (*in++)/(float)0x7fff; - nsamples--; - } -} - -static void -mono_int16_to_stereo_float32 (int16_t *in, float *out, int nsamples) { - while (nsamples > 0) { - float sample = (*in++)/(float)0x7fff; - *out++ = sample; - *out++ = sample; - nsamples--; - } -} - -static void -mono_float32_to_stereo_float32 (float *in, float *out, int nsamples) { - while (nsamples > 0) { - float sample = *in++; - *out++ = sample; - *out++ = sample; - nsamples--; - } -} -#endif - -static void -float32_to_int16 (float *in, int16_t *out, int nsamples) { - fpu_control ctl; - fpu_setround (&ctl); - while (nsamples > 0) { - float sample = *in++; - if (sample > 1) { - sample = 1; - } - else if (sample < -1) { - sample = -1; - } - *out++ = (int16_t)ftoi (sample*0x7fff); - nsamples--; - } - fpu_restore (ctl); -} - -/* - - src algorithm - - initsize = size; - while (size > 0) { - need_frames = SRC_BUFFER - src_remaining - read_samples (need_frames) - src_process (output_frames) - convert_to_int16 (bytes, size) - // handle errors - } - return initsize-size; - -*/ - -#if 0 -static int -streamer_read_data_for_src (int16_t *buffer, int frames) { - int channels = fileinfo->fmt.channels; - if (channels > 2) { - channels = 2; - } - int bytesread = fileinfo->plugin->read_int16 (fileinfo, (uint8_t*)buffer, frames * sizeof (int16_t) * channels); - apply_replay_gain_int16 (streaming_track, (uint8_t*)buffer, bytesread); - if (channels == 1) { - // convert to stereo - int n = frames-1; - while (n >= 0) { - buffer[n*2+0] = buffer[n]; - buffer[n*2+1] = buffer[n]; - n--; - } - } - return bytesread / (sizeof (int16_t) * channels); -} - -static int -streamer_read_data_for_src_float (float *buffer, int frames) { - int channels = fileinfo->fmt.channels; - if (channels > 2) { - channels = 2; - } - if (fileinfo->plugin->read_float32) { - int bytesread = fileinfo->plugin->read_float32 (fileinfo, (uint8_t*)buffer, frames * sizeof (float) * channels); - apply_replay_gain_float32 (streaming_track, (uint8_t*)buffer, bytesread); - if (channels == 1) { - // convert to stereo - int n = frames-1; - while (n >= 0) { - buffer[n*2+1] = buffer[n]; - buffer[n*2+0] = buffer[n]; - n--; - } - } - return bytesread / (sizeof (float) * channels); - } - -// trace ("read_float32 not impl\n"); - int16_t intbuffer[frames*2]; - int res = streamer_read_data_for_src (intbuffer, frames); - for (int i = 0; i < res; i++) { - buffer[i*2+0] = intbuffer[i*2+0]/(float)0x7fff; - buffer[i*2+1] = intbuffer[i*2+1]/(float)0x7fff; - } - return res; -} - -static int -streamer_decode_src_libsamplerate (uint8_t *bytes, int size) { - DB_output_t *output = plug_get_output (); - int initsize = size; - int16_t *out = (int16_t *)bytes; - int samplerate = fileinfo->fmt.samplerate; - if (!samplerate) { - return 0; - } - float ratio = output->fmt.samplerate/(float)samplerate; - while (size > 0) { - int n_output_frames = size / sizeof (int16_t) / 2; - int n_input_frames = n_output_frames * samplerate / output->fmt.samplerate + 100; - // read data from decoder - if (n_input_frames >= SRC_BUFFER - src_remaining ) { - n_input_frames = SRC_BUFFER - src_remaining; - } - - int nread; - if (!n_input_frames) { - nread = 0; - } - else { - nread = streamer_read_data_for_src_float (&g_src_in_fbuffer[src_remaining*2], n_input_frames); - } - src_remaining += nread; - if (!src_remaining) { - trace ("SRC input buffer empty\n"); - break; - } - // resample - - srcdata.data_in = g_src_in_fbuffer; - srcdata.data_out = g_src_out_fbuffer; - srcdata.input_frames = src_remaining; - srcdata.output_frames = size/4; - srcdata.src_ratio = ratio; -// trace ("SRC from %d to %d\n", samplerate, output->fmt.samplerate); - srcdata.end_of_input = 0;//(nread == n_input_frames) ? 0 : 1; - //if (streamer_buffering) - src_lock (); - src_set_ratio (src, ratio); - int src_err = src_process (src, &srcdata); - src_unlock (); - if (src_err) { - const char *err = src_strerror (src_err) ; - fprintf (stderr, "src_process error %s\n" - "srcdata.data_in=%p, srcdata.data_out=%p, srcdata.input_frames=%d, srcdata.output_frames=%d, srcdata.src_ratio=%f", err, srcdata.data_in, srcdata.data_out, (int)srcdata.input_frames, (int)srcdata.output_frames, (float)srcdata.src_ratio); - exit (-1); - } - // convert back to s16 format - int genbytes = srcdata.output_frames_gen * 4; - int bytesread = min(size, genbytes); - float32_to_int16 ((float*)g_src_out_fbuffer, (int16_t*)bytes, bytesread>>1); - size -= bytesread; - bytes += bytesread; - // calculate how many unused input samples left - src_remaining -= srcdata.input_frames_used; - - // copy spare samples for next update - if (src_remaining > 0) { - memmove (g_src_in_fbuffer, &g_src_in_fbuffer[srcdata.input_frames_used*2], src_remaining * sizeof (float) * 2); - } - -// if (nread != n_input_frames) { -// trace ("nread=%d, n_input_frames=%d, mismatch!\n", nread, n_input_frames); -// break; -// } - } - return initsize-size; -} -#endif // decodes data and converts to current output format // returns number of bytes been read @@ -1525,22 +1310,76 @@ streamer_read_async (char *bytes, int size) { mutex_unlock (decodemutex); break; } + if (fileinfo->fmt.samplerate != -1) { - if (!memcmp (&fileinfo->fmt, &output->fmt, sizeof (ddb_waveformat_t)), 0) { + DB_dsp_t **dsp = deadbeef->plug_get_dsp_list (); + if (!memcmp (&fileinfo->fmt, &output->fmt, sizeof (ddb_waveformat_t))) { bytesread = fileinfo->plugin->read (fileinfo, bytes, size); } else { -// trace ("format mismatch, converting:\n"); -// trace ("input bps=%d, channels=%d, samplerate=%d, channelmask=%X\n", fileinfo->fmt.bps, fileinfo->fmt.channels, fileinfo->fmt.samplerate, fileinfo->fmt.channelmask); -// trace ("output bps=%d, channels=%d, samplerate=%d, channelmask=%X\n", output->fmt.bps, output->fmt.channels, output->fmt.samplerate, output->fmt.channelmask); - - int outputsamplesize = (output->fmt.bps>>3)*output->fmt.channels; - int inputsamplesize = (fileinfo->fmt.bps>>3)*fileinfo->fmt.channels; - int inputsize = size/outputsamplesize*inputsamplesize; - char input[inputsize]; - inputsize = fileinfo->plugin->read (fileinfo, input, inputsize); - bytesread = pcm_convert (&fileinfo->fmt, input, &output->fmt, bytes, inputsize); -// trace ("decoded %d bytes, writing %d bytes, requested %d bytes\n", inputsize, bytesread, size); + if (output->fmt.samplerate != fileinfo->fmt.samplerate) { + // convert to float, prepare for DSP + int outputsamplesize = (output->fmt.bps>>3)*output->fmt.channels; + int inputsamplesize = (fileinfo->fmt.bps>>3)*fileinfo->fmt.channels; + + float ratio = output->fmt.samplerate/(float)fileinfo->fmt.samplerate; + +#define SRC_NUM_SAMPLES 1024 + char outbuf[SRC_NUM_SAMPLES * output->fmt.channels * sizeof (float)]; + char *src_data = NULL; + int src_data_size = 0; + bytesread = 0; + ddb_waveformat_t srcfmt; + memcpy (&srcfmt, &output->fmt, sizeof (srcfmt)); + srcfmt.bps = 32; + srcfmt.is_float = 1; + int inputsize = (ftoi (SRC_NUM_SAMPLES * ratio) + 100) * inputsamplesize; + char input[inputsize]; + char tempbuf[inputsize/inputsamplesize * sizeof (float) * output->fmt.channels]; + while (1) { + int converted_bytes = 0; + // drain src + int n = sizeof (outbuf); + + int remaining = (size - bytesread) / (output->fmt.bps >> 3) * 4; + if (n > remaining) { + n = remaining; + } + converted_bytes = ddb_src_process (src, src_data, src_data_size/(sizeof(float)*output->fmt.channels), outbuf, n, ratio, srcfmt.channels); + + src_data = NULL; + src_data_size = 0; + if (converted_bytes > 0) { + bytesread += pcm_convert (&srcfmt, outbuf, &output->fmt, bytes + bytesread, converted_bytes); + assert (bytesread <= size); + if (bytesread == size) { + break; + } + continue; + } + + // read more samples for src + inputsize = fileinfo->plugin->read (fileinfo, input, (ftoi (SRC_NUM_SAMPLES * ratio) + 100) * inputsamplesize); + if (!inputsize && !converted_bytes) { + break; // eof + } + + // convert to float + int tempsize = pcm_convert (&fileinfo->fmt, input, &srcfmt, tempbuf, inputsize); + assert (tempsize <= sizeof (tempbuf)); + + src_data = tempbuf; + src_data_size = tempsize; + } + } + else { + int outputsamplesize = (output->fmt.bps>>3)*output->fmt.channels; + int inputsamplesize = (fileinfo->fmt.bps>>3)*fileinfo->fmt.channels; + int inputsize = size/outputsamplesize*inputsamplesize; + char input[inputsize]; + inputsize = fileinfo->plugin->read (fileinfo, input, inputsize); + bytesread = pcm_convert (&fileinfo->fmt, input, &output->fmt, bytes, inputsize); + } } #if WRITE_DUMP if (bytesread) { @@ -1715,19 +1554,8 @@ void streamer_configchanged (void) { conf_replaygain_mode = conf_get_int ("replaygain_mode", 0); conf_replaygain_scale = conf_get_int ("replaygain_scale", 1); - int q = conf_get_int ("src_quality", 2); - if (q != src_quality && q >= SRC_SINC_BEST_QUALITY && q <= SRC_LINEAR) { - src_lock (); - trace ("changing src_quality from %d to %d\n", src_quality, q); - src_quality = q; - if (src) { - src_delete (src); - src = NULL; - } - memset (&srcdata, 0, sizeof (srcdata)); - src = src_new (src_quality, 2, NULL); - src_unlock (); - } + + ddb_src_confchanged (src); } void |