History

clean-ups only

robs committed 18 years ago

Commit d79c8a11 parent 784ea2a3 files · +48 −35Browse files

Unified · Split

3 files
  1. soxeffect.7 +2 −1
  2. src/spectrogram.c +45 −34
  3. src/util.h +1 −0
soxeffect.7+2−1
@@ -1051,7 +1051,8 @@ these methods affect the audio in the effects chain. · 1050 unmodified lines
1051X-axis pixels/second, default 100. This controls the width of the1051X-axis pixels/second, default 100. This controls the width of the
1052spectrogram;1052spectrogram;
1053.I num1053.I num
1054can be from 1 (low time resolution) to 5000 (high time resolution). SoX1054can be from 1 (low time resolution) to 5000 (high time resolution);
1055non-integer values (e.g. 1\*d5) can be used here. SoX
1055may make a slight adjustment to the given number for processing1056may make a slight adjustment to the given number for processing
1056quantisation reasons; if so, SoX will report the actual number used1057quantisation reasons; if so, SoX will report the actual number used
1057(viewable when1058(viewable when
src/spectrogram.c+45−34
@@ -15,6 +15,11 @@ · 14 unmodified lines
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */16 */
17 17
18/* TODO
19 * o Two-channel support.
20 * o Option for a larger font (for use with image down-scaling).
21 */
22
18#ifdef NDEBUG /* Enable assert always. */23#ifdef NDEBUG /* Enable assert always. */
19#undef NDEBUG /* Must undef above assert.h or other that might include it. */24#undef NDEBUG /* Must undef above assert.h or other that might include it. */
20#endif25#endif
@@ -88,19 +93,28 @@ static enum_item const window_options[] = { · 67 unmodified lines
88 {0, 0}};93 {0, 0}};
89 94
90typedef struct {95typedef struct {
91 int y_size, dft_size, rows, cols, step_size, block_steps, block_num;96 /* Parameters */
92 int dB_range, gain, style, read, end, end_min, last_end;97 double pixels_per_sec;
93 int spectrum_points, perm;98 int y_size, dB_range, gain, spectrum_points, perm;
94 char const * out_name, * title, * comment;99 sox_bool monochrome, light_background, high_colour, slack_overlap, no_axes;
95 sox_bool high_colour, slack_overlap, no_axes, truncated;
96 win_type_t win_type;100 win_type_t win_type;
101 char const * out_name, * title, * comment;
102
103 /* Work area */
104 int WORK; /* Start of work area is marked by this dummy variable. */
105 int dft_size, step_size, block_steps, block_num, rows, cols, read;
106 int end, end_min, last_end;
107 sox_bool truncated;
97 double buf[MAX_DFT_SIZE], dft_buf[MAX_DFT_SIZE], window[MAX_DFT_SIZE];108 double buf[MAX_DFT_SIZE], dft_buf[MAX_DFT_SIZE], window[MAX_DFT_SIZE];
98 double pixels_per_sec, block_norm, max, magnitudes[(MAX_DFT_SIZE>>1) + 1];109 double block_norm, max, magnitudes[(MAX_DFT_SIZE>>1) + 1];
99 int bit_rev_table[100]; /* For Ooura fft */110 int bit_rev_table[100]; /* For Ooura fft */
100 double sin_cos_table[dft_sc_len(MAX_DFT_SIZE)]; /* ditto */111 double sin_cos_table[dft_sc_len(MAX_DFT_SIZE)]; /* ditto */
101 float * dBfs;112 float * dBfs;
102} priv_t;113} priv_t;
103 114
115#define secs(cols) \
116 ((double)(cols) * p->step_size * p->block_steps / effp->in_signal.rate)
117
104#define GETOPT_NUMERIC(ch, name, min, max) case ch:{ \118#define GETOPT_NUMERIC(ch, name, min, max) case ch:{ \
105 char * end_ptr; \119 char * end_ptr; \
106 double d = strtod(optarg, &end_ptr); \120 double d = strtod(optarg, &end_ptr); \
@@ -134,14 +148,13 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 27 unmodified lines
134{148{
135 priv_t * p = (priv_t *)effp->priv;149 priv_t * p = (priv_t *)effp->priv;
136 int c, callers_optind = optind, callers_opterr = opterr;150 int c, callers_optind = optind, callers_opterr = opterr;
137 sox_bool monochrome = sox_false, light_background = sox_false;
138 151
139 assert(array_length(p->bit_rev_table) >= (size_t)dft_br_len(MAX_DFT_SIZE));152 assert(array_length(p->bit_rev_table) >= (size_t)dft_br_len(MAX_DFT_SIZE));
140 153
141 --argv, ++argc, optind = 1, opterr = 0; /* re-jig for getopt */154 --argv, ++argc, optind = 1, opterr = 0; /* re-jig for getopt */
142 p->pixels_per_sec = 100, p->y_size = 2, p->dB_range = 120;/* non-0 defaults */155 p->pixels_per_sec = 100, p->y_size = 2, p->dB_range = 120;/* non-0 defaults */
143 p->spectrum_points = 249, p->perm = 1;156 p->spectrum_points = 249, p->perm = 1;
144 p->style = 1, p->out_name = "spectrogram.png", p->comment = "Created by SoX";157 p->out_name = "spectrogram.png", p->comment = "Created by SoX";
145 158
146 while ((c = getopt(argc, argv, "+x:y:z:Z:q:p:w:st:c:amlho:")) != -1) switch (c) {159 while ((c = getopt(argc, argv, "+x:y:z:Z:q:p:w:st:c:amlho:")) != -1) switch (c) {
147 GETOPT_NUMERIC('x', pixels_per_sec, 1 , 5000)160 GETOPT_NUMERIC('x', pixels_per_sec, 1 , 5000)
@@ -155,15 +168,14 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 7 unmodified lines
155 case 't': p->title = optarg; break;168 case 't': p->title = optarg; break;
156 case 'c': p->comment = optarg; break;169 case 'c': p->comment = optarg; break;
157 case 'a': p->no_axes = sox_true; break;170 case 'a': p->no_axes = sox_true; break;
158 case 'm': monochrome = sox_true; break;171 case 'm': p->monochrome = sox_true; break;
159 case 'l': light_background = sox_true; break;172 case 'l': p->light_background = sox_true; break;
160 case 'h': p->high_colour = sox_true; break;173 case 'h': p->high_colour = sox_true; break;
161 case 'o': p->out_name = optarg; break;174 case 'o': p->out_name = optarg; break;
162 default: sox_fail("unknown option `-%c'", optopt); return lsx_usage(effp);175 default: sox_fail("unknown option `-%c'", optopt); return lsx_usage(effp);
163 }176 }
164 p->gain = - p->gain;177 p->gain = -p->gain;
165 --p->y_size, --p->perm;178 --p->y_size, --p->perm;
166 p->style = 2 * monochrome + light_background;
167 p->spectrum_points += 2;179 p->spectrum_points += 2;
168 argc -= optind, optind = callers_optind, opterr = callers_opterr;180 argc -= optind, optind = callers_optind, opterr = callers_opterr;
169 return argc || p->win_type == INT_MAX? lsx_usage(effp) : SOX_SUCCESS;181 return argc || p->win_type == INT_MAX? lsx_usage(effp) : SOX_SUCCESS;
@@ -198,6 +210,7 @@ static int start(sox_effect_t * effp) · 28 unmodified lines
198 sox_fail("only 1 channel is supported");210 sox_fail("only 1 channel is supported");
199 return SOX_EOF;211 return SOX_EOF;
200 }212 }
213 memset(&p->WORK, 0, sizeof(*p) - field_offset(priv_t, WORK));
201 p->end = p->dft_size = DFT_BASE_SIZE << p->y_size;214 p->end = p->dft_size = DFT_BASE_SIZE << p->y_size;
202 p->rows = (p->dft_size >> 1) + 1;215 p->rows = (p->dft_size >> 1) + 1;
203 actual = make_window(p, p->last_end = 0);216 actual = make_window(p, p->last_end = 0);
@@ -222,7 +235,7 @@ static int do_column(sox_effect_t * effp) · 18 unmodified lines
222 int i;235 int i;
223 236
224 if (p->cols == MAX_COLS) {237 if (p->cols == MAX_COLS) {
225 sox_warn("PNG truncated at %g seconds", (double)MAX_COLS * p->step_size * p->block_steps / effp->in_signal.rate);238 sox_warn("PNG truncated at %g seconds", secs(p->cols));
226 p->truncated = sox_true;239 p->truncated = sox_true;
227 return SOX_EOF;240 return SOX_EOF;
228 }241 }
@@ -231,8 +244,7 @@ static int do_column(sox_effect_t * effp) · 2 unmodified lines
231 for (i = 0; i < p->rows; ++i) {244 for (i = 0; i < p->rows; ++i) {
232 double dBfs = 10 * log10(p->magnitudes[i] * p->block_norm);245 double dBfs = 10 * log10(p->magnitudes[i] * p->block_norm);
233 p->dBfs[(p->cols - 1) * p->rows + i] = dBfs + p->gain;246 p->dBfs[(p->cols - 1) * p->rows + i] = dBfs + p->gain;
234 if (dBfs > p->max)247 p->max = max(dBfs, p->max);
235 p->max = dBfs;
236 }248 }
237 memset(p->magnitudes, 0, p->rows * sizeof(*p->magnitudes));249 memset(p->magnitudes, 0, p->rows * sizeof(*p->magnitudes));
238 p->block_num = 0;250 p->block_num = 0;
@@ -289,8 +301,7 @@ static int drain(sox_effect_t * effp, sox_sample_t * obuf_, sox_size_t * osamp) · 50 unmodified lines
289 if (left_over >= p->step_size >> 1)301 if (left_over >= p->step_size >> 1)
290 isamp += p->step_size - left_over;302 isamp += p->step_size - left_over;
291 sox_debug("cols=%i left=%i end=%i", p->cols, p->read, p->end);303 sox_debug("cols=%i left=%i end=%i", p->cols, p->read, p->end);
292 p->end = 0;304 p->end = 0, p->end_min = -p->dft_size;
293 p->end_min = -p->dft_size;
294 if (flow(effp, ibuf, obuf, &isamp, &isamp) == SOX_SUCCESS && p->block_num) {305 if (flow(effp, ibuf, obuf, &isamp, &isamp) == SOX_SUCCESS && p->block_num) {
295 p->block_norm *= (double)p->block_steps / p->block_num;306 p->block_norm *= (double)p->block_steps / p->block_num;
296 do_column(effp);307 do_column(effp);
@@ -316,8 +327,8 @@ static void make_palette(priv_t const * p, png_color * palette) · 19 unmodified lines
316{327{
317 int i;328 int i;
318 329
319 if (p->style & 1) {330 if (p->light_background) {
320 memcpy(palette++, (p->style & 2)? "\337\337\337":"\335\330\320", 3);331 memcpy(palette++, (p->monochrome)? "\337\337\337":"\335\330\320", 3);
321 memcpy(palette++, "\0\0\0" , 3);332 memcpy(palette++, "\0\0\0" , 3);
322 memcpy(palette++, "\077\077\077", 3);333 memcpy(palette++, "\077\077\077", 3);
323 memcpy(palette++, "\077\077\077", 3);334 memcpy(palette++, "\077\077\077", 3);
@@ -328,9 +339,9 @@ static void make_palette(priv_t const * p, png_color * palette) · 4 unmodified lines
328 memcpy(palette++, "\177\177\177", 3);339 memcpy(palette++, "\177\177\177", 3);
329 }340 }
330 for (i = 0; i < p->spectrum_points; ++i) {341 for (i = 0; i < p->spectrum_points; ++i) {
331 double c[3] , x = (double)i / (p->spectrum_points - 1);342 double c[3], x = (double)i / (p->spectrum_points - 1);
332 int at = (p->style & 1)? p->spectrum_points - 1 - i : i;343 int at = (p->light_background)? p->spectrum_points - 1 - i : i;
333 if (p->style > 1) {344 if (p->monochrome) {
334 c[2] = c[1] = c[0] = x;345 c[2] = c[1] = c[0] = x;
335 if (p->high_colour) {346 if (p->high_colour) {
336 c[(1 + p->perm) % 3] = x < .4? 0 : 5 / 3. * (x - .4);347 c[(1 + p->perm) % 3] = x < .4? 0 : 5 / 3. * (x - .4);
@@ -345,13 +356,13 @@ static void make_palette(priv_t const * p, png_color * palette) · 8 unmodified lines
345 if (p->high_colour) {356 if (p->high_colour) {
346 static const int states[3][7] = {357 static const int states[3][7] = {
347 {4,5,0,0,2,1,1}, {0,0,2,1,1,3,2}, {4,1,1,3,0,0,2}};358 {4,5,0,0,2,1,1}, {0,0,2,1,1,3,2}, {4,1,1,3,0,0,2}};
348 int j, phase_num = min(6, x * 7);359 int j, phase_num = min(7 * x, 6);
349 for (j = 0; j < 3; ++j) switch (states[j][phase_num]) {360 for (j = 0; j < 3; ++j) switch (states[j][phase_num]) {
350 case 0: c[j] = 0; break;361 case 0: c[j] = 0; break;
351 case 1: c[j] = 1; break;362 case 1: c[j] = 1; break;
352 case 2: c[j] = sin((7 * x - phase_num) * M_PI / 2); break;363 case 2: c[j] = sin((7 * x - phase_num) * M_PI / 2); break;
353 case 3: c[j] = cos((7 * x - phase_num) * M_PI / 2); break;364 case 3: c[j] = cos((7 * x - phase_num) * M_PI / 2); break;
354 case 4: c[j] = 7 * x - phase_num; break;365 case 4: c[j] = 7 * x - phase_num; break;
355 case 5: c[j] = 1 - (7 * x - phase_num); break;366 case 5: c[j] = 1 - (7 * x - phase_num); break;
356 }367 }
357 } else {368 } else {
@@ -447,13 +458,12 @@ static int stop(sox_effect_t * effp) · 89 unmodified lines
447 uLong font_len = 96 * font_y;458 uLong font_len = 96 * font_y;
448 int rows = below + p->rows + 30 + 20 * !!p->title;459 int rows = below + p->rows + 30 + 20 * !!p->title;
449 int cols = left + p->cols + between + spectrum_width + right;460 int cols = left + p->cols + between + spectrum_width + right;
450 sox_bool do_frame = !p->no_axes;
451 png_byte * pixels = malloc(cols * rows * sizeof(*pixels));461 png_byte * pixels = malloc(cols * rows * sizeof(*pixels));
452 png_bytepp png_rows = malloc(rows * sizeof(*png_rows));462 png_bytepp png_rows = malloc(rows * sizeof(*png_rows));
453 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0,0);463 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0,0);
454 png_infop png_info = png_create_info_struct(png);464 png_infop png_info = png_create_info_struct(png);
455 png_color palette[256];465 png_color palette[256];
456 int i, j, step, tick_len = 2 + do_frame;466 int i, j, step, tick_len = 3 - p->no_axes;
457 char text[200], * prefix;467 char text[200], * prefix;
458 double limit;468 double limit;
459 469
@@ -475,7 +485,7 @@ static int stop(sox_effect_t * effp) · 15 unmodified lines
475 png_set_IHDR(png, png_info, (size_t)cols, (size_t)rows, 8,485 png_set_IHDR(png, png_info, (size_t)cols, (size_t)rows, 8,
476 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,486 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
477 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);487 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
478 for (j = 0; j < rows; ++j)488 for (j = 0; j < rows; ++j) /* Put (0,0) at bottom-left of PNG */
479 png_rows[rows - 1 - j] = (png_bytep)(pixels + j * cols);489 png_rows[rows - 1 - j] = (png_bytep)(pixels + j * cols);
480 490
481 if (p->title && (i = (int)strlen(p->title) * font_X) < cols + 1) /* Title */491 if (p->title && (i = (int)strlen(p->title) * font_X) < cols + 1) /* Title */
@@ -487,20 +497,20 @@ static int stop(sox_effect_t * effp) · 5 unmodified lines
487 for (j = 0; j < p->rows; ++j) {497 for (j = 0; j < p->rows; ++j) {
488 for (i = 0; i < p->cols; ++i)498 for (i = 0; i < p->cols; ++i)
489 pixel(left + i, below + j) = colour(p, p->dBfs[i*p->rows + j]);499 pixel(left + i, below + j) = colour(p, p->dBfs[i*p->rows + j]);
490 if (do_frame) /* Frame verticals */500 if (!p->no_axes) /* Y-axis lines */
491 pixel(left - 1, below + j) = pixel(left + p->cols,below + j) = Grid;501 pixel(left - 1, below + j) = pixel(left + p->cols,below + j) = Grid;
492 }502 }
493 if (do_frame) for (i = -1; i <= p->cols; ++i) /* Frame horizontals */503 if (!p->no_axes) for (i = -1; i <= p->cols; ++i) /* X-axis lines */
494 pixel(left + i, below - 1) = pixel(left + i, below + p->rows) = Grid;504 pixel(left + i, below - 1) = pixel(left + i, below + p->rows) = Grid;
495 505
496 /* X-axis */506 /* X-axis */
497 step = axis((double)p->cols * p->step_size * p->block_steps / effp->in_signal.rate, p->cols / (font_X * 9 / 2), &limit, &prefix);507 step = axis(secs(p->cols), p->cols / (font_X * 9 / 2), &limit, &prefix);
498 sprintf(text, "Time (%.1ss)", prefix); /* Axis label */508 sprintf(text, "Time (%.1ss)", prefix); /* Axis label */
499 print_at(left + (p->cols - font_X * (int)strlen(text)) / 2, 24, Text, text);509 print_at(left + (p->cols - font_X * (int)strlen(text)) / 2, 24, Text, text);
500 for (i = 0; i <= limit; i += step) {510 for (i = 0; i <= limit; i += step) {
501 int y, x = limit? (double)i / limit * p->cols + .5 : 0;511 int y, x = limit? (double)i / limit * p->cols + .5 : 0;
502 for (y = 0; y < tick_len; ++y) /* Ticks */512 for (y = 0; y < tick_len; ++y) /* Ticks */
503 pixel(left - 1 + x, below - 1 - y) = pixel(left - 1 + x, below + p->rows + y) = Grid;513 pixel(left-1+x, below-1-y) = pixel(left-1+x, below+p->rows+y) = Grid;
504 if (step == 5 && (i%10))514 if (step == 5 && (i%10))
505 continue;515 continue;
506 sprintf(text, "%g", .1 * i); /* Tick labels */516 sprintf(text, "%g", .1 * i); /* Tick labels */
@@ -510,13 +520,14 @@ static int stop(sox_effect_t * effp) · 3 unmodified lines
510 }520 }
511 521
512 /* Y-axis */522 /* Y-axis */
513 step = axis(effp->in_signal.rate / 2, (p->rows - 1) / ((font_y * 3 + 1) >> 1), &limit, &prefix);523 step = axis(effp->in_signal.rate / 2,
524 (p->rows - 1) / ((font_y * 3 + 1) >> 1), &limit, &prefix);
514 sprintf(text, "Frequency (%.1sHz)", prefix); /* Axis label */525 sprintf(text, "Frequency (%.1sHz)", prefix); /* Axis label */
515 print_up(10, below + (p->rows - font_X * (int)strlen(text)) / 2, Text, text);526 print_up(10, below + (p->rows - font_X * (int)strlen(text)) / 2, Text, text);
516 for (i = 0; i <= limit; i += step) {527 for (i = 0; i <= limit; i += step) {
517 int x, y = limit? (double)i / limit * (p->rows - 1) + .5 : 0;528 int x, y = limit? (double)i / limit * (p->rows - 1) + .5 : 0;
518 for (x = 0; x < tick_len; ++x) /* Ticks */529 for (x = 0; x < tick_len; ++x) /* Ticks */
519 pixel(left - 1 - x, below + y) = pixel(left + p->cols + x, below + y) = Grid;530 pixel(left-1-x, below+y) = pixel(left+p->cols+x, below+y) = Grid;
520 if (step == 5 && (i%10))531 if (step == 5 && (i%10))
521 continue;532 continue;
522 sprintf(text, i?"%5g":" DC", .1 * i); /* Tick labels */533 sprintf(text, i?"%5g":" DC", .1 * i); /* Tick labels */
src/util.h+1−0
@@ -69,6 +69,7 @@ · 68 unmodified lines
69#define assert_static(e,f) enum {assert_static__##f = 1/(e)}69#define assert_static(e,f) enum {assert_static__##f = 1/(e)}
70#define range_limit(x, lower, upper) (min(max(x, lower), upper))70#define range_limit(x, lower, upper) (min(max(x, lower), upper))
71#define array_length(a) (sizeof(a)/sizeof(a[0]))71#define array_length(a) (sizeof(a)/sizeof(a[0]))
72#define field_offset(type, field) ((unsigned)&(((type *)0)->field))
72#define sqr(a) ((a) * (a))73#define sqr(a) ((a) * (a))
73 74
74#define dB_to_linear(x) exp((x) * M_LN10 * 0.05)75#define dB_to_linear(x) exp((x) * M_LN10 * 0.05)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t