diff --git a/Frameworks/Dumb/dumb/include/dumb.h b/Frameworks/Dumb/dumb/include/dumb.h index a6d00210d..dad2fd049 100644 --- a/Frameworks/Dumb/dumb/include/dumb.h +++ b/Frameworks/Dumb/dumb/include/dumb.h @@ -36,24 +36,24 @@ #endif -#define DUMB_MAJOR_VERSION 0 -#define DUMB_MINOR_VERSION 9 -#define DUMB_REVISION_VERSION 3 +#define DUMB_MAJOR_VERSION 1 +#define DUMB_MINOR_VERSION 0 +#define DUMB_REVISION_VERSION 0 #define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION) -#define DUMB_VERSION_STR "0.9.3" +#define DUMB_VERSION_STR "1.0.0" #define DUMB_NAME "DUMB v" DUMB_VERSION_STR -#define DUMB_YEAR 2005 -#define DUMB_MONTH 8 -#define DUMB_DAY 7 +#define DUMB_YEAR 2015 +#define DUMB_MONTH 1 +#define DUMB_DAY 17 -#define DUMB_YEAR_STR2 "05" -#define DUMB_YEAR_STR4 "2005" -#define DUMB_MONTH_STR1 "8" -#define DUMB_DAY_STR1 "7" +#define DUMB_YEAR_STR2 "15" +#define DUMB_YEAR_STR4 "2015" +#define DUMB_MONTH_STR1 "1" +#define DUMB_DAY_STR1 "17" #if DUMB_MONTH < 10 #define DUMB_MONTH_STR2 "0" DUMB_MONTH_STR1 @@ -228,6 +228,8 @@ DUH *read_duh(DUMBFILE *f); long duh_get_length(DUH *duh); const char *duh_get_tag(DUH *duh, const char *key); +int duh_get_tag_iterator_size(DUH *duh); +int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag, int i); /* Signal Rendering Functions */ @@ -317,15 +319,41 @@ void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer); /* DUH Rendering Functions */ -long duh_render( +/* For packed integers: 8, 16, 24-bit wide. + * Intermediary buffer sig_samples must be freed with destroy_sample_buffer() + * in the end of the rendering loop. + */ +long duh_render_int( DUH_SIGRENDERER *sigrenderer, + sample_t ***sig_samples, + long *sig_samples_size, int bits, int unsign, float volume, float delta, long size, void *sptr ); +/* For floats: 32, 64-bit wide. + * Intermediary buffer sig_samples must be freed with destroy_sample_buffer() + * in the end of the rendering loop. + */ +long duh_render_float( + DUH_SIGRENDERER *sigrenderer, + sample_t ***sig_samples, + long *sig_samples_size, + int bits, + float volume, float delta, + long size, void *sptr +); + #ifdef DUMB_DECLARE_DEPRECATED +long duh_render( + DUH_SIGRENDERER *sigrenderer, + int bits, int unsign, + float volume, float delta, + long size, void *sptr +) DUMB_DEPRECATED; + long duh_render_signal( DUH_SIGRENDERER *sigrenderer, float volume, float delta, @@ -385,9 +413,9 @@ enum DUMB_IT_RAMP_ONOFF_ONLY = 1, DUMB_IT_RAMP_FULL = 2 }; - + void dumb_it_set_ramp_style(DUMB_IT_SIGRENDERER * sigrenderer, int ramp_style); - + void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data, int channel, unsigned char midi_byte), void *data); diff --git a/Frameworks/Dumb/dumb/include/internal/lpc.h b/Frameworks/Dumb/dumb/include/internal/lpc.h index 8c585fa5f..844fb2b3a 100644 --- a/Frameworks/Dumb/dumb/include/internal/lpc.h +++ b/Frameworks/Dumb/dumb/include/internal/lpc.h @@ -18,13 +18,7 @@ #ifndef _V_LPC_H_ #define _V_LPC_H_ -/* simple linear scale LPC code */ -extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m); - -extern void vorbis_lpc_predict(float *coeff,float *prime,int m, - float *data,long n); - struct DUMB_IT_SIGDATA; -extern void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata); +extern int dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata); #endif diff --git a/Frameworks/Dumb/dumb/include/internal/resampler.h b/Frameworks/Dumb/dumb/include/internal/resampler.h index cea5e38d1..d0283a340 100644 --- a/Frameworks/Dumb/dumb/include/internal/resampler.h +++ b/Frameworks/Dumb/dumb/include/internal/resampler.h @@ -1,60 +1,62 @@ -#ifndef _RESAMPLER_H_ -#define _RESAMPLER_H_ - -// Ugglay -#ifdef RESAMPLER_DECORATE +#ifndef _RESAMPLER_H_ +#define _RESAMPLER_H_ + +// Ugglay +#ifdef RESAMPLER_DECORATE #undef PASTE -#undef EVALUATE -#define PASTE(a,b) a ## b -#define EVALUATE(a,b) PASTE(a,b) -#define resampler_init EVALUATE(RESAMPLER_DECORATE,_resampler_init) -#define resampler_create EVALUATE(RESAMPLER_DECORATE,_resampler_create) -#define resampler_delete EVALUATE(RESAMPLER_DECORATE,_resampler_delete) -#define resampler_dup EVALUATE(RESAMPLER_DECORATE,_resampler_dup) -#define resampler_dup_inplace EVALUATE(RESAMPLER_DECORATE,_resampler_dup_inplace) -#define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality) -#define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count) -#define resampler_write_sample EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample) -#define resampler_write_sample_fixed EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_fixed) -#define resampler_set_rate EVALUATE(RESAMPLER_DECORATE,_resampler_set_rate) -#define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready) -#define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear) -#define resampler_get_sample_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_count) -#define resampler_get_sample EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample) -#define resampler_get_sample_float EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_float) -#define resampler_remove_sample EVALUATE(RESAMPLER_DECORATE,_resampler_remove_sample) -#endif - -void resampler_init(void); - -void * resampler_create(void); -void resampler_delete(void *); -void * resampler_dup(const void *); -void resampler_dup_inplace(void *, const void *); - -enum -{ - RESAMPLER_QUALITY_MIN = 0, - RESAMPLER_QUALITY_ZOH = 0, - RESAMPLER_QUALITY_BLEP = 1, - RESAMPLER_QUALITY_LINEAR = 2, - RESAMPLER_QUALITY_BLAM = 3, - RESAMPLER_QUALITY_CUBIC = 4, - RESAMPLER_QUALITY_SINC = 5, - RESAMPLER_QUALITY_MAX = 5 -}; - -void resampler_set_quality(void *, int quality); - -int resampler_get_free_count(void *); -void resampler_write_sample(void *, short sample); -void resampler_write_sample_fixed(void *, int sample, unsigned char depth); -void resampler_set_rate( void *, double new_factor ); -int resampler_ready(void *); -void resampler_clear(void *); -int resampler_get_sample_count(void *); -int resampler_get_sample(void *); -float resampler_get_sample_float(void *); -void resampler_remove_sample(void *, int decay); - -#endif +#undef EVALUATE +#define PASTE(a,b) a ## b +#define EVALUATE(a,b) PASTE(a,b) +#define resampler_init EVALUATE(RESAMPLER_DECORATE,_resampler_init) +#define resampler_create EVALUATE(RESAMPLER_DECORATE,_resampler_create) +#define resampler_delete EVALUATE(RESAMPLER_DECORATE,_resampler_delete) +#define resampler_dup EVALUATE(RESAMPLER_DECORATE,_resampler_dup) +#define resampler_dup_inplace EVALUATE(RESAMPLER_DECORATE,_resampler_dup_inplace) +#define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality) +#define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count) +#define resampler_write_sample EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample) +#define resampler_write_sample_fixed EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_fixed) +#define resampler_write_sample_float EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_float) +#define resampler_set_rate EVALUATE(RESAMPLER_DECORATE,_resampler_set_rate) +#define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready) +#define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear) +#define resampler_get_sample_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_count) +#define resampler_get_sample EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample) +#define resampler_get_sample_float EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_float) +#define resampler_remove_sample EVALUATE(RESAMPLER_DECORATE,_resampler_remove_sample) +#endif + +void resampler_init(void); + +void * resampler_create(void); +void resampler_delete(void *); +void * resampler_dup(const void *); +void resampler_dup_inplace(void *, const void *); + +enum +{ + RESAMPLER_QUALITY_MIN = 0, + RESAMPLER_QUALITY_ZOH = 0, + RESAMPLER_QUALITY_BLEP = 1, + RESAMPLER_QUALITY_LINEAR = 2, + RESAMPLER_QUALITY_BLAM = 3, + RESAMPLER_QUALITY_CUBIC = 4, + RESAMPLER_QUALITY_SINC = 5, + RESAMPLER_QUALITY_MAX = 5 +}; + +void resampler_set_quality(void *, int quality); + +int resampler_get_free_count(void *); +void resampler_write_sample(void *, short sample); +void resampler_write_sample_fixed(void *, int sample, unsigned char depth); +void resampler_write_sample_float(void *, float sample); +void resampler_set_rate( void *, double new_factor ); +int resampler_ready(void *); +void resampler_clear(void *); +int resampler_get_sample_count(void *); +int resampler_get_sample(void *); +float resampler_get_sample_float(void *); +void resampler_remove_sample(void *, int decay); + +#endif diff --git a/Frameworks/Dumb/dumb/include/internal/stack_alloc.h b/Frameworks/Dumb/dumb/include/internal/stack_alloc.h index ed892a279..b82edec05 100644 --- a/Frameworks/Dumb/dumb/include/internal/stack_alloc.h +++ b/Frameworks/Dumb/dumb/include/internal/stack_alloc.h @@ -1,50 +1,47 @@ -/* Copyright (C) 2002-2003 Jean-Marc Valin - Copyright (C) 2007-2009 Xiph.Org Foundation */ +/* Copyright (C) 2002 Jean-Marc Valin */ /** - @file stack_alloc.h - @brief Temporary memory allocation on stack - */ + @file stack_alloc.h + @brief Temporary memory allocation on stack +*/ /* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ #ifndef STACK_ALLOC_H #define STACK_ALLOC_H -#if (!defined (VAR_ARRAYS) && !defined (USE_ALLOCA)) -#error "Dumb requires one of VAR_ARRAYS or USE_ALLOCA be defined to select the temporary allocation mode." -#endif - -#ifdef USE_ALLOCA -# ifdef WIN32 -# include +#ifdef WIN32 +# include +#else +# ifdef HAVE_ALLOCA_H +# include # else -# ifdef HAVE_ALLOCA_H -# include -# else -# include -# endif +# include # endif #endif @@ -85,28 +82,32 @@ * @param type Type of element */ +#ifdef ENABLE_VALGRIND + +#include + +#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) + +#define PUSH(stack, size, type) (VALGRIND_MAKE_NOACCESS(stack, 1000),ALIGN((stack),sizeof(type)),VALGRIND_MAKE_WRITABLE(stack, ((size)*sizeof(type))),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type)))) + +#else + +#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) + +#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type)))) + +#endif + #if defined(VAR_ARRAYS) - -#define VARDECL(type, var) +#define VARDECL(var) #define ALLOC(var, size, type) type var[size] -#define SAVE_STACK -#define RESTORE_STACK -#define ALLOC_STACK - #elif defined(USE_ALLOCA) +#define VARDECL(var) var +#define ALLOC(var, size, type) var = alloca(sizeof(type)*(size)) +#else +#define VARDECL(var) var +#define ALLOC(var, size, type) var = PUSH(stack, size, type) +#endif -#define VARDECL(type, var) type *var -# ifdef WIN32 -# define ALLOC(var, size, type) var = ((type*)_alloca(sizeof(type)*(size))) -# else -# define ALLOC(var, size, type) var = ((type*)alloca(sizeof(type)*(size))) -# endif - -#define SAVE_STACK -#define RESTORE_STACK -#define ALLOC_STACK - -#endif /* VAR_ARRAYS */ - -#endif /* STACK_ALLOC_H */ +#endif diff --git a/Frameworks/Dumb/dumb/src/core/duhtag.c b/Frameworks/Dumb/dumb/src/core/duhtag.c index 77061094e..3dd02c2ca 100644 --- a/Frameworks/Dumb/dumb/src/core/duhtag.c +++ b/Frameworks/Dumb/dumb/src/core/duhtag.c @@ -36,3 +36,23 @@ const char *duh_get_tag(DUH *duh, const char *key) return NULL; } + + + +int duh_get_tag_iterator_size(DUH *duh) +{ + return (duh && duh->tag ? duh->n_tags : 0); +} + + +int duh_get_tag_iterator_get(DUH *duh, const char **key, const char **tag, int i) +{ + ASSERT(key); + ASSERT(tag); + if (!duh || !duh->tag || i >= duh->n_tags) return -1; + + *key = duh->tag[i][0]; + *tag = duh->tag[i][1]; + + return 0; +} diff --git a/Frameworks/Dumb/dumb/src/core/rendduh.c b/Frameworks/Dumb/dumb/src/core/rendduh.c index 1effa3eb4..2077c089a 100644 --- a/Frameworks/Dumb/dumb/src/core/rendduh.c +++ b/Frameworks/Dumb/dumb/src/core/rendduh.c @@ -70,6 +70,21 @@ #endif +#define CONVERT24(src, pos) { \ + signed int f = src; \ + f = MID(-8388608, f, 8388607); \ + ((unsigned char*)sptr)[pos ] = (f) & 0xFF; \ + ((unsigned char*)sptr)[pos+1] = (f >> 8) & 0xFF; \ + ((unsigned char*)sptr)[pos+2] = (f >> 16) & 0xFF; \ +} + +#define CONVERT32F(src, pos) { \ + ((float*)sptr)[pos] = (float)((signed int)src) * (1.0f/(float)(0xffffff/2+1)); \ +} + +#define CONVERT64F(src, pos) { \ + ((double*)sptr)[pos] = (double)((signed int)src) * (1.0/(double)(0xffffff/2+1)); \ +} /* DEPRECATED */ @@ -79,7 +94,7 @@ DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos) } - +/* DEPRECATED */ long duh_render( DUH_SIGRENDERER *sigrenderer, int bits, int unsign, @@ -136,6 +151,138 @@ long duh_render( } +long duh_render_int( + DUH_SIGRENDERER *sigrenderer, + sample_t ***sig_samples, + long *sig_samples_size, + int bits, int unsign, + float volume, float delta, + long size, void *sptr +) +{ + long n; + + sample_t **sampptr; + + int n_channels; + + ASSERT(bits == 8 || bits == 16 || bits == 24); + ASSERT(sptr); + ASSERT(sig_samples); + ASSERT(sig_samples_size); + + if (!sigrenderer) + return 0; + + n_channels = duh_sigrenderer_get_n_channels(sigrenderer); + + ASSERT(n_channels > 0); + /* This restriction will be removed when need be. At the moment, tightly + * optimised loops exist for exactly one or two channels. + */ + ASSERT(n_channels <= 2); + + if ((*sig_samples == NULL) || (*sig_samples_size != size)) + { + destroy_sample_buffer(*sig_samples); + *sig_samples = allocate_sample_buffer(n_channels, size); + *sig_samples_size = size; + } + sampptr = *sig_samples; + + if (!sampptr) + return 0; + + dumb_silence(sampptr[0], n_channels * size); + + size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr); + + if (bits == 24) { + long i = 0; + ASSERT(unsign == 0); + + for (n = 0; n < size * n_channels; n++, i += 3) { + CONVERT24(sampptr[0][n], i); + } + } else + if (bits == 16) { + int signconv = unsign ? 0x8000 : 0x0000; + + for (n = 0; n < size * n_channels; n++) { + CONVERT16(sampptr[0][n], n, signconv); + } + } else { + char signconv = unsign ? 0x80 : 0x00; + + for (n = 0; n < size * n_channels; n++) { + CONVERT8(sampptr[0][n], n, signconv); + } + } + + return size; +} + + +long duh_render_float( + DUH_SIGRENDERER *sigrenderer, + sample_t ***sig_samples, + long *sig_samples_size, + int bits, + float volume, float delta, + long size, void *sptr +) +{ + long n; + + sample_t **sampptr; + + int n_channels; + + ASSERT(bits == 32 || bits == 64); + ASSERT(sptr); + ASSERT(sig_samples); + ASSERT(sig_samples_size); + + if (!sigrenderer) + return 0; + + n_channels = duh_sigrenderer_get_n_channels(sigrenderer); + + ASSERT(n_channels > 0); + /* This restriction will be removed when need be. At the moment, tightly + * optimised loops exist for exactly one or two channels. + */ + ASSERT(n_channels <= 2); + + if ((*sig_samples == NULL) || (*sig_samples_size != size)) + { + destroy_sample_buffer(*sig_samples); + *sig_samples = allocate_sample_buffer(n_channels, size); + *sig_samples_size = size; + } + sampptr = *sig_samples; + + if (!sampptr) + return 0; + + dumb_silence(sampptr[0], n_channels * size); + + size = duh_sigrenderer_generate_samples(sigrenderer, volume, delta, size, sampptr); + + if (bits == 64) { + for (n = 0; n < size * n_channels; n++) { + CONVERT64F(sampptr[0][n], n); + } + } else + if (bits == 32) { + for (n = 0; n < size * n_channels; n++) { + CONVERT32F(sampptr[0][n], n); + } + } + + return size; +} + /* DEPRECATED */ int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr) diff --git a/Frameworks/Dumb/dumb/src/helpers/barray.c b/Frameworks/Dumb/dumb/src/helpers/barray.c index 95fe7af10..23db09887 100644 --- a/Frameworks/Dumb/dumb/src/helpers/barray.c +++ b/Frameworks/Dumb/dumb/src/helpers/barray.c @@ -53,6 +53,21 @@ void bit_array_set(void * array, size_t bit) } } +void bit_array_set_range(void * array, size_t bit, size_t count) +{ + if (array && count) + { + size_t * size = (size_t *) array; + if (bit < *size) + { + unsigned char * ptr = (unsigned char *)(size + 1); + size_t i; + for (i = bit; i < *size && i < bit + count; ++i) + ptr[i >> 3] |= (1U << (i & 7)); + } + } +} + int bit_array_test(void * array, size_t bit) { if (array) @@ -120,6 +135,21 @@ void bit_array_clear(void * array, size_t bit) } } +void bit_array_clear_range(void * array, size_t bit, size_t count) +{ + if (array && count) + { + size_t * size = (size_t *) array; + if (bit < *size) + { + unsigned char * ptr = (unsigned char *)(size + 1); + size_t i; + for (i = bit; i < *size && i < bit + count; ++i) + ptr[i >> 3] &= ~(1U << (i & 7)); + } + } +} + void bit_array_merge(void * dest, void * source, size_t offset) { if (dest && source) diff --git a/Frameworks/Dumb/dumb/src/helpers/lpc.c b/Frameworks/Dumb/dumb/src/helpers/lpc.c index 75d76b3d3..309f976bc 100644 --- a/Frameworks/Dumb/dumb/src/helpers/lpc.c +++ b/Frameworks/Dumb/dumb/src/helpers/lpc.c @@ -55,14 +55,12 @@ Carsten Bormann /* Input : n elements of time doamin data Output: m lpc coefficients, excitation energy */ -float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){ - VARDECL(double, aut); - VARDECL(double, lpc); - ALLOC(aut, m+1, double); - ALLOC(lpc, m, double); +static float vorbis_lpc_from_data(float *data,float *lpci,long n,long m){ + double *aut=alloca(sizeof(*aut)*(m+1)); + double *lpc=alloca(sizeof(*lpc)*(m)); double error; double epsilon; - int i,j; + long i,j; /* autocorrelation, p+1 lag coefficients */ j=m+1; @@ -129,7 +127,7 @@ float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){ return error; } -void vorbis_lpc_predict(float *coeff,float *prime,int m, +static void vorbis_lpc_predict(float *coeff,float *prime,long m, float *data,long n){ /* in: coeff[0...m-1] LPC coefficients @@ -169,7 +167,7 @@ enum { lpc_extra = 64 }; /* How many samples of padding to predict or silence * /* This extra sample padding is really only needed by the FIR resampler, but it helps the other resamplers as well. */ -void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){ +int dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){ float lpc[lpc_order * 2]; float lpc_input[lpc_max * 2]; float lpc_output[lpc_extra * 2]; @@ -177,11 +175,12 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){ signed char * s8; signed short * s16; - int n, o, offset, lpc_samples; + long n, o, offset, lpc_samples; for ( n = 0; n < sigdata->n_samples; n++ ) { IT_SAMPLE * sample = sigdata->sample + n; - if ( ( sample->flags & ( IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP) ) == IT_SAMPLE_EXISTS ) { + if ( ( sample->flags & ( IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP) ) == IT_SAMPLE_EXISTS && + sample->data != NULL ) { /* If we have enough sample data to train the filter, use the filter to generate the padding */ if ( sample->length >= lpc_order ) { lpc_samples = sample->length; @@ -220,6 +219,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){ if ( sample->flags & IT_SAMPLE_16BIT ) { s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 * sizeof(short) ); + if ( !s16 ) + return -1; + sample->data = s16; s16 += sample->length * 2; @@ -234,6 +236,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){ else { s8 = ( signed char * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 ); + if ( !s8 ) + return -1; + sample->data = s8; s8 += sample->length * 2; @@ -274,6 +279,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){ if ( sample->flags & IT_SAMPLE_16BIT ) { s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * sizeof(short) ); + if (!s16) + return -1; + sample->data = s16; s16 += sample->length; @@ -287,6 +295,9 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){ else { s8 = ( signed char * ) realloc( sample->data, sample->length + lpc_extra ); + if ( !s8 ) + return -1; + sample->data = s8; s8 += sample->length; @@ -302,6 +313,7 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){ else /* Otherwise, pad with silence. */ { + void *data; offset = sample->length; lpc_samples = lpc_extra; @@ -314,9 +326,15 @@ void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){ offset *= n; lpc_samples *= n; - sample->data = realloc( sample->data, offset + lpc_samples ); - memset( (char*)sample->data + offset, 0, lpc_samples ); + data = realloc( sample->data, offset + lpc_samples ); + if (!data) + return -1; + sample->data = data; + + memset( (char*)data + offset, 0, lpc_samples ); } } } + + return 0; } diff --git a/Frameworks/Dumb/dumb/src/helpers/resamp2.inc b/Frameworks/Dumb/dumb/src/helpers/resamp2.inc index 50c79b806..ee4151280 100644 --- a/Frameworks/Dumb/dumb/src/helpers/resamp2.inc +++ b/Frameworks/Dumb/dumb/src/helpers/resamp2.inc @@ -105,11 +105,11 @@ static int process_pickup(DUMB_RESAMPLER *resampler) #define VOLUME_VARIABLES lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm #define SET_VOLUME_VARIABLES { \ if ( volume_left ) { \ - lvolr = (int)(volume_left->volume * 16777216.0); \ - lvold = (int)(volume_left->delta * 16777216.0); \ - lvolt = (int)(volume_left->target * 16777216.0); \ - lvolm = (int)(volume_left->mix * 16777216.0); \ - lvol = MULSCV( lvolr, lvolm ); \ + lvolr = volume_left->volume; \ + lvold = volume_left->delta; \ + lvolt = volume_left->target; \ + lvolm = volume_left->mix; \ + lvol = lvolr * lvolm; \ if ( lvolr == lvolt ) volume_left = NULL; \ } else { \ lvol = 0; \ @@ -118,11 +118,11 @@ static int process_pickup(DUMB_RESAMPLER *resampler) lvolm = 0; \ } \ if ( volume_right ) { \ - rvolr = (int)(volume_right->volume * 16777216.0); \ - rvold = (int)(volume_right->delta * 16777216.0); \ - rvolt = (int)(volume_right->target * 16777216.0); \ - rvolm = (int)(volume_right->mix * 16777216.0); \ - rvol = MULSCV( rvolr, rvolm ); \ + rvolr = volume_right->volume; \ + rvold = volume_right->delta; \ + rvolt = volume_right->target; \ + rvolm = volume_right->mix; \ + rvol = rvolr * rvolm; \ if ( rvolr == rvolt ) volume_right = NULL; \ } else { \ rvol = 0; \ @@ -132,8 +132,8 @@ static int process_pickup(DUMB_RESAMPLER *resampler) } \ } #define RETURN_VOLUME_VARIABLES { \ - if ( volume_left ) volume_left->volume = (float)lvolr / 16777216.0f; \ - if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \ + if ( volume_left ) volume_left->volume = lvolr; \ + if ( volume_right ) volume_right->volume = rvolr; \ } #define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0) #define PEEK_FIR STEREO_DEST_PEEK_FIR diff --git a/Frameworks/Dumb/dumb/src/helpers/resamp3.inc b/Frameworks/Dumb/dumb/src/helpers/resamp3.inc index 3a77ebe26..e98515b19 100644 --- a/Frameworks/Dumb/dumb/src/helpers/resamp3.inc +++ b/Frameworks/Dumb/dumb/src/helpers/resamp3.inc @@ -47,12 +47,11 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLUME_PARAMETERS, float delta) { int dt, inv_dt; - int VOLUME_VARIABLES; + float VOLUME_VARIABLES; long done; long todo; LONG_LONG todo64; int quality; - /*int check;*/ if (!resampler || resampler->dir == 0) return 0; ASSERT(resampler->dir == -1 || resampler->dir == 1); @@ -210,7 +209,7 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETERS, sample_t *dst) { - int VOLUME_VARIABLES; + float VOLUME_VARIABLES; SRCTYPE *src; long pos; int subpos; diff --git a/Frameworks/Dumb/dumb/src/helpers/resample.c b/Frameworks/Dumb/dumb/src/helpers/resample.c index 4c6852f51..7a7bfacb0 100644 --- a/Frameworks/Dumb/dumb/src/helpers/resample.c +++ b/Frameworks/Dumb/dumb/src/helpers/resample.c @@ -81,7 +81,7 @@ * Values outside the range 0-4 will behave the same as the nearest * value within the range. */ -int dumb_resampling_quality = DUMB_RQ_BLAM; +int dumb_resampling_quality = DUMB_RQ_CUBIC; @@ -179,14 +179,14 @@ void _dumb_init_cubic(void) #define SUFFIX _16 #define SRCTYPE short #define SRCBITS 16 -#define FIR(x) (x) +#define FIR(x) (x * (1.0f / 32768.0f)) #include "resample.inc" /* Create resamplers for 8-bit source samples. */ #define SUFFIX _8 #define SRCTYPE signed char #define SRCBITS 8 -#define FIR(x) (x << 8) +#define FIR(x) (x * (1.0f / 256.0f)) #include "resample.inc" diff --git a/Frameworks/Dumb/dumb/src/helpers/resample.inc b/Frameworks/Dumb/dumb/src/helpers/resample.inc index d39de5596..fa63e843f 100644 --- a/Frameworks/Dumb/dumb/src/helpers/resample.inc +++ b/Frameworks/Dumb/dumb/src/helpers/resample.inc @@ -98,9 +98,9 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l pvol->declick_stage >= 3) \ pvol->declick_stage++; \ pvol = NULL; \ - vol = MULSCV( vol##t, vol##m ); \ + vol = vol##t * vol##m; \ } else { \ - vol = MULSCV( vol##r, vol##m ); \ + vol = vol##r * vol##m; \ } \ } \ } @@ -118,11 +118,11 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l #define MONO_DEST_VOLUME_ZEROS 0 #define SET_MONO_DEST_VOLUME_VARIABLES { \ if ( volume ) { \ - volr = (int)(volume->volume * 16777216.0); \ - vold = (int)(volume->delta * 16777216.0); \ - volt = (int)(volume->target * 16777216.0); \ - volm = (int)(volume->mix * 16777216.0); \ - vol = MULSCV( volr, volm ); \ + volr = volume->volume; \ + vold = volume->delta; \ + volt = volume->target; \ + volm = volume->mix; \ + vol = volr * volm; \ if ( volr == volt ) volume = NULL; \ } else { \ vol = 0; \ @@ -131,26 +131,26 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l volm = 0; \ } \ } -#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = (float)volr / 16777216.0f +#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = volr #define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0) #define POKE_FIR(offset) { \ - resampler_write_sample( resampler->fir_resampler[0], FIR(x[offset]) ); \ + resampler_write_sample_float( resampler->fir_resampler[0], FIR(x[offset]) ); \ } -#define MONO_DEST_PEEK_FIR *dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol ) +#define MONO_DEST_PEEK_FIR *dst = resampler_get_sample_float( resampler->fir_resampler[0] ) * vol * 16777216.0f #define MONO_DEST_MIX_FIR { \ - *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol ); \ + *dst++ += resampler_get_sample_float( resampler->fir_resampler[0] ) * vol * 16777216.0f; \ UPDATE_VOLUME( volume, vol ); \ } #define ADVANCE_FIR resampler_remove_sample( resampler->fir_resampler[0], 1 ) #define STEREO_DEST_PEEK_FIR { \ - int sample = resampler_get_sample( resampler->fir_resampler[0] ); \ - *dst++ = MULSC( sample, lvol ); \ - *dst++ = MULSC( sample, rvol ); \ + float sample = resampler_get_sample_float( resampler->fir_resampler[0] ); \ + *dst++ = sample * lvol * 16777216.0f; \ + *dst++ = sample * rvol * 16777216.0f; \ } #define STEREO_DEST_MIX_FIR { \ - int sample = resampler_get_sample( resampler->fir_resampler[0] ); \ - *dst++ += MULSC( sample, lvol ); \ - *dst++ += MULSC( sample, rvol ); \ + float sample = resampler_get_sample_float( resampler->fir_resampler[0] ); \ + *dst++ += sample * lvol * 16777216.0f; \ + *dst++ += sample * rvol * 16777216.0f; \ UPDATE_VOLUME( volume_left, lvol ); \ UPDATE_VOLUME( volume_right, rvol ); \ } @@ -179,11 +179,11 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l #define MONO_DEST_VOLUME_ZEROS 0, 0 #define SET_MONO_DEST_VOLUME_VARIABLES { \ if ( volume_left ) { \ - lvolr = (int)(volume_left->volume * 16777216.0); \ - lvold = (int)(volume_left->delta * 16777216.0); \ - lvolt = (int)(volume_left->target * 16777216.0); \ - lvolm = (int)(volume_left->mix * 16777216.0); \ - lvol = MULSCV( lvolr, lvolm ); \ + lvolr = volume_left->volume; \ + lvold = volume_left->delta; \ + lvolt = volume_left->target; \ + lvolm = volume_left->mix; \ + lvol = lvolr * lvolm; \ if ( lvolr == lvolt ) volume_left = NULL; \ } else { \ lvol = 0; \ @@ -192,11 +192,11 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l lvolm = 0; \ } \ if ( volume_right ) { \ - rvolr = (int)(volume_right->volume * 16777216.0); \ - rvold = (int)(volume_right->delta * 16777216.0); \ - rvolt = (int)(volume_right->target * 16777216.0); \ - rvolm = (int)(volume_right->mix * 16777216.0); \ - rvol = MULSCV( rvolr, rvolm ); \ + rvolr = volume_right->volume; \ + rvold = volume_right->delta; \ + rvolt = volume_right->target; \ + rvolm = volume_right->mix; \ + rvol = rvolr * rvolm; \ if ( rvolr == rvolt ) volume_right = NULL; \ } else { \ rvol = 0; \ @@ -206,21 +206,21 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l } \ } #define RETURN_MONO_DEST_VOLUME_VARIABLES { \ - if ( volume_left ) volume_left->volume = (float)lvolr / 16777216.0f; \ - if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \ + if ( volume_left ) volume_left->volume = lvolr; \ + if ( volume_right ) volume_right->volume = rvolr; \ } #define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0) #define POKE_FIR(offset) { \ - resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \ - resampler_write_sample( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \ + resampler_write_sample_float( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \ + resampler_write_sample_float( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \ } #define MONO_DEST_PEEK_FIR { \ - *dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \ - MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \ + *dst = (resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol + \ + resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol) * 16777216.0f; \ } #define MONO_DEST_MIX_FIR { \ - *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \ - MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \ + *dst++ += (resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol + \ + resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol) * 16777216.0f; \ UPDATE_VOLUME( volume_left, lvol ); \ UPDATE_VOLUME( volume_right, rvol ); \ } @@ -229,12 +229,12 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l resampler_remove_sample( resampler->fir_resampler[1], 1 ); \ } #define STEREO_DEST_PEEK_FIR { \ - *dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \ - *dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \ + *dst++ = resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol * 16777216.0f; \ + *dst++ = resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol * 16777216.0f; \ } #define STEREO_DEST_MIX_FIR { \ - *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \ - *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \ + *dst++ += resampler_get_sample_float( resampler->fir_resampler[0] ) * lvol * 16777216.0f; \ + *dst++ += resampler_get_sample_float( resampler->fir_resampler[1] ) * rvol * 16777216.0f; \ UPDATE_VOLUME( volume_left, lvol ); \ UPDATE_VOLUME( volume_right, rvol ); \ } diff --git a/Frameworks/Dumb/dumb/src/helpers/resampler.c b/Frameworks/Dumb/dumb/src/helpers/resampler.c index b0ea57e40..9bbdc51bf 100644 --- a/Frameworks/Dumb/dumb/src/helpers/resampler.c +++ b/Frameworks/Dumb/dumb/src/helpers/resampler.c @@ -2,7 +2,7 @@ #include #define _USE_MATH_DEFINES #include -#if (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__)) +#if defined(_USE_SSE) && (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__)) #include #define RESAMPLER_SSE #endif @@ -11,6 +11,8 @@ #if TARGET_CPU_ARM || TARGET_CPU_ARM64 #define RESAMPLER_NEON #endif +#elif (defined(__arm__) && defined(__ARM_NEON__)) +#define RESAMPLER_NEON #endif #ifdef RESAMPLER_NEON #include @@ -35,9 +37,9 @@ enum { RESAMPLER_RESOLUTION_EXTRA = 1 << (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTR enum { SINC_WIDTH = 16 }; enum { SINC_SAMPLES = RESAMPLER_RESOLUTION * SINC_WIDTH }; enum { CUBIC_SAMPLES = RESAMPLER_RESOLUTION * 4 }; -enum { IIR_ORDER = 6 }; static const float RESAMPLER_BLEP_CUTOFF = 0.90f; +static const float RESAMPLER_BLAM_CUTOFF = 0.93f; static const float RESAMPLER_SINC_CUTOFF = 0.999f; ALIGNED static float cubic_lut[CUBIC_SAMPLES]; @@ -138,54 +140,6 @@ void resampler_init(void) #endif } -typedef struct iir -{ - double cutoff; //frequency cutoff - double quality; //frequency response quality - double gain; //peak gain - double a0, a1, a2, b1, b2; //coefficients - double z1, z2; //second-order IIR -} iir; - -static void iir_reset(iir * i, double cutoff, double quality, double gain) -{ - double v, k, q, n; - - i->cutoff = cutoff; - i->quality = quality; - i->gain = gain; - - v = pow(10, fabs(gain) / 20.0); - k = tan(M_PI * cutoff); - q = quality; - - n = 1 / (1 + k / q + k * k); - i->a0 = k * k * n; - i->a1 = 2 * i->a0; - i->a2 = i->a0; - i->b1 = 2 * (k * k - 1) * n; - i->b2 = (1 - k / q + k * k) * n; -} - -static void iir_clear(iir * i) -{ - i->z1 = 0.0; - i->z2 = 0.0; -} - -static double iir_process(iir * i, double in) -{ - double out = in * i->a0 + i->z1; - i->z1 = in * i->a1 + i->z2 - i->b1 * out; - i->z2 = in * i->a2 - i->b2 * out; - return out; -} - -static double butterworth(unsigned int order, unsigned int phase) -{ - return -0.5 / cos(M_PI / 2.0 * (1.0 + (1.0 + (2.0 * phase + 1.0) / order))); -} - typedef struct resampler { int write_pos, write_filled; @@ -197,12 +151,10 @@ typedef struct resampler unsigned char quality; signed char delay_added; signed char delay_removed; - unsigned char output_stage; float last_amp; float accumulator; float buffer_in[resampler_buffer_size * 2]; float buffer_out[resampler_buffer_size + SINC_WIDTH * 2 - 1]; - iir filter[IIR_ORDER / 2]; } resampler; void * resampler_create(void) @@ -221,12 +173,10 @@ void * resampler_create(void) r->quality = RESAMPLER_QUALITY_MAX; r->delay_added = -1; r->delay_removed = -1; - r->output_stage = 0; r->last_amp = 0; r->accumulator = 0; memset( r->buffer_in, 0, sizeof(r->buffer_in) ); memset( r->buffer_out, 0, sizeof(r->buffer_out) ); - memset( r->filter, 0, sizeof(r->filter) ); return r; } @@ -262,12 +212,10 @@ void resampler_dup_inplace(void *_d, const void *_s) r_out->quality = r_in->quality; r_out->delay_added = r_in->delay_added; r_out->delay_removed = r_in->delay_removed; - r_out->output_stage = r_in->output_stage; r_out->last_amp = r_in->last_amp; r_out->accumulator = r_in->accumulator; memcpy( r_out->buffer_in, r_in->buffer_in, sizeof(r_in->buffer_in) ); memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) ); - memcpy( r_out->filter, r_in->filter, sizeof(r_in->filter) ); } void resampler_set_quality(void *_r, int quality) @@ -279,7 +227,8 @@ void resampler_set_quality(void *_r, int quality) quality = RESAMPLER_QUALITY_MAX; if ( r->quality != quality ) { - if ( quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLEP ) + if ( quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLEP || + quality == RESAMPLER_QUALITY_BLAM || r->quality == RESAMPLER_QUALITY_BLAM ) { r->read_pos = 0; r->read_filled = 0; @@ -289,8 +238,6 @@ void resampler_set_quality(void *_r, int quality) } r->delay_added = -1; r->delay_removed = -1; - if ( quality == RESAMPLER_QUALITY_BLAM && r->phase_inc ) - resampler_set_rate( r, r->phase_inc ); } r->quality = (unsigned char)quality; } @@ -348,21 +295,16 @@ static int resampler_output_delay(resampler *r) default: case RESAMPLER_QUALITY_ZOH: case RESAMPLER_QUALITY_LINEAR: - case RESAMPLER_QUALITY_BLAM: case RESAMPLER_QUALITY_CUBIC: case RESAMPLER_QUALITY_SINC: return 0; case RESAMPLER_QUALITY_BLEP: + case RESAMPLER_QUALITY_BLAM: return SINC_WIDTH - 1; } } -int resampler_get_padding_size() -{ - return SINC_WIDTH - 1; -} - int resampler_ready(void *_r) { resampler * r = ( resampler * ) _r; @@ -381,48 +323,21 @@ void resampler_clear(void *_r) r->delay_removed = -1; memset(r->buffer_in, 0, (SINC_WIDTH - 1) * sizeof(r->buffer_in[0])); memset(r->buffer_in + resampler_buffer_size, 0, (SINC_WIDTH - 1) * sizeof(r->buffer_in[0])); - if (r->quality == RESAMPLER_QUALITY_BLEP) + if (r->quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLAM) { r->inv_phase = 0; r->last_amp = 0; r->accumulator = 0; memset(r->buffer_out, 0, sizeof(r->buffer_out)); } - if (r->quality == RESAMPLER_QUALITY_BLAM) - { - unsigned int i, j; - for (i = 0, j = IIR_ORDER / 2; i < j; ++i) - iir_clear(r->filter + i); - } } void resampler_set_rate(void *_r, double new_factor) { resampler * r = ( resampler * ) _r; - float old_phase_inc = r->phase_inc; r->phase_inc = new_factor; new_factor = 1.0 / new_factor; r->inv_phase_inc = new_factor; - if (r->quality == RESAMPLER_QUALITY_BLAM && old_phase_inc != r->phase_inc) - { - double ratio_ = new_factor; - unsigned int i, j; - r->output_stage = (ratio_ >= 1.0); - if (!r->output_stage) - { - ratio_ *= 0.45; - } - else - { - ratio_ = (1.0 / ratio_) * 0.45; - } - if (ratio_ > 0.45) - { - ratio_ = 0.45; - } - for (i = 0, j = IIR_ORDER / 2; i < j; ++i) - iir_reset(r->filter + i, ratio_, butterworth(IIR_ORDER, i), 0.0); - } } void resampler_write_sample(void *_r, short s) @@ -437,16 +352,8 @@ void resampler_write_sample(void *_r, short s) if ( r->write_filled < resampler_buffer_size ) { - double s32 = s; + float s32 = s; s32 *= 256.0; - s32 += 1e-25; - - if ( r->quality == RESAMPLER_QUALITY_BLAM && !r->output_stage ) - { - unsigned int i, j; - for (i = 0, j = IIR_ORDER / 2; i < j; ++i) - s32 = iir_process(r->filter + i, s32); - } r->buffer_in[ r->write_pos ] = s32; r->buffer_in[ r->write_pos + resampler_buffer_size ] = s32; @@ -469,17 +376,9 @@ void resampler_write_sample_fixed(void *_r, int s, unsigned char depth) if ( r->write_filled < resampler_buffer_size ) { - double s32 = s; + float s32 = s; s32 /= (double)(1 << (depth - 1)); - s32 += 1e-25; - if ( r->quality == RESAMPLER_QUALITY_BLAM && !r->output_stage ) - { - unsigned int i, j; - for (i = 0, j = IIR_ORDER / 2; i < j; ++i) - s32 = iir_process(r->filter + i, s32); - } - r->buffer_in[ r->write_pos ] = s32; r->buffer_in[ r->write_pos + resampler_buffer_size ] = s32; @@ -489,6 +388,27 @@ void resampler_write_sample_fixed(void *_r, int s, unsigned char depth) } } +void resampler_write_sample_float(void *_r, float s) +{ + resampler * r = ( resampler * ) _r; + + if ( r->delay_added < 0 ) + { + r->delay_added = 0; + r->write_filled = resampler_input_delay( r ); + } + + if ( r->write_filled < resampler_buffer_size ) + { + r->buffer_in[ r->write_pos ] = s; + r->buffer_in[ r->write_pos + resampler_buffer_size ] = s; + + ++r->write_filled; + + r->write_pos = ( r->write_pos + 1 ) % resampler_buffer_size; + } +} + static int resampler_run_zoh(resampler * r, float ** out_, float * out_end) { int in_size = r->write_filled; @@ -800,11 +720,11 @@ static int resampler_run_linear(resampler * r, float ** out_, float * out_end) return used; } +#ifndef RESAMPLER_NEON static int resampler_run_blam(resampler * r, float ** out_, float * out_end) { int in_size = r->write_filled; float const* in_ = r->buffer_in + resampler_buffer_size + r->write_pos - r->write_filled; - unsigned int output_stage = r->output_stage; int used = 0; in_size -= 2; if ( in_size > 0 ) @@ -812,36 +732,66 @@ static int resampler_run_blam(resampler * r, float ** out_, float * out_end) float* out = *out_; float const* in = in_; float const* const in_end = in + in_size; + float last_amp = r->last_amp; float phase = r->phase; float phase_inc = r->phase_inc; + float inv_phase = r->inv_phase; + float inv_phase_inc = r->inv_phase_inc; + const int step = RESAMPLER_BLAM_CUTOFF * RESAMPLER_RESOLUTION; + const int window_step = RESAMPLER_RESOLUTION; + do { float sample; - if ( out >= out_end ) + if ( out + SINC_WIDTH * 2 > out_end ) break; - sample = in[0] + (in[1] - in[0]) * phase; - - if ( output_stage ) + sample = in[0]; + if (phase_inc < 1.0f) + sample += (in[1] - in[0]) * phase; + sample -= last_amp; + + if (sample) { - unsigned int i, j; - for (i = 0, j = IIR_ORDER / 2; i < j; ++i) - sample = iir_process(r->filter + i, sample); - } + float kernel[SINC_WIDTH * 2], kernel_sum = 0.0f; + int phase_reduced = (int)(inv_phase * RESAMPLER_RESOLUTION); + int phase_adj = phase_reduced * step / RESAMPLER_RESOLUTION; + int i = SINC_WIDTH; - *out++ = sample; + for (; i >= -SINC_WIDTH + 1; --i) + { + int pos = i * step; + int window_pos = i * window_step; + kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase_reduced - window_pos)]; + } + last_amp += sample; + sample /= kernel_sum; + for (i = 0; i < SINC_WIDTH * 2; ++i) + out[i] += sample * kernel[i]; + } - phase += phase_inc; - - in += (int)phase; - - phase = fmod(phase, 1.0f); + if (inv_phase_inc < 1.0f) + { + ++in; + inv_phase += inv_phase_inc; + out += (int)inv_phase; + inv_phase = fmod(inv_phase, 1.0f); + } + else + { + phase += phase_inc; + ++out; + in += (int)phase; + phase = fmod(phase, 1.0f); + } } while ( in < in_end ); r->phase = phase; + r->inv_phase = inv_phase; + r->last_amp = last_amp; *out_ = out; used = (int)(in - in_); @@ -851,6 +801,204 @@ static int resampler_run_blam(resampler * r, float ** out_, float * out_end) return used; } +#endif + +#ifdef RESAMPLER_SSE +static int resampler_run_blam_sse(resampler * r, float ** out_, float * out_end) +{ + int in_size = r->write_filled; + float const* in_ = r->buffer_in + resampler_buffer_size + r->write_pos - r->write_filled; + int used = 0; + in_size -= 2; + if ( in_size > 0 ) + { + float* out = *out_; + float const* in = in_; + float const* const in_end = in + in_size; + float last_amp = r->last_amp; + float phase = r->phase; + float phase_inc = r->phase_inc; + float inv_phase = r->inv_phase; + float inv_phase_inc = r->inv_phase_inc; + + const int step = RESAMPLER_BLAM_CUTOFF * RESAMPLER_RESOLUTION; + const int window_step = RESAMPLER_RESOLUTION; + + do + { + float sample; + + if ( out + SINC_WIDTH * 2 > out_end ) + break; + + sample = in[0]; + if (phase_inc < 1.0f) + { + sample += (in[1] - in[0]) * phase; + } + sample -= last_amp; + + if (sample) + { + float kernel_sum = 0.0f; + __m128 kernel[SINC_WIDTH / 2]; + __m128 temp1, temp2; + __m128 samplex; + float *kernelf = (float*)(&kernel); + int phase_reduced = (int)(inv_phase * RESAMPLER_RESOLUTION); + int phase_adj = phase_reduced * step / RESAMPLER_RESOLUTION; + int i = SINC_WIDTH; + + for (; i >= -SINC_WIDTH + 1; --i) + { + int pos = i * step; + int window_pos = i * window_step; + kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase_reduced - window_pos)]; + } + last_amp += sample; + sample /= kernel_sum; + samplex = _mm_set1_ps( sample ); + for (i = 0; i < SINC_WIDTH / 2; ++i) + { + temp1 = _mm_load_ps( (const float *)( kernel + i ) ); + temp1 = _mm_mul_ps( temp1, samplex ); + temp2 = _mm_loadu_ps( (const float *) out + i * 4 ); + temp1 = _mm_add_ps( temp1, temp2 ); + _mm_storeu_ps( (float *) out + i * 4, temp1 ); + } + } + + if (inv_phase_inc < 1.0f) + { + ++in; + inv_phase += inv_phase_inc; + out += (int)inv_phase; + inv_phase = fmod(inv_phase, 1.0f); + } + else + { + phase += phase_inc; + ++out; + + if (phase >= 1.0f) + { + ++in; + phase = fmod(phase, 1.0f); + } + } + } + while ( in < in_end ); + + r->phase = phase; + r->inv_phase = inv_phase; + r->last_amp = last_amp; + *out_ = out; + + used = (int)(in - in_); + + r->write_filled -= used; + } + + return used; +} +#endif + +#ifdef RESAMPLER_NEON +static int resampler_run_blam(resampler * r, float ** out_, float * out_end) +{ + int in_size = r->write_filled; + float const* in_ = r->buffer_in + resampler_buffer_size + r->write_pos - r->write_filled; + int used = 0; + in_size -= 2; + if ( in_size > 0 ) + { + float* out = *out_; + float const* in = in_; + float const* const in_end = in + in_size; + float last_amp = r->last_amp; + float phase = r->phase; + float phase_inc = r->phase_inc; + float inv_phase = r->inv_phase; + float inv_phase_inc = r->inv_phase_inc; + + const int step = RESAMPLER_BLAM_CUTOFF * RESAMPLER_RESOLUTION; + const int window_step = RESAMPLER_RESOLUTION; + + do + { + float sample; + + if ( out + SINC_WIDTH * 2 > out_end ) + break; + + sample = in[0]; + if (phase_inc < 1.0f) + sample += (in[1] - in[0]) * phase; + sample -= last_amp; + + if (sample) + { + float kernel_sum = 0.0; + float32x4_t kernel[SINC_WIDTH / 2]; + float32x4_t temp1, temp2; + float32x4_t samplex; + float *kernelf = (float*)(&kernel); + int phase_reduced = (int)(inv_phase * RESAMPLER_RESOLUTION); + int phase_adj = phase_reduced * step / RESAMPLER_RESOLUTION; + int i = SINC_WIDTH; + + for (; i >= -SINC_WIDTH + 1; --i) + { + int pos = i * step; + int window_pos = i * window_step; + kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase_reduced - window_pos)]; + } + last_amp += sample; + sample /= kernel_sum; + samplex = vdupq_n_f32(sample); + for (i = 0; i < SINC_WIDTH / 2; ++i) + { + temp1 = vld1q_f32( (const float32_t *)( kernel + i ) ); + temp2 = vld1q_f32( (const float32_t *) out + i * 4 ); + temp2 = vmlaq_f32( temp2, temp1, samplex ); + vst1q_f32( (float32_t *) out + i * 4, temp2 ); + } + } + + if (inv_phase_inc < 1.0f) + { + ++in; + inv_phase += inv_phase_inc; + out += (int)inv_phase; + inv_phase = fmod(inv_phase, 1.0f); + } + else + { + phase += phase_inc; + ++out; + + if (phase >= 1.0f) + { + ++in; + phase = fmod(phase, 1.0f); + } + } + } + while ( in < in_end ); + + r->phase = phase; + r->inv_phase = inv_phase; + r->last_amp = last_amp; + *out_ = out; + + used = (int)(in - in_); + + r->write_filled -= used; + } + + return used; +} +#endif #ifndef RESAMPLER_NEON static int resampler_run_cubic(resampler * r, float ** out_, float * out_end) @@ -1257,8 +1405,25 @@ static void resampler_fill(resampler * r) break; case RESAMPLER_QUALITY_BLAM: - resampler_run_blam( r, &out, out + write_size ); + { + float * out_ = out; + int write_extra = 0; + if ( write_pos >= r->read_pos ) + write_extra = r->read_pos; + if ( write_extra > SINC_WIDTH * 2 - 1 ) + write_extra = SINC_WIDTH * 2 - 1; + memcpy( r->buffer_out + resampler_buffer_size, r->buffer_out, write_extra * sizeof(r->buffer_out[0]) ); +#ifdef RESAMPLER_SSE + if ( resampler_has_sse ) + resampler_run_blam_sse( r, &out, out + write_size + write_extra ); + else +#endif + resampler_run_blam( r, &out, out + write_size + write_extra ); + memcpy( r->buffer_out, r->buffer_out + resampler_buffer_size, write_extra * sizeof(r->buffer_out[0]) ); + if ( out == out_ ) + return; break; + } case RESAMPLER_QUALITY_CUBIC: #ifdef RESAMPLER_SSE @@ -1297,7 +1462,7 @@ static void resampler_fill_and_remove_delay(resampler * r) int resampler_get_sample_count(void *_r) { resampler * r = ( resampler * ) _r; - if ( r->read_filled < 1 && (r->quality != RESAMPLER_QUALITY_BLEP || r->inv_phase_inc) ) + if ( r->read_filled < 1 && ((r->quality != RESAMPLER_QUALITY_BLEP && r->quality != RESAMPLER_QUALITY_BLAM) || r->inv_phase_inc)) resampler_fill_and_remove_delay( r ); return r->read_filled; } @@ -1309,7 +1474,7 @@ int resampler_get_sample(void *_r) resampler_fill_and_remove_delay( r ); if ( r->read_filled < 1 ) return 0; - if ( r->quality == RESAMPLER_QUALITY_BLEP ) + if ( r->quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLAM ) return (int)(r->buffer_out[ r->read_pos ] + r->accumulator); else return (int)r->buffer_out[ r->read_pos ]; @@ -1322,7 +1487,7 @@ float resampler_get_sample_float(void *_r) resampler_fill_and_remove_delay( r ); if ( r->read_filled < 1 ) return 0; - if ( r->quality == RESAMPLER_QUALITY_BLEP ) + if ( r->quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLAM ) return r->buffer_out[ r->read_pos ] + r->accumulator; else return r->buffer_out[ r->read_pos ]; @@ -1333,7 +1498,7 @@ void resampler_remove_sample(void *_r, int decay) resampler * r = ( resampler * ) _r; if ( r->read_filled > 0 ) { - if ( r->quality == RESAMPLER_QUALITY_BLEP ) + if ( r->quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLAM ) { r->accumulator += r->buffer_out[ r->read_pos ]; r->buffer_out[ r->read_pos ] = 0; diff --git a/Frameworks/Dumb/dumb/src/helpers/stdfile.c b/Frameworks/Dumb/dumb/src/helpers/stdfile.c index ec042ecac..0da786924 100644 --- a/Frameworks/Dumb/dumb/src/helpers/stdfile.c +++ b/Frameworks/Dumb/dumb/src/helpers/stdfile.c @@ -36,6 +36,11 @@ static void *dumb_stdfile_open(const char *filename) dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) ); if ( !file ) return 0; file->file = fopen(filename, "rb"); + if ( !file->file ) + { + free( file ); + return 0; + } fseek(file->file, 0, SEEK_END); file->size = ftell(file->file); fseek(file->file, 0, SEEK_SET); diff --git a/Frameworks/Dumb/dumb/src/it/itread.c b/Frameworks/Dumb/dumb/src/it/itread.c index 8f41d57bf..b9a2d02bc 100644 --- a/Frameworks/Dumb/dumb/src/it/itread.c +++ b/Frameworks/Dumb/dumb/src/it/itread.c @@ -28,7 +28,7 @@ #endif -#define INVESTIGATE_OLD_INSTRUMENTS +//#define INVESTIGATE_OLD_INSTRUMENTS @@ -290,12 +290,15 @@ static int it_read_envelope(IT_ENVELOPE *envelope, DUMBFILE *f) envelope->flags = dumbfile_getc(f); envelope->n_nodes = dumbfile_getc(f); + if(envelope->n_nodes > 25) { + TRACE("IT error: wrong number of envelope nodes (%d)\n", envelope->n_nodes); + envelope->n_nodes = 0; + return -1; + } envelope->loop_start = dumbfile_getc(f); envelope->loop_end = dumbfile_getc(f); envelope->sus_loop_start = dumbfile_getc(f); envelope->sus_loop_end = dumbfile_getc(f); - if (envelope->n_nodes > 25) - envelope->n_nodes = 25; for (n = 0; n < envelope->n_nodes; n++) { envelope->node_y[n] = dumbfile_getc(f); envelope->node_t[n] = dumbfile_igetw(f); @@ -620,8 +623,8 @@ long _dumb_it_read_sample_data_adpcm4(IT_SAMPLE *sample, DUMBFILE *f) long n, len, delta; signed char * ptr, * end; signed char compression_table[16]; - if (dumbfile_getnc((char *)compression_table, 16, f) != 16) - return -1; + if (dumbfile_getnc((char *)compression_table, 16, f) != 16) + return -1; ptr = (signed char *) sample->data; delta = 0; @@ -822,7 +825,7 @@ static int it_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buff while (bufpos < buflen) { unsigned char b = buffer[bufpos++]; - + if (b == 0) { /* End of row */ IT_SET_END_ROW(entry); @@ -838,31 +841,46 @@ static int it_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buff channel = (b - 1) & 63; - if (b & 128) + if (b & 128) { + if (bufpos >= buflen) + return -1; + cmask[channel] = mask = buffer[bufpos++]; - else + } else mask = cmask[channel]; if (mask) { entry->mask = (mask & 15) | (mask >> 4); entry->channel = channel; - if (mask & IT_ENTRY_NOTE) + if (mask & IT_ENTRY_NOTE) { + if (bufpos >= buflen) + return -1; + cnote[channel] = entry->note = buffer[bufpos++]; - else if (mask & (IT_ENTRY_NOTE << 4)) + } else if (mask & (IT_ENTRY_NOTE << 4)) entry->note = cnote[channel]; - if (mask & IT_ENTRY_INSTRUMENT) + if (mask & IT_ENTRY_INSTRUMENT) { + if (bufpos >= buflen) + return -1; + cinstrument[channel] = entry->instrument = buffer[bufpos++]; - else if (mask & (IT_ENTRY_INSTRUMENT << 4)) + } else if (mask & (IT_ENTRY_INSTRUMENT << 4)) entry->instrument = cinstrument[channel]; - if (mask & IT_ENTRY_VOLPAN) + if (mask & IT_ENTRY_VOLPAN) { + if (bufpos >= buflen) + return -1; + cvolpan[channel] = entry->volpan = buffer[bufpos++]; - else if (mask & (IT_ENTRY_VOLPAN << 4)) + } else if (mask & (IT_ENTRY_VOLPAN << 4)) entry->volpan = cvolpan[channel]; if (mask & IT_ENTRY_EFFECT) { + if (bufpos + 1 >= buflen) + return -1; + ceffect[channel] = entry->effect = buffer[bufpos++]; ceffectvalue[channel] = entry->effectvalue = buffer[bufpos++]; } else { @@ -940,6 +958,7 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f) int message_length, message_offset; IT_COMPONENT *component; + int min_components; int n_components = 0; unsigned char sample_convert[4096]; @@ -1044,10 +1063,15 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f) sigdata->pattern[n].entry = NULL; } - dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f); + if ( dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders ) { + _dumb_it_unload_sigdata(sigdata); + return NULL; + } sigdata->restart_position = 0; + + min_components = (special & 1) + sigdata->n_instruments + sigdata->n_samples + sigdata->n_patterns; - component = malloc(769 * sizeof(*component)); + component = malloc(min_components * sizeof(*component)); if (!component) { _dumb_it_unload_sigdata(sigdata); return NULL; @@ -1236,7 +1260,7 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f) switch (component[n].type) { case IT_COMPONENT_SONG_MESSAGE: - if ( n < n_components ) { + if ( n+1 < n_components ) { message_length = min( message_length, (int)(component[n+1].offset - component[n].offset) ); } sigdata->song_message = malloc(message_length + 1); diff --git a/Frameworks/Dumb/dumb/src/it/itrender.c b/Frameworks/Dumb/dumb/src/it/itrender.c index 15d956c4d..d5bbf7928 100644 --- a/Frameworks/Dumb/dumb/src/it/itrender.c +++ b/Frameworks/Dumb/dumb/src/it/itrender.c @@ -3789,7 +3789,7 @@ static void update_tick_counts(DUMB_IT_SIGRENDERER *sigrenderer) } } } - } else if (channel->note_delay_count) { + } else if (channel->note_delay_count && channel->note_delay_entry) { channel->note_delay_count--; if (channel->note_delay_count == 0) process_note_data(sigrenderer, channel->note_delay_entry, 0); @@ -4259,6 +4259,8 @@ static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer) tick = 0; else ++tick; + if (sigrenderer->sigdata->flags & IT_WAS_AN_STM) + tick /= 16; playing->delta *= (float)pow(DUMB_SEMITONE_BASE, channel->arpeggio_offsets[channel->arpeggio_table[tick&31]]); } /* @@ -4299,6 +4301,9 @@ static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer) static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer) { DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata; + + if ( sigrenderer->tempo < 32 || sigrenderer->tempo > 255 ) // problematic + return 1; // Set note vol/freq to vol/freq set for each channel @@ -4440,8 +4445,13 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer) /** WARNING - everything pertaining to a new pattern initialised? */ - sigrenderer->entry = sigrenderer->entry_start = pattern->entry; - sigrenderer->entry_end = sigrenderer->entry + pattern->n_entries; + if ( pattern->entry ) { + sigrenderer->entry = sigrenderer->entry_start = pattern->entry; + sigrenderer->entry_end = sigrenderer->entry + pattern->n_entries; + } else { + sigrenderer->entry = sigrenderer->entry_start = 0; + sigrenderer->entry_end = 0; + } /* If n_rows was 0, we're only just starting. Don't do anything weird here. */ /* added: process row check, for break to row spooniness */ @@ -4506,6 +4516,7 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer) if (!(sigdata->flags & IT_WAS_A_669)) reset_effects(sigrenderer); + if ( sigrenderer->entry ) { IT_ENTRY *entry = sigrenderer->entry; int ignore_cxx = 0; @@ -4525,6 +4536,7 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer) else if (!(sigdata->flags & IT_OLD_EFFECTS)) update_smooth_effects(sigrenderer); } else { + if ( sigrenderer->entry ) { IT_ENTRY *entry = sigrenderer->entry; @@ -5320,6 +5332,10 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha channel->inv_loop_speed = 0; channel->inv_loop_offset = 0; channel->playing = NULL; + channel->key_off_count = 0; + channel->note_cut_count = 0; + channel->note_delay_count = 0; + channel->note_delay_entry = 0; #ifdef BIT_ARRAY_BULLSHIT channel->played_patjump = NULL; channel->played_patjump_order = 0xFFFE; @@ -5405,7 +5421,10 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha //sigrenderer->max_output = 0; if ( !(sigdata->flags & IT_WAS_PROCESSED) ) { - dumb_it_add_lpc( sigdata ); + if ( dumb_it_add_lpc( sigdata ) < 0 ) { + _dumb_it_end_sigrenderer( sigrenderer ); + return NULL; + } sigdata->flags |= IT_WAS_PROCESSED; } @@ -5596,6 +5615,8 @@ static long it_sigrenderer_get_samples( LONG_LONG t; if (sigrenderer->order < 0) return 0; // problematic + + if (!sigrenderer->tempo) return 0; // also problematic pos = 0; dt = (int)(delta * 65536.0f + 0.5f); diff --git a/Frameworks/Dumb/dumb/src/it/readamf.c b/Frameworks/Dumb/dumb/src/it/readamf.c index 82fa4fca3..34dd2cb01 100644 --- a/Frameworks/Dumb/dumb/src/it/readamf.c +++ b/Frameworks/Dumb/dumb/src/it/readamf.c @@ -260,6 +260,9 @@ static int it_amf_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f ) if ( sample->length ) read_length = (int)dumbfile_getnc( sample->data, sample->length, f ); + + if ( read_length < 0 ) + read_length = 0; for ( i = 0; i < read_length; i++ ) { ( ( signed char * ) sample->data )[ i ] ^= 0x80; @@ -320,6 +323,8 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version) free( sigdata ); return NULL; } + + sigdata->n_pchannels = nchannels; memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS ); diff --git a/Frameworks/Dumb/dumb/src/it/readany.c b/Frameworks/Dumb/dumb/src/it/readany.c index 637ad16d3..ec9e37db1 100644 --- a/Frameworks/Dumb/dumb/src/it/readany.c +++ b/Frameworks/Dumb/dumb/src/it/readany.c @@ -39,7 +39,7 @@ DUH *dumb_read_any_quick(DUMBFILE *f, int restrict_, int subsong) unsigned long signature_size; DUH * duh = NULL; - signature_size = dumbfile_get_size(f); + /* signature_size = dumbfile_get_size(f); */ signature_size = dumbfile_getnc( (char *)signature, maximum_signature_size, f ); dumbfile_seek( f, 0, DFS_SEEK_SET ); diff --git a/Frameworks/Dumb/dumb/src/it/readmod.c b/Frameworks/Dumb/dumb/src/it/readmod.c index 61e0d7a29..fdff3ca62 100644 --- a/Frameworks/Dumb/dumb/src/it/readmod.c +++ b/Frameworks/Dumb/dumb/src/it/readmod.c @@ -118,7 +118,7 @@ static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, -static int it_mod_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, int stk) +static int it_mod_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, unsigned long fft, int stk) { int finetune, loop_start, loop_length; @@ -137,7 +137,10 @@ assumed not to be an instrument name, and is probably a message. sample->filename[0] = 0; sample->length = dumbfile_mgetw(f) << 1; - finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */ + if (fft == DUMB_ID('F','E','S','T')) + finetune = (signed char)((-dumbfile_getc(f) & 0x1F) << 3) >> 3; + else + finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */ /** Each finetune step changes the note 1/8th of a semitone. */ sample->global_volume = 64; sample->default_volume = dumbfile_getc(f); // Should we be setting global_volume to this instead? @@ -166,7 +169,7 @@ told to stop. sample->default_pan = 0; sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 ); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32)); - sample->finetune = finetune * 32; + sample->finetune = finetune * ((fft == DUMB_ID('F','E','S','T')) ? 16 : 32); // the above line might be wrong if (sample->loop_end > sample->length) @@ -280,15 +283,15 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_) int i; unsigned long fft; - if ( dumbfile_seek(f, MOD_FFT_OFFSET, DFS_SEEK_SET) ) - return NULL; + if ( dumbfile_seek(f, MOD_FFT_OFFSET, DFS_SEEK_SET) ) + return NULL; - fft = dumbfile_mgetl(f); - if (dumbfile_error(f)) - return NULL; + fft = dumbfile_mgetl(f); + if (dumbfile_error(f)) + return NULL; - if ( dumbfile_seek(f, 0, DFS_SEEK_SET) ) - return NULL; + if ( dumbfile_seek(f, 0, DFS_SEEK_SET) ) + return NULL; sigdata = malloc(sizeof(*sigdata)); if (!sigdata) { @@ -317,6 +320,7 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_) case DUMB_ID('F','L','T','4'): case DUMB_ID('M',0,0,0): case DUMB_ID('8',0,0,0): + case DUMB_ID('F','E','S','T'): n_channels = 4; break; case DUMB_ID('F','L','T','8'): @@ -381,6 +385,7 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_) } else { n_channels = 4; sigdata->n_samples = 15; + fft = 0; } } @@ -412,7 +417,7 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_) sigdata->sample[i].data = NULL; for (i = 0; i < sigdata->n_samples; i++) { - if (it_mod_read_sample_header(&sigdata->sample[i], f, sigdata->n_samples == 15)) { + if (it_mod_read_sample_header(&sigdata->sample[i], f, fft, sigdata->n_samples == 15)) { _dumb_it_unload_sigdata(sigdata); return NULL; } diff --git a/Frameworks/Dumb/dumb/src/it/readmtm.c b/Frameworks/Dumb/dumb/src/it/readmtm.c index 93685cd3d..0daa5b83b 100644 --- a/Frameworks/Dumb/dumb/src/it/readmtm.c +++ b/Frameworks/Dumb/dumb/src/it/readmtm.c @@ -30,7 +30,7 @@ size_t strlen_max(const char * ptr, size_t max) if (ptr==0) return 0; start = ptr; end = ptr + max; - while(*ptr && ptr < end) ptr++; + while(ptr < end && *ptr) ptr++; return ptr - start; } @@ -92,7 +92,7 @@ static int it_mtm_assemble_pattern(IT_PATTERN *pattern, const unsigned char * tr return 0; } -static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f) +static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f, int * skip_bytes) { int finetune, flags; @@ -117,7 +117,9 @@ static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f) sample->flags = IT_SAMPLE_EXISTS; + *skip_bytes = 0; if (flags & 1) { + *skip_bytes = sample->length & 1; sample->flags |= IT_SAMPLE_16BIT; sample->length >>= 1; sample->loop_start >>= 1; @@ -144,10 +146,11 @@ static int it_mtm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f) return dumbfile_error(f); } -static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f) +static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f, int skip_bytes) { long i; long truncated_size; + long bytes_per_sample; /* let's get rid of the sample data coming after the end of the loop */ if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) { @@ -156,20 +159,24 @@ static int it_mtm_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f) } else { truncated_size = 0; } + + bytes_per_sample = (sample->flags & IT_SAMPLE_16BIT) ? 2 : 1; - sample->data = malloc(sample->length); + sample->data = malloc(sample->length * bytes_per_sample); if (!sample->data) return -1; - dumbfile_getnc((char *)sample->data, sample->length, f); - dumbfile_skip(f, truncated_size); + dumbfile_getnc((char *)sample->data, sample->length * bytes_per_sample, f); + dumbfile_skip(f, truncated_size * bytes_per_sample); + dumbfile_skip(f, skip_bytes); if (dumbfile_error(f)) return -1; - for (i = 0; i < sample->length; i++) - ((signed char *)sample->data)[i] ^= 0x80; + if (bytes_per_sample == 1) + for (i = 0; i < sample->length; i++) + ((signed char *)sample->data)[i] ^= 0x80; return 0; } @@ -185,6 +192,8 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version) unsigned short * sequence; char * comment; + + int * skip_bytes; if (dumbfile_getc(f) != 'M' || dumbfile_getc(f) != 'T' || @@ -258,23 +267,26 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version) sigdata->restart_position = 0; sigdata->n_pchannels = n_channels; - + for (n = 0; n < sigdata->n_samples; n++) sigdata->sample[n].data = NULL; + skip_bytes = calloc(sizeof(int), sigdata->n_samples); + if (!skip_bytes) goto error_usd; + for (n = 0; n < sigdata->n_samples; n++) { - if (it_mtm_read_sample_header(&sigdata->sample[n], f)) goto error_usd; + if (it_mtm_read_sample_header(&sigdata->sample[n], f, skip_bytes + n)) goto error_sb; } sigdata->order = malloc(sigdata->n_orders); - if (!sigdata->order) goto error_usd; + if (!sigdata->order) goto error_sb; - if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders) goto error_usd; + if (dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f) < sigdata->n_orders) goto error_sb; if (sigdata->n_orders < 128) - if (dumbfile_skip(f, 128 - sigdata->n_orders)) goto error_usd; + if (dumbfile_skip(f, 128 - sigdata->n_orders)) goto error_sb; track = malloc(192 * n_tracks); - if (!track) goto error_usd; + if (!track) goto error_sb; if (dumbfile_getnc((char *)track, 192 * n_tracks, f) < 192 * n_tracks) goto error_ft; @@ -321,7 +333,8 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version) int l, m; for (l = 0, n = 0; n <= o; n += 40) { - l += strlen_max(&comment[n], 40) + 2; + int maxlen = l_comment - n; + l += strlen_max(&comment[n], maxlen > 40 ? 40 : maxlen) + 2; } l -= 1; @@ -330,7 +343,8 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version) if (!sigdata->song_message) goto error_fc; for (m = 0, n = 0; n <= o; n += 40) { - int p = (int) strlen_max(&comment[n], 40); + int maxlen = l_comment - n; + int p = (int) strlen_max(&comment[n], maxlen > 40 ? 40 : maxlen); if (p) { memcpy(sigdata->song_message + m, &comment[n], p); m += p; @@ -348,13 +362,14 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version) } for (n = 0; n < sigdata->n_samples; n++) { - if (it_mtm_read_sample_data(&sigdata->sample[n], f)) goto error_fs; + if (it_mtm_read_sample_data(&sigdata->sample[n], f, skip_bytes[n])) goto error_fs; } - + _dumb_it_fix_invalid_orders(sigdata); free(sequence); free(track); + free(skip_bytes); return sigdata; @@ -364,6 +379,8 @@ error_fs: free(sequence); error_ft: free(track); +error_sb: + free(skip_bytes); error_usd: _dumb_it_unload_sigdata(sigdata); return NULL; diff --git a/Frameworks/Dumb/dumb/src/it/readoldpsm.c b/Frameworks/Dumb/dumb/src/it/readoldpsm.c index b3f81076d..48f4d9e48 100644 --- a/Frameworks/Dumb/dumb/src/it/readoldpsm.c +++ b/Frameworks/Dumb/dumb/src/it/readoldpsm.c @@ -66,89 +66,88 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num) qsort(buffer, count, 64, &psm_sample_compare); - for (n = 0; n < true_num; n++) { + for (n = 0; n < *num; n++) { (*sample)[n].flags = 0; } for (n = 0; n < count; n++) { + IT_SAMPLE smp; IT_SAMPLE * s; snum = buffer[(n * 64) + 45] | (buffer[(n * 64) + 46] << 8); s = &((*sample)[snum - 1]); - memcpy(s->filename, buffer + (n * 64), 13); - s->filename[13] = 0; - memcpy(s->name, buffer + (n * 64) + 13, 24); - s->name[24] = 0; + memcpy(smp.filename, buffer + (n * 64), 13); + smp.filename[13] = 0; + memcpy(smp.name, buffer + (n * 64) + 13, 24); + smp.name[24] = 0; offset = buffer[(n * 64) + 37] | (buffer[(n * 64) + 38] << 8) | (buffer[(n * 64) + 39] << 16) | (buffer[(n * 64) + 40] << 24); flags = buffer[(n * 64) + 47]; - s->length = buffer[(n * 64) + 48] | (buffer[(n * 64) + 49] << 8) | + smp.length = buffer[(n * 64) + 48] | (buffer[(n * 64) + 49] << 8) | (buffer[(n * 64) + 50] << 16) | (buffer[(n * 64) + 51] << 24); - s->loop_start = buffer[(n * 64) + 52] | (buffer[(n * 64) + 53] << 8) | + smp.loop_start = buffer[(n * 64) + 52] | (buffer[(n * 64) + 53] << 8) | (buffer[(n * 64) + 54] << 16) | (buffer[(n * 64) + 55] << 24); - s->loop_end = buffer[(n * 64) + 56] | (buffer[(n * 64) + 57] << 8) | + smp.loop_end = buffer[(n * 64) + 56] | (buffer[(n * 64) + 57] << 8) | (buffer[(n * 64) + 58] << 16) | (buffer[(n * 64) + 59] << 24); - if (s->length <= 0) continue; + if (smp.length <= 0) continue; finetune = buffer[(n * 64) + 60]; - s->default_volume = buffer[(n * 64) + 61]; - s->C5_speed = buffer[(n * 64) + 62] | (buffer[(n * 64) + 63] << 8); + smp.default_volume = buffer[(n * 64) + 61]; + smp.C5_speed = buffer[(n * 64) + 62] | (buffer[(n * 64) + 63] << 8); if (finetune & 15) { finetune &= 15; if (finetune >= 8) finetune -= 16; //s->C5_speed = (long)((double)s->C5_speed * pow(DUMB_PITCH_BASE, finetune*32)); - s->finetune = finetune * 32; + smp.finetune = finetune * 32; } - else s->finetune = 0; + else smp.finetune = 0; - s->flags |= IT_SAMPLE_EXISTS; - if (flags & 0x41) { - s->flags &= ~IT_SAMPLE_EXISTS; + smp.flags |= IT_SAMPLE_EXISTS; + if (flags & 0x41) continue; - } - if (flags & 0x20) s->flags |= IT_SAMPLE_PINGPONG_LOOP; - if (flags & 4) s->flags |= IT_SAMPLE_16BIT; + if (flags & 0x20) smp.flags |= IT_SAMPLE_PINGPONG_LOOP; + if (flags & 4) smp.flags |= IT_SAMPLE_16BIT; if (flags & 0x80) { - s->flags |= IT_SAMPLE_LOOP; - if ((unsigned int)s->loop_end > (unsigned int)s->length) - s->loop_end = s->length; - else if ((unsigned int)s->loop_start >= (unsigned int)s->loop_end) - s->flags &= ~IT_SAMPLE_LOOP; + smp.flags |= IT_SAMPLE_LOOP; + if ((unsigned int)smp.loop_end > (unsigned int)smp.length) + smp.loop_end = smp.length; + else if ((unsigned int)smp.loop_start >= (unsigned int)smp.loop_end) + smp.flags &= ~IT_SAMPLE_LOOP; else - s->length = s->loop_end; + smp.length = smp.loop_end; } - s->global_volume = 64; + smp.global_volume = 64; - s->vibrato_speed = 0; - s->vibrato_depth = 0; - s->vibrato_rate = 0; - s->vibrato_waveform = IT_VIBRATO_SINE; - s->max_resampling_quality = -1; + smp.vibrato_speed = 0; + smp.vibrato_depth = 0; + smp.vibrato_rate = 0; + smp.vibrato_waveform = IT_VIBRATO_SINE; + smp.max_resampling_quality = -1; - sample_bytes = s->length * ((flags & 4) ? 2 : 1); - s->data = malloc(sample_bytes); - if (!s->data) goto error_fb; + sample_bytes = smp.length * ((flags & 4) ? 2 : 1); + smp.data = malloc(sample_bytes); + if (!smp.data) goto error_fb; + sdata = (const unsigned char *) smp.data; - if (dumbfile_seek(f, offset, DFS_SEEK_SET) || dumbfile_getnc(s->data, sample_bytes, f) < sample_bytes) goto error_fb; - sdata = ( const unsigned char * ) s->data; + if (dumbfile_seek(f, offset, DFS_SEEK_SET) || dumbfile_getnc(smp.data, sample_bytes, f) < sample_bytes) goto error_fd; if (flags & 0x10) { if (flags & 8) { if (flags & 4) { - for (o = 0; o < s->length; o++) - ((short *)s->data)[o] = (sdata[o * 2] | (sdata[(o * 2) + 1] << 8)) ^ 0x8000; + for (o = 0; o < smp.length; o++) + ((short *)smp.data)[o] = (sdata[o * 2] | (sdata[(o * 2) + 1] << 8)) ^ 0x8000; } else { - for (o = 0; o < s->length; o++) - ((signed char *)s->data)[o] = sdata[o] ^ 0x80; + for (o = 0; o < smp.length; o++) + ((signed char *)smp.data)[o] = sdata[o] ^ 0x80; } } else { if (flags & 4) { - for (o = 0; o < s->length; o++) - ((short *)s->data)[o] = sdata[o * 2] | (sdata[(o * 2) + 1] << 8); + for (o = 0; o < smp.length; o++) + ((short *)smp.data)[o] = sdata[o * 2] | (sdata[(o * 2) + 1] << 8); } else { - memcpy(s->data, sdata, s->length); + memcpy(smp.data, sdata, smp.length); } } } else { @@ -156,36 +155,41 @@ static int it_old_psm_read_samples(IT_SAMPLE ** sample, DUMBFILE * f, int * num) if (flags & 8) { /* unsigned delta? mehhh, does anything even use this? */ if (flags & 4) { - for (o = 0; o < s->length; o++) { + for (o = 0; o < smp.length; o++) { delta += (short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8)); - ((short *)s->data)[o] = delta ^ 0x8000; + ((short *)smp.data)[o] = delta ^ 0x8000; } } else { - for (o = 0; o < s->length; o++) { + for (o = 0; o < smp.length; o++) { delta += (signed char)sdata[o]; - ((signed char *)s->data)[o] = delta ^ 0x80; + ((signed char *)smp.data)[o] = delta ^ 0x80; } } } else { if (flags & 4) { - for (o = 0; o < s->length; o++) { + for (o = 0; o < smp.length; o++) { delta += (signed short)(sdata[o * 2] | (sdata[(o * 2) + 1] << 8)); - ((signed short *)s->data)[o] = delta; + ((signed short *)smp.data)[o] = delta; } } else { - for (o = 0; o < s->length; o++) { + for (o = 0; o < smp.length; o++) { delta += (signed char)sdata[o]; - ((signed char *)s->data)[o] = delta; + ((signed char *)smp.data)[o] = delta; } } } } + + if (s->data) free(s->data); + *s = smp; } free(buffer); return 0; +error_fd: + free((void *)sdata); error_fb: free(buffer); error: @@ -224,6 +228,8 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num, } psize = (psize + 15) & ~15; + + if (offset + psize > size) goto error_fb; end = ptr + psize; ptr += 4; @@ -243,9 +249,8 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num, if (flags & 0x80) ptr += 2; if (flags & 0x40) ptr++; if (flags & 0x20) { - ptr++; - if (*ptr == 40) ptr += 3; - else ptr++; + if (*ptr == 40) ptr += 4; + else ptr += 2; } } } diff --git a/Frameworks/Dumb/dumb/src/it/readpsm.c b/Frameworks/Dumb/dumb/src/it/readpsm.c index 43cceae18..2fd9dfbb8 100644 --- a/Frameworks/Dumb/dumb/src/it/readpsm.c +++ b/Frameworks/Dumb/dumb/src/it/readpsm.c @@ -96,7 +96,7 @@ static int it_psm_process_sample(IT_SAMPLE * sample, const unsigned char * data, if (insno != id) return -1; - if (!length) { + if (length <= 0) { sample->flags &= ~IT_SAMPLE_EXISTS; return 0; } @@ -162,7 +162,12 @@ static int it_psm_process_pattern(IT_PATTERN * pattern, const unsigned char * da nrows = data[0] | (data[1] << 8); - if (!nrows) return 0; + if (!nrows) { + pattern->n_rows = 0; + pattern->n_entries = 0; + pattern->entry = NULL; + return 0; + } pattern->n_rows = nrows; @@ -461,7 +466,7 @@ static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong) PSMCHUNK *chunk; int n_chunks = 0; - PSMCHUNK *songchunk; + PSMCHUNK *songchunk = 0; int n_song_chunks = 0; PSMEVENT *event = 0; @@ -491,6 +496,7 @@ static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong) chunk = calloc(768, sizeof(*chunk)); while (length >= 8) { + if (n_chunks >= 768) goto error_fc; chunk[n_chunks].id = dumbfile_mgetl(f); n = dumbfile_igetl(f); length -= 8; @@ -584,13 +590,14 @@ static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong) ptr += 11; songchunk = 0; if (length >= 8) { - songchunk = malloc(128 * sizeof(*songchunk)); + songchunk = malloc(256 * sizeof(*songchunk)); if (!songchunk) goto error_usd; while (length >= 8) { + if (n_song_chunks >= 256) goto error_sc; songchunk[n_song_chunks].id = DUMB_ID(ptr[0], ptr[1], ptr[2], ptr[3]); n = ptr[4] | (ptr[5] << 8) | (ptr[6] << 16) | (ptr[7] << 24); length -= 8; - if (n > length) goto error_sc; + if (n < 0 || n > length) goto error_sc; songchunk[n_song_chunks].len = n; songchunk[n_song_chunks].data = ptr + 8; n_song_chunks++; @@ -1246,7 +1253,7 @@ int pattcmp( const unsigned char * a, const unsigned char * b, size_t l ) } if ( i < j ) return -1; - else if ( j > i ) return 1; + else if ( i > j ) return 1; i = memcmp( a, b, j ); if ( i ) return i; @@ -1279,7 +1286,7 @@ DUH *dumb_read_psm_quick(DUMBFILE *f, int subsong) if ( ver ) { tag[2][0] = "FORMATVERSION"; - snprintf( version, 15, "%u", ver ); + snprintf( version, 15, "%d", ver ); version[15] = 0; tag[2][1] = (const char *) &version; ++n_tags; diff --git a/Frameworks/Dumb/dumb/src/it/readxm.c b/Frameworks/Dumb/dumb/src/it/readxm.c index 44fc9bdb5..69866ae72 100644 --- a/Frameworks/Dumb/dumb/src/it/readxm.c +++ b/Frameworks/Dumb/dumb/src/it/readxm.c @@ -371,6 +371,8 @@ static int limit_xm_resize(void *f, long n) { DUMBFILE *df = f; LIMITED_XM *lx = df->file; + if (n < 0) + return -1; if (lx->buffered || n) { if (n > lx->allocated) { unsigned char *buffered = realloc( lx->buffered, n ); @@ -897,20 +899,20 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version) if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo? sigdata->tempo = dumbfile_igetw(f); - // FT2 always clips restart position against the song length - if (sigdata->restart_position > sigdata->n_orders) - sigdata->restart_position = sigdata->n_orders; - // And FT2 starts playback on order 0, regardless of length, - // and only checks if the next order is greater than or equal - // to this, not the current pattern. Work around this with - // DUMB's playback core by overriding a zero length with one. - if (sigdata->n_orders == 0) - sigdata->n_orders = 1; + // FT2 always clips restart position against the song length + if (sigdata->restart_position > sigdata->n_orders) + sigdata->restart_position = sigdata->n_orders; + // And FT2 starts playback on order 0, regardless of length, + // and only checks if the next order is greater than or equal + // to this, not the current pattern. Work around this with + // DUMB's playback core by overriding a zero length with one. + if (sigdata->n_orders == 0) + sigdata->n_orders = 1; /* sanity checks */ // XXX i = header_size - 4 - 2 * 8; /* Maximum number of orders expected */ - if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_orders > i || sigdata->n_patterns > 256 || sigdata->n_instruments > 256 || n_channels > DUMB_IT_N_CHANNELS) { + if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_orders > i || !sigdata->n_patterns || sigdata->n_patterns > 256 || !sigdata->n_instruments || sigdata->n_instruments > 256 || n_channels > DUMB_IT_N_CHANNELS) { _dumb_it_unload_sigdata(sigdata); return NULL; } @@ -1095,6 +1097,7 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version) sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument)); if (!sigdata->instrument) { + free(roguebytes); _dumb_it_unload_sigdata(sigdata); return NULL; } diff --git a/Frameworks/Dumb/dumb/src/it/xmeffect.c b/Frameworks/Dumb/dumb/src/it/xmeffect.c index 1aa489222..c490780b8 100644 --- a/Frameworks/Dumb/dumb/src/it/xmeffect.c +++ b/Frameworks/Dumb/dumb/src/it/xmeffect.c @@ -19,6 +19,7 @@ +#include #include #include