Eric Wong <normalper...@yhbt.net> writes: > From: Martin Guy <martinw...@gmail.com> > > Sox had an arbitrary limit of 8193 on the vertical axis size > based on MAX_FFT_SIZE=4096 and had fixed-size arrays for its data. > This is both wasteful of memory for smaller FFTs and stops us producing > more detailed output for no obvious reason. > > This patch removes the size limit on Y-axis-height by making array > allocation dynamic. In practice, you can't remove the limit as getopt > insists on minimum and maximum values for numeric arguments, so we > copy the similarly arbitrary limit of 200000 from MAX_X_SIZE. > > Tested-by: Eric Wong <normalper...@yhbt.net> > --- > src/spectrogram.c | 37 +++++++++++++++++++++++++++---------- > 1 file changed, 27 insertions(+), 10 deletions(-) > > diff --git a/src/spectrogram.c b/src/spectrogram.c > index afb0b0e8..b38d2124 100644 > --- a/src/spectrogram.c > +++ b/src/spectrogram.c > @@ -36,10 +36,13 @@ > #include <io.h> > #endif > > -#define MAX_FFT_SIZE 4096 > #define is_p2(x) !(x & (x - 1)) > > +/* These are arbitrary as there is no upper limit, but > + * sox's getopt() needs an upper limit for each option, so... > + */ > #define MAX_X_SIZE 200000 > +#define MAX_Y_SIZE 200000 > > typedef enum {Window_Hann, Window_Hamming, Window_Bartlett, > Window_Rectangular, Window_Kaiser, Window_Dolph} win_type_t; > static lsx_enum_item const window_options[] = { > @@ -71,8 +74,11 @@ typedef struct { > int dft_size, step_size, block_steps, block_num, rows, cols, read; > int x_size, end, end_min, last_end; > sox_bool truncated; > - double buf[MAX_FFT_SIZE], dft_buf[MAX_FFT_SIZE], > window[MAX_FFT_SIZE+1]; > - double block_norm, max, magnitudes[(MAX_FFT_SIZE>>1) + 1]; > + double * buf; /* [dft_size] */ > + double * dft_buf; /* [dft_size] */ > + double * window; /* [dft_size + 1] */ > + double block_norm, max; > + double * magnitudes; /* [(dft_size / 2) + 1] */ > float * dBfs; > } priv_t; > > @@ -114,9 +120,9 @@ static int getopts(sox_effect_t * effp, int argc, char > **argv) > > while ((c = lsx_getopt(&optstate)) != -1) switch (c) { > GETOPT_NUMERIC(optstate, 'x', x_size0 , 100, MAX_X_SIZE) > - GETOPT_NUMERIC(optstate, 'X', pixels_per_sec, 1 , 5000) > - GETOPT_NUMERIC(optstate, 'y', y_size , 64 , 1200) > - GETOPT_NUMERIC(optstate, 'Y', Y_size , 130, MAX_FFT_SIZE / 2 + 2) > + GETOPT_NUMERIC(optstate, 'X', pixels_per_sec, 1 , MAX_X_SIZE) > + GETOPT_NUMERIC(optstate, 'y', y_size , 64 , MAX_Y_SIZE) > + GETOPT_NUMERIC(optstate, 'Y', Y_size , 130, MAX_Y_SIZE) > GETOPT_NUMERIC(optstate, 'z', dB_range , 20 , 180) > GETOPT_NUMERIC(optstate, 'Z', gain ,-100, 100) > GETOPT_NUMERIC(optstate, 'q', spectrum_points, 0 , p->spectrum_points) > @@ -172,7 +178,7 @@ static double make_window(priv_t * p, int end) > double sum = 0, * w = end < 0? p->window : p->window + end; > int i, n = 1 + p->dft_size - abs(end); > > - if (end) memset(p->window, 0, sizeof(p->window)); > + if (end) memset(p->window, 0, sizeof(*(p->window)) * p->dft_size);
This memset is short by one element. > for (i = 0; i < n; ++i) w[i] = 1; > switch (p->win_type) { > case Window_Hann: lsx_apply_hann(w, n); break; > @@ -190,10 +196,10 @@ static double make_window(priv_t * p, int end) > return sum; > } > > -static double * rdft_init(int n) > +static double * rdft_init(size_t n) > { > double * q = lsx_malloc(2 * (n / 2 + 1) * n * sizeof(*q)), * p = q; > - int i, j; > + size_t i, j; > for (j = 0; j <= n / 2; ++j) for (i = 0; i < n; ++i) > *p++ = cos(2 * M_PI * j * i / n), *p++ = sin(2 * M_PI * j * i / n); > return q; > @@ -260,11 +266,18 @@ static int start(sox_effect_t * effp) > if (p->y_size) { > p->dft_size = 2 * (p->y_size - 1); > if (!is_p2(p->dft_size) && !effp->flow) > - p->shared = rdft_init(p->dft_size); > + p->shared = rdft_init((size_t)(p->dft_size)); > } else { > int y = max(32, (p->Y_size? p->Y_size : 550) / effp->in_signal.channels - > 2); > for (p->dft_size = 128; p->dft_size <= y; p->dft_size <<= 1); > } > + > + /* Now that dft_size is set, allocate variable-sized elements of priv_t */ > + p->buf = lsx_calloc(p->dft_size, sizeof(*(p->buf))); > + p->dft_buf = lsx_calloc(p->dft_size, sizeof(*(p->dft_buf))); > + p->window = lsx_calloc(p->dft_size + 1, sizeof(*(p->window))); > + p->magnitudes = lsx_calloc((p->dft_size / 2) + 1, > sizeof(*(p->magnitudes))); > + > if (is_p2(p->dft_size) && !effp->flow) > lsx_safe_rdft(p->dft_size, 1, p->dft_buf); > lsx_debug("duration=%g x_size=%i pixels_per_sec=%g dft_size=%i", duration, > p->x_size, pixels_per_sec, p->dft_size); > @@ -651,6 +664,10 @@ error: png_destroy_write_struct(&png, &png_info); > free(png_rows); > free(pixels); > free(p->dBfs); > + free(p->buf); > + free(p->dft_buf); > + free(p->window); > + free(p->magnitudes); > return SOX_SUCCESS; > } -- Måns Rullgård _______________________________________________ SoX-devel mailing list SoX-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sox-devel