diff --git a/CMakeLists.txt b/CMakeLists.txt index 92006cdd9..e114587e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -346,7 +346,7 @@ ENDIF(LMMS_BUILD_WIN32) # check for libsamplerate IF(WANT_SYSTEM_SR) - PKG_CHECK_MODULES(SAMPLERATE samplerate>=0.1.6) + PKG_CHECK_MODULES(SAMPLERATE samplerate>=0.1.7) IF(SAMPLERATE_FOUND) SET(LMMS_HAVE_SAMPLERATE TRUE) ENDIF(SAMPLERATE_FOUND) diff --git a/src/3rdparty/samplerate/common.h b/src/3rdparty/samplerate/common.h index 436e69c4d..ed2198b11 100644 --- a/src/3rdparty/samplerate/common.h +++ b/src/3rdparty/samplerate/common.h @@ -34,6 +34,8 @@ typedef long int32_t ; #endif #define SRC_MAX_RATIO 256 +#define SRC_MAX_RATIO_STR "256" + #define SRC_MIN_RATIO_DIFF (1e-20) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) @@ -44,6 +46,12 @@ typedef long int32_t ; #define MAKE_MAGIC(a,b,c,d,e,f) ((a) + ((b) << 4) + ((c) << 8) + ((d) << 12) + ((e) << 16) + ((f) << 20)) +#ifdef __GNUC__ +# define WARN_UNUSED __attribute__ ((warn_unused_result)) +#else +# define WARN_UNUSED +#endif + #include "samplerate.h" @@ -78,6 +86,7 @@ enum SRC_ERR_BAD_MODE, SRC_ERR_NULL_CALLBACK, SRC_ERR_NO_VARIABLE_RATIO, + SRC_ERR_SINC_PREPARE_DATA_BAD_LEN, /* This must be the last error number. */ SRC_ERR_MAX_ERROR diff --git a/src/3rdparty/samplerate/samplerate.c b/src/3rdparty/samplerate/samplerate.c index 504372fa1..67062e257 100644 --- a/src/3rdparty/samplerate/samplerate.c +++ b/src/3rdparty/samplerate/samplerate.c @@ -226,7 +226,7 @@ src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data) ** returns without setting the ptr. */ float dummy [1] ; - + if (src_data.input_frames == 0) { float *ptr = dummy ; @@ -392,8 +392,10 @@ src_strerror (int error) return "SRC_DATA->data_out is NULL." ; case SRC_ERR_NO_PRIVATE : return "Internal error. No private data." ; + case SRC_ERR_BAD_SRC_RATIO : - return "SRC ratio outside [1/12, 12] range." ; + return "SRC ratio outside [1/" SRC_MAX_RATIO_STR ", " SRC_MAX_RATIO_STR "] range." ; + case SRC_ERR_BAD_SINC_STATE : return "src_process() called without reset after end_of_input." ; case SRC_ERR_BAD_PROC_PTR : @@ -422,6 +424,8 @@ src_strerror (int error) return "Callback function pointer is NULL in src_callback_read ()." ; case SRC_ERR_NO_VARIABLE_RATIO : return "This converter only allows constant conversion ratios." ; + case SRC_ERR_SINC_PREPARE_DATA_BAD_LEN : + return "Internal error : Bad length in prepare_data ()." ; case SRC_ERR_MAX_ERROR : return "Placeholder. No error defined for this error number." ; diff --git a/src/3rdparty/samplerate/src_sinc.c b/src/3rdparty/samplerate/src_sinc.c index 899249e3e..b9b00fed9 100644 --- a/src/3rdparty/samplerate/src_sinc.c +++ b/src/3rdparty/samplerate/src_sinc.c @@ -66,6 +66,9 @@ typedef struct int b_current, b_end, b_real_end, b_len ; + /* Sure hope noone does more than 128 channels at once. */ + double left_calc [128], right_calc [128] ; + /* C99 struct flexible array. */ float buffer [] ; } SINC_FILTER ; @@ -76,7 +79,7 @@ static int sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ; static int sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ; static int sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ; -static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ; +static int prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) WARN_UNUSED ; static void sinc_reset (SRC_PRIVATE *psrc) ; @@ -168,7 +171,9 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum) temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ; temp_filter.channels = psrc->channels ; - if (psrc->channels == 1) + if (psrc->channels > ARRAY_LEN (temp_filter.left_calc)) + return SRC_ERR_BAD_CHANNEL_COUNT ; + else if (psrc->channels == 1) { psrc->const_process = sinc_mono_vari_process ; psrc->vari_process = sinc_mono_vari_process ; } @@ -221,7 +226,7 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum) ** a better way. Need to look at prepare_data () at the same time. */ - temp_filter.b_len = 2 * lrint (1.0 + temp_filter.coeff_half_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ; + temp_filter.b_len = lrint (2.5 * temp_filter.coeff_half_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ; temp_filter.b_len = MAX (temp_filter.b_len, 4096) ; temp_filter.b_len *= temp_filter.channels ; @@ -366,7 +371,8 @@ sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; if (samples_in_hand <= half_filter_chan_len) - { prepare_data (filter, data, half_filter_chan_len) ; + { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0) + return psrc->error ; samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; if (samples_in_hand <= half_filter_chan_len) @@ -514,7 +520,8 @@ sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; if (samples_in_hand <= half_filter_chan_len) - { prepare_data (filter, data, half_filter_chan_len) ; + { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0) + return psrc->error ; samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; if (samples_in_hand <= half_filter_chan_len) @@ -667,7 +674,8 @@ sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; if (samples_in_hand <= half_filter_chan_len) - { prepare_data (filter, data, half_filter_chan_len) ; + { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0) + return psrc->error ; samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; if (samples_in_hand <= half_filter_chan_len) @@ -826,7 +834,8 @@ sinc_hex_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; if (samples_in_hand <= half_filter_chan_len) - { prepare_data (filter, data, half_filter_chan_len) ; + { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0) + return psrc->error ; samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; if (samples_in_hand <= half_filter_chan_len) @@ -876,10 +885,13 @@ static inline void calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int channels, double scale, float * output) { double fraction, icoeff ; /* The following line is 1999 ISO Standard C. If your compiler complains, get a better compiler. */ - double left [channels], right [channels] ; + double *left, *right ; increment_t filter_index, max_filter_index ; int data_index, coeff_count, indx, ch ; + left = filter->left_calc ; + right = filter->right_calc ; + /* Convert input parameters into fixed point. */ max_filter_index = int_to_fp (filter->coeff_half_len) ; @@ -889,7 +901,7 @@ calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start filter_index = filter_index + coeff_count * increment ; data_index = filter->b_current - channels * coeff_count ; - memset (left, 0, sizeof (left)) ; + memset (left, 0, sizeof (left [0]) * channels) ; do { fraction = fp_to_double (filter_index) ; @@ -944,7 +956,7 @@ calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start filter_index = filter_index + coeff_count * increment ; data_index = filter->b_current + channels * (1 + coeff_count) ; - memset (right, 0, sizeof (right)) ; + memset (right, 0, sizeof (right [0]) * channels) ; do { fraction = fp_to_double (filter_index) ; indx = fp_to_int (filter_index) ; @@ -1069,7 +1081,8 @@ sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; if (samples_in_hand <= half_filter_chan_len) - { prepare_data (filter, data, half_filter_chan_len) ; + { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0) + return psrc->error ; samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ; if (samples_in_hand <= half_filter_chan_len) @@ -1118,12 +1131,12 @@ sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) /*---------------------------------------------------------------------------------------- */ -static void +static int prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) { int len = 0 ; if (filter->b_real_end >= 0) - return ; /* This doesn't make sense, so return. */ + return 0 ; /* Should be terminating. Just return. */ if (filter->b_current == 0) { /* Initial state. Set up zeros at the start of the buffer and @@ -1153,6 +1166,9 @@ prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) len = MIN (filter->in_count - filter->in_used, len) ; len -= (len % filter->channels) ; + if (len < 0 || filter->b_end + len > filter->b_len) + return SRC_ERR_SINC_PREPARE_DATA_BAD_LEN ; + memcpy (filter->buffer + filter->b_end, data->data_in + filter->in_used, len * sizeof (filter->buffer [0])) ; @@ -1182,7 +1198,7 @@ prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) filter->b_end += len ; } ; - return ; + return 0 ; } /* prepare_data */