Interpret sample counts given for spectrogram's -d and -S options correctly. Previously, they were accepted syntactically (because lsx_parsesamples() is used for parsing the argument), but always interpreted according to a sample rate of 100 kHz; i.e., -d 20000s meant 0.2 seconds even when the sample rate was actually 10 kHz. Not really a bug though, because the possibility to specify samples wasn't documented.
Showing the changes to src/spectrogram.c (1 of 2 files). Show all
Unified · Split
| @@ -44,12 +44,13 @@ static lsx_enum_item const window_options[] = { · 43 unmodified lines | |||
| 44 | 44 | ||
| 45 | typedef struct { | 45 | typedef struct { |
| 46 | /* Parameters */ | 46 | /* Parameters */ |
| 47 | double pixels_per_sec, duration, start_time, window_adjust; | 47 | double pixels_per_sec, window_adjust; |
| 48 | int x_size0, y_size, Y_size, dB_range, gain, spectrum_points, perm; | 48 | int x_size0, y_size, Y_size, dB_range, gain, spectrum_points, perm; |
| 49 | sox_bool monochrome, light_background, high_colour, slack_overlap, no_axes; | 49 | sox_bool monochrome, light_background, high_colour, slack_overlap, no_axes; |
| 50 | sox_bool raw, alt_palette, truncate; | 50 | sox_bool raw, alt_palette, truncate; |
| 51 | win_type_t win_type; | 51 | win_type_t win_type; |
| 52 | char const * out_name, * title, * comment; | 52 | char const * out_name, * title, * comment; |
| 53 | char const *duration_str, *start_time_str; | ||
| 53 | sox_bool using_stdout; /* output image to stdout */ | 54 | sox_bool using_stdout; /* output image to stdout */ |
| 54 | 55 | ||
| 55 | /* Shared work area */ | 56 | /* Shared work area */ |
| @@ -93,7 +94,7 @@ static unsigned char const alt_palette[] = · 37 unmodified lines | |||
| 93 | static int getopts(sox_effect_t * effp, int argc, char **argv) | 94 | static int getopts(sox_effect_t * effp, int argc, char **argv) |
| 94 | { | 95 | { |
| 95 | priv_t * p = (priv_t *)effp->priv; | 96 | priv_t * p = (priv_t *)effp->priv; |
| 96 | uint64_t duration; | 97 | uint64_t dummy; |
| 97 | char const * next; | 98 | char const * next; |
| 98 | int c; | 99 | int c; |
| 99 | lsx_getopt_t optstate; | 100 | lsx_getopt_t optstate; |
| @@ -124,15 +125,15 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 24 unmodified lines | |||
| 124 | case 't': p->title = optstate.arg; break; | 125 | case 't': p->title = optstate.arg; break; |
| 125 | case 'c': p->comment = optstate.arg; break; | 126 | case 'c': p->comment = optstate.arg; break; |
| 126 | case 'o': p->out_name = optstate.arg; break; | 127 | case 'o': p->out_name = optstate.arg; break; |
| 127 | case 'S': next = lsx_parsesamples(1e5, optstate.arg, &duration, 't'); | 128 | case 'S': next = lsx_parsesamples(1e5, optstate.arg, &dummy, 't'); |
| 128 | if (next && !*next) {p->start_time = duration * 1e-5; break;} | 129 | if (next && !*next) {p->start_time_str = lsx_strdup(optstate.arg); break;} |
| 129 | return lsx_usage(effp); | 130 | return lsx_usage(effp); |
| 130 | case 'd': next = lsx_parsesamples(1e5, optstate.arg, &duration, 't'); | 131 | case 'd': next = lsx_parsesamples(1e5, optstate.arg, &dummy, 't'); |
| 131 | if (next && !*next) {p->duration = duration * 1e-5; break;} | 132 | if (next && !*next) {p->duration_str = lsx_strdup(optstate.arg); break;} |
| 132 | return lsx_usage(effp); | 133 | return lsx_usage(effp); |
| 133 | default: lsx_fail("invalid option `-%c'", optstate.opt); return lsx_usage(effp); | 134 | default: lsx_fail("invalid option `-%c'", optstate.opt); return lsx_usage(effp); |
| 134 | } | 135 | } |
| 135 | if (!!p->x_size0 + !!p->pixels_per_sec + !!p->duration > 2) { | 136 | if (!!p->x_size0 + !!p->pixels_per_sec + !!p->duration_str > 2) { |
| 136 | lsx_fail("only two of -x, -X, -d may be given"); | 137 | lsx_fail("only two of -x, -X, -d may be given"); |
| 137 | return SOX_EOF; | 138 | return SOX_EOF; |
| 138 | } | 139 | } |
| @@ -202,11 +203,22 @@ static void rdft_p(double const * q, double const * in, double * out, int n) · 63 unmodified lines | |||
| 202 | static int start(sox_effect_t * effp) | 203 | static int start(sox_effect_t * effp) |
| 203 | { | 204 | { |
| 204 | priv_t * p = (priv_t *)effp->priv; | 205 | priv_t * p = (priv_t *)effp->priv; |
| 205 | double actual, duration = p->duration, pixels_per_sec = p->pixels_per_sec; | 206 | double actual, duration = 0.0, start_time = 0.0, |
| 207 | pixels_per_sec = p->pixels_per_sec; | ||
| 208 | uint64_t d; | ||
| 206 | 209 | ||
| 207 | memset(&p->WORK, 0, sizeof(*p) - field_offset(priv_t, WORK)); | 210 | memset(&p->WORK, 0, sizeof(*p) - field_offset(priv_t, WORK)); |
| 208 | 211 | ||
| 209 | p->skip = p->start_time * effp->in_signal.rate + .5; | 212 | if (p->duration_str) { |
| 213 | lsx_parsesamples(effp->in_signal.rate, p->duration_str, &d, 't'); | ||
| 214 | duration = d / effp->in_signal.rate; | ||
| 215 | } | ||
| 216 | if (p->start_time_str) { | ||
| 217 | lsx_parsesamples(effp->in_signal.rate, p->start_time_str, &d, 't'); | ||
| 218 | start_time = d / effp->in_signal.rate; | ||
| 219 | p->skip = d; | ||
| 220 | } | ||
| 221 | |||
| 210 | p->x_size = p->x_size0; | 222 | p->x_size = p->x_size0; |
| 211 | while (sox_true) { | 223 | while (sox_true) { |
| 212 | if (!pixels_per_sec && p->x_size && duration) | 224 | if (!pixels_per_sec && p->x_size && duration) |
| @@ -215,7 +227,7 @@ static int start(sox_effect_t * effp) · 2 unmodified lines | |||
| 215 | p->x_size = min(5000, (int)(pixels_per_sec * duration + .5)); | 227 | p->x_size = min(5000, (int)(pixels_per_sec * duration + .5)); |
| 216 | if (!duration && effp->in_signal.length) { | 228 | if (!duration && effp->in_signal.length) { |
| 217 | duration = effp->in_signal.length / (effp->in_signal.rate * effp->in_signal.channels); | 229 | duration = effp->in_signal.length / (effp->in_signal.rate * effp->in_signal.channels); |
| 218 | duration -= p->start_time; | 230 | duration -= start_time; |
| 219 | if (duration <= 0) | 231 | if (duration <= 0) |
| 220 | duration = 1; | 232 | duration = 1; |
| 221 | continue; | 233 | continue; |