History

a few updates

robs committed 18 years ago

Commit 22d5cf21 parent 52f4fa03 files · +89 −23Browse files

Unified · Split

3 files
  1. soxeffect.7 +17 −9
  2. src/spectrogram.c +23 −14
  3. src/test-srcs +49 −0
soxeffect.7+17−9
@@ -1102,9 +1102,9 @@ SoX effects chain remains unaffected by this option (cf. the · 1101 unmodified lines
1102.B gain1102.B gain
1103effect).1103effect).
1104.IP \fB-w\ \fIname\fR1104.IP \fB-w\ \fIname\fR
1105Window: Hann (default), Hamming, Bartlett, Rectangular, Kaiser. The1105Window: Hann (default), Hamming, Bartlett, Rectangular or Kaiser. The
1106spectrogram is produced using the Discrete Fourier Transform (DFT)1106spectrogram is produced using the Discrete Fourier Transform (DFT)
1107algorithm. A significant paramater to this algorithm is the choice of1107algorithm. A significant parameter to this algorithm is the choice of
1108`window function'. By default, SoX uses the Hann window which has good1108`window function'. By default, SoX uses the Hann window which has good
1109all-round frequency-resolution and dynamic-range properties. For better1109all-round frequency-resolution and dynamic-range properties. For better
1110frequency resolution (but lower dynamic-range), select a Hamming window;1110frequency resolution (but lower dynamic-range), select a Hamming window;
@@ -1113,17 +1113,25 @@ Kaiser window. Selecting a window other than Hann will usually require · 2 unmodified lines
1113a corresponding 1113a corresponding
1114.B \-z1114.B \-z
1115setting.1115setting.
1116.IP \fB-s\ \fInum\fR1116.IP \fB-s\fR
1117Display style (1 - 4), default 1. There are 2 colour and 2 monochrome1117Allow slack overlapping of DFT windows.
1118styles; select the style that works best with the given audio signal and1118This can, in some cases, increase image sharpness and give greater adherence
1119your display or printer.1119to the
1120.B \-x
1121value, but at the expense of a little spectral loss.
1122.IP \fB-m\fR
1123Creates a monochrome spectrogram (the default is colour).
1124.IP \fB-l\fR
1125Creates a `printer friendly' spectrogram with a light background (the
1126default has a dark background).
1120.IP \fB-a\fR1127.IP \fB-a\fR
1121Toggle the presence of the axes lines. This is sometimes useful in1128Suppress the display of the axes lines. This is sometimes useful in
1122helping to discern artefacts at the spectrogram edges.1129helping to discern artefacts at the spectrogram edges.
1123.IP \fB-t\ \fItext\fR1130.IP \fB-t\ \fItext\fR
1124Text to display above the spectrogram.1131Set the image title\*mtext to display above the spectrogram.
1125.IP \fB-c\ \fItext\fR1132.IP \fB-c\ \fItext\fR
1126Text to display below and to the left of the spectrogram.1133Set the image comment\*mtext to display below and to the left of the
1134spectrogram.
1127.IP \fB-o\ \fItext\fR1135.IP \fB-o\ \fItext\fR
1128Name of the spectrogram output PNG file, default `spectrogram.png'.1136Name of the spectrogram output PNG file, default `spectrogram.png'.
1129.RE1137.RE
src/spectrogram.c+23−14
@@ -99,7 +99,7 @@ typedef struct { · 98 unmodified lines
99 double pixels_per_sec, block_norm, max;99 double pixels_per_sec, block_norm, max;
100 int dB_range, gain, style, read, end, end_min, last_end;100 int dB_range, gain, style, read, end, end_min, last_end;
101 char const * out_name, * title, * comment;101 char const * out_name, * title, * comment;
102 sox_bool no_axes;102 sox_bool slack_overlap, no_axes;
103 win_type_t win_type;103 win_type_t win_type;
104} priv_t;104} priv_t;
105 105
@@ -136,6 +136,7 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 30 unmodified lines
136{136{
137 priv_t * p = (priv_t *)effp->priv;137 priv_t * p = (priv_t *)effp->priv;
138 int c, callers_optind = optind, callers_opterr = opterr;138 int c, callers_optind = optind, callers_opterr = opterr;
139 sox_bool monochrome = sox_false, light_background = sox_false;
139 140
140 assert(array_length(p->bit_rev_table) >= (size_t)dft_br_len(MAX_DFT_SIZE));141 assert(array_length(p->bit_rev_table) >= (size_t)dft_br_len(MAX_DFT_SIZE));
141 142
@@ -143,25 +144,28 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 1 unmodified line
143 p->pixels_per_sec = 100, p->y_size = 2, p->dB_range = 120;/* non-0 defaults */144 p->pixels_per_sec = 100, p->y_size = 2, p->dB_range = 120;/* non-0 defaults */
144 p->style = 1, p->out_name = "spectrogram.png", p->comment = "Created by SoX";145 p->style = 1, p->out_name = "spectrogram.png", p->comment = "Created by SoX";
145 146
146 while ((c = getopt(argc, argv, "+x:y:z:g:s:w:t:c:o:a")) != -1) switch (c) {147 while ((c = getopt(argc, argv, "+x:y:z:g:w:st:c:amlo:")) != -1) switch (c) {
147 GETOPT_NUMERIC('x', pixels_per_sec, 1 , 5000)148 GETOPT_NUMERIC('x', pixels_per_sec, 1 , 5000)
148 GETOPT_NUMERIC('y', y_size , 1 , 1 + MAX_DFT_SIZE_SHIFT)149 GETOPT_NUMERIC('y', y_size , 1 , 1 + MAX_DFT_SIZE_SHIFT)
149 GETOPT_NUMERIC('z', dB_range , 40 , 180)150 GETOPT_NUMERIC('z', dB_range , 40 , 180)
150 GETOPT_NUMERIC('g', gain ,-100, 100)151 GETOPT_NUMERIC('g', gain ,-100, 100)
151 GETOPT_NUMERIC('s', style , 1 , 4)
152 case 'w': p->win_type = enum_option(c, window_options); break;152 case 'w': p->win_type = enum_option(c, window_options); break;
153 case 's': p->slack_overlap = sox_true; break;
153 case 't': p->title = optarg; break;154 case 't': p->title = optarg; break;
154 case 'c': p->comment = optarg; break;155 case 'c': p->comment = optarg; break;
155 case 'o': p->out_name = optarg; break;
156 case 'a': p->no_axes = sox_true; break;156 case 'a': p->no_axes = sox_true; break;
157 case 'm': monochrome = sox_true; break;
158 case 'l': light_background = sox_true; break;
159 case 'o': p->out_name = optarg; break;
157 default: sox_fail("unknown option `-%c'", optopt); return lsx_usage(effp);160 default: sox_fail("unknown option `-%c'", optopt); return lsx_usage(effp);
158 }161 }
159 p->y_size -= 1, p->style -= 1;162 p->y_size -= 1;
163 p->style = 2 * monochrome + light_background;
160 argc -= optind, optind = callers_optind, opterr = callers_opterr;164 argc -= optind, optind = callers_optind, opterr = callers_opterr;
161 return argc || p->win_type == INT_MAX? lsx_usage(effp) : SOX_SUCCESS;165 return argc || p->win_type == INT_MAX? lsx_usage(effp) : SOX_SUCCESS;
162}166}
163 167
164static int make_window(priv_t * p, int end)168static double make_window(priv_t * p, int end)
165{169{
166 double sum = 0, * w = end < 0? p->window : p->window + end;170 double sum = 0, * w = end < 0? p->window : p->window + end;
167 int i, n = p->dft_size - abs(end);171 int i, n = p->dft_size - abs(end);
@@ -178,7 +182,7 @@ static int make_window(priv_t * p, int end) · 10 unmodified lines
178 for (i = 0; i < p->dft_size; ++i) sum += p->window[i];182 for (i = 0; i < p->dft_size; ++i) sum += p->window[i];
179 for (i = 0; i < p->dft_size; ++i) p->window[i] *= 2 / sum183 for (i = 0; i < p->dft_size; ++i) p->window[i] *= 2 / sum
180 * sqr((double)n / p->dft_size); /* empirical small window adjustment */184 * sqr((double)n / p->dft_size); /* empirical small window adjustment */
181 return sum + .5;185 return sum;
182}186}
183 187
184static int start(sox_effect_t * effp)188static int start(sox_effect_t * effp)
@@ -192,7 +196,9 @@ static int start(sox_effect_t * effp) · 7 unmodified lines
192 }196 }
193 p->end = p->dft_size = DFT_BASE_SIZE << p->y_size;197 p->end = p->dft_size = DFT_BASE_SIZE << p->y_size;
194 p->rows = (p->dft_size >> 1) + 1;198 p->rows = (p->dft_size >> 1) + 1;
195 p->step_size = make_window(p, p->last_end = 0);199 actual = make_window(p, p->last_end = 0);
200 sox_debug("window_density=%g", actual / p->dft_size);
201 p->step_size = (p->slack_overlap? sqrt(actual * p->dft_size) : actual) + .5;
196 p->block_steps = effp->in_signal.rate / p->pixels_per_sec;202 p->block_steps = effp->in_signal.rate / p->pixels_per_sec;
197 p->step_size = p->block_steps / ceil((double)p->block_steps / p->step_size) +.5;203 p->step_size = p->block_steps / ceil((double)p->block_steps / p->step_size) +.5;
198 p->block_steps = floor((double)p->block_steps / p->step_size +.5);204 p->block_steps = floor((double)p->block_steps / p->step_size +.5);
@@ -370,7 +376,7 @@ static unsigned char * font; · 171 unmodified lines
370static void print_at_(png_byte * pixels, int cols, int x, int y, int c, char const * text, int orientation)376static void print_at_(png_byte * pixels, int cols, int x, int y, int c, char const * text, int orientation)
371{377{
372 for (;*text; ++text) {378 for (;*text; ++text) {
373 int pos = (*text - ' ') * font_y;379 int pos = ((*text < ' ' || *text > '~'? '~' + 1 : *text) - ' ') * font_y;
374 int i, j;380 int i, j;
375 for (i = 0; i < font_y; ++i) {381 for (i = 0; i < font_y; ++i) {
376 unsigned line = font[pos++];382 unsigned line = font[pos++];
@@ -387,7 +393,7 @@ static void print_at_(png_byte * pixels, int cols, int x, int y, int c, char con · 10 unmodified lines
387 }393 }
388}394}
389 395
390static int axis(double to, int max_steps, int * limit, char * * prefix)396static int axis(double to, int max_steps, double * limit, char * * prefix)
391{397{
392 double scale = 1, step = 1;398 double scale = 1, step = 1;
393 int i, prefix_num = 0;399 int i, prefix_num = 0;
@@ -422,8 +428,9 @@ static int stop(sox_effect_t * effp) · 28 unmodified lines
422 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0,0);428 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0,0);
423 png_infop png_info = png_create_info_struct(png);429 png_infop png_info = png_create_info_struct(png);
424 png_byte palette[palette_size * 3];430 png_byte palette[palette_size * 3];
425 int i, j, step, limit, tick_len = 2 + do_frame;431 int i, j, step, tick_len = 2 + do_frame;
426 char text[200], * prefix;432 char text[200], * prefix;
433 double limit;
427 434
428 if (!file) {435 if (!file) {
429 sox_fail("failed to create `%s' :(", p->out_name);436 sox_fail("failed to create `%s' :(", p->out_name);
@@ -526,11 +533,13 @@ sox_effect_handler_t const * sox_spectrogram_effect_fn(void) · 96 unmodified lines
526 " -z num Z-axis (colour) range in dB, default 120\n"533 " -z num Z-axis (colour) range in dB, default 120\n"
527 " -g num Apply num dB gain; to shift Z-axis\n"534 " -g num Apply num dB gain; to shift Z-axis\n"
528 " -w name Window: Hann (default), Hamming, Bartlett, Rectangular, Kaiser\n"535 " -w name Window: Hann (default), Hamming, Bartlett, Rectangular, Kaiser\n"
529 " -s num Display style (1 - 4), default 1\n"536 " -s Slack overlap\n"
530 " -a Toggle the presence of the axes' lines\n"537 " -a Suppress axes' lines\n"
531 " -t text Title text\n"538 " -t text Title text\n"
532 " -c text Comment text\n"539 " -c text Comment text\n"
533 " -o text Name of the spectrogram output file, default `spectrogram.png'\n",540 " -l Light background\n"
541 " -m Monochrome display\n"
542 " -o text output file name, default `spectrogram.png'\n",
534 0, getopts, start, flow, drain, stop, NULL, sizeof(priv_t)};543 0, getopts, start, flow, drain, stop, NULL, sizeof(priv_t)};
535 return &handler;544 return &handler;
536}545}
src/test-srcs+49−0
@@ -0,0 +1,49 @@
1#!/bin/sh
2
3# Sample rate conversion tests. Create a 30s sweep of 0-48kHz @ 96kHz sampling
4# rate, then use each resampler to convert it to 44.1kHz. Display the results
5# in a PNG file for each converter.
6
7# Set up the following two before running the script:
8SOX=./sox # The actual sox executable
9SSRC_PATH=/usr/local/bin # Path to the two ssrc executables
10
11RANGE=180
12if [ "$1" -ne "" ]; then
13 RANGE="$1"
14fi
15
16# Temporary files
17IN=/tmp/$0-in-$$.wav
18OUT=/tmp/$0-out-$$.wav
19TIME=/tmp/$0-time-$$.wav
20
21# Create input file
22$SOX -r96k -n -twavpcm $IN synth 30 sin 0~48k gain -1
23
24# Test each one
25for src in \
26 "polyphase" \
27 "rabbit -c0" \
28 "rabbit -c1" \
29 "rate -h" \
30 "rate -v" \
31 "resample -q" \
32 "resample -ql" \
33 "ssrc" \
34 "ssrc_hp" \
35 ; do
36 echo $src
37 case "$src" in
38 ssrc*) time -f %U -o $TIME $SSRC_PATH/$src --quiet --rate 44100 $IN $OUT;;
39 *) time -f %U -o $TIME $SOX $IN -r 44.1k $OUT $src;;
40 esac
41 t=`cat $TIME`
42 $SOX $OUT -n spectrogram \
43 -x 20 -z $RANGE -w kaiser \
44 -t " $src " -c "${t}s user time" \
45 -o "spectrogram-`echo $src | tr ' ' '_'`.png"
46done
47
48# Clean up
49rm -f $IN $OUT $TIME

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