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
11021102 .B gain
11031103 effect).
11041104 .IP \fB-w\ \fIname\fR
1105−Window: Hann (default), Hamming, Bartlett, Rectangular, Kaiser. The
1105+Window: Hann (default), Hamming, Bartlett, Rectangular or Kaiser. The
11061106 spectrogram is produced using the Discrete Fourier Transform (DFT)
1107−algorithm. A significant paramater to this algorithm is the choice of
1107+algorithm. A significant parameter to this algorithm is the choice of
11081108 `window function'. By default, SoX uses the Hann window which has good
11091109 all-round frequency-resolution and dynamic-range properties. For better
11101110 frequency 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
11131113 a corresponding
11141114 .B \-z
11151115 setting.
1116−.IP \fB-s\ \fInum\fR
1117−Display style (1 - 4), default 1. There are 2 colour and 2 monochrome
1118−styles; select the style that works best with the given audio signal and
1119−your display or printer.
1116+.IP \fB-s\fR
1117+Allow slack overlapping of DFT windows.
1118+This can, in some cases, increase image sharpness and give greater adherence
1119+to the
1120+.B \-x
1121+value, but at the expense of a little spectral loss.
1122+.IP \fB-m\fR
1123+Creates a monochrome spectrogram (the default is colour).
1124+.IP \fB-l\fR
1125+Creates a `printer friendly' spectrogram with a light background (the
1126+default has a dark background).
11201127 .IP \fB-a\fR
1121−Toggle the presence of the axes lines. This is sometimes useful in
1128+Suppress the display of the axes lines. This is sometimes useful in
11221129 helping to discern artefacts at the spectrogram edges.
11231130 .IP \fB-t\ \fItext\fR
1124−Text to display above the spectrogram.
1131+Set the image title\*mtext to display above the spectrogram.
11251132 .IP \fB-c\ \fItext\fR
1126−Text to display below and to the left of the spectrogram.
1133+Set the image comment\*mtext to display below and to the left of the
1134+spectrogram.
11271135 .IP \fB-o\ \fItext\fR
11281136 Name of the spectrogram output PNG file, default `spectrogram.png'.
11291137 .RE
src/spectrogram.c+23−14
@@ -99,7 +99,7 @@ typedef struct { · 98 unmodified lines
9999 double pixels_per_sec, block_norm, max;
100100 int dB_range, gain, style, read, end, end_min, last_end;
101101 char const * out_name, * title, * comment;
102− sox_bool no_axes;
102+ sox_bool slack_overlap, no_axes;
103103 win_type_t win_type;
104104 } priv_t;
105105
@@ -136,6 +136,7 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 30 unmodified lines
136136 {
137137 priv_t * p = (priv_t *)effp->priv;
138138 int c, callers_optind = optind, callers_opterr = opterr;
139+ sox_bool monochrome = sox_false, light_background = sox_false;
139140
140141 assert(array_length(p->bit_rev_table) >= (size_t)dft_br_len(MAX_DFT_SIZE));
141142
@@ -143,25 +144,28 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 1 unmodified line
143144 p->pixels_per_sec = 100, p->y_size = 2, p->dB_range = 120;/* non-0 defaults */
144145 p->style = 1, p->out_name = "spectrogram.png", p->comment = "Created by SoX";
145146
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) {
147148 GETOPT_NUMERIC('x', pixels_per_sec, 1 , 5000)
148149 GETOPT_NUMERIC('y', y_size , 1 , 1 + MAX_DFT_SIZE_SHIFT)
149150 GETOPT_NUMERIC('z', dB_range , 40 , 180)
150151 GETOPT_NUMERIC('g', gain ,-100, 100)
151− GETOPT_NUMERIC('s', style , 1 , 4)
152152 case 'w': p->win_type = enum_option(c, window_options); break;
153+ case 's': p->slack_overlap = sox_true; break;
153154 case 't': p->title = optarg; break;
154155 case 'c': p->comment = optarg; break;
155− case 'o': p->out_name = optarg; break;
156156 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;
157160 default: sox_fail("unknown option `-%c'", optopt); return lsx_usage(effp);
158161 }
159− p->y_size -= 1, p->style -= 1;
162+ p->y_size -= 1;
163+ p->style = 2 * monochrome + light_background;
160164 argc -= optind, optind = callers_optind, opterr = callers_opterr;
161165 return argc || p->win_type == INT_MAX? lsx_usage(effp) : SOX_SUCCESS;
162166 }
163167
164−static int make_window(priv_t * p, int end)
168+static double make_window(priv_t * p, int end)
165169 {
166170 double sum = 0, * w = end < 0? p->window : p->window + end;
167171 int i, n = p->dft_size - abs(end);
@@ -178,7 +182,7 @@ static int make_window(priv_t * p, int end) · 10 unmodified lines
178182 for (i = 0; i < p->dft_size; ++i) sum += p->window[i];
179183 for (i = 0; i < p->dft_size; ++i) p->window[i] *= 2 / sum
180184 * sqr((double)n / p->dft_size); /* empirical small window adjustment */
181− return sum + .5;
185+ return sum;
182186 }
183187
184188 static int start(sox_effect_t * effp)
@@ -192,7 +196,9 @@ static int start(sox_effect_t * effp) · 7 unmodified lines
192196 }
193197 p->end = p->dft_size = DFT_BASE_SIZE << p->y_size;
194198 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;
196202 p->block_steps = effp->in_signal.rate / p->pixels_per_sec;
197203 p->step_size = p->block_steps / ceil((double)p->block_steps / p->step_size) +.5;
198204 p->block_steps = floor((double)p->block_steps / p->step_size +.5);
@@ -370,7 +376,7 @@ static unsigned char * font; · 171 unmodified lines
370376 static void print_at_(png_byte * pixels, int cols, int x, int y, int c, char const * text, int orientation)
371377 {
372378 for (;*text; ++text) {
373− int pos = (*text - ' ') * font_y;
379+ int pos = ((*text < ' ' || *text > '~'? '~' + 1 : *text) - ' ') * font_y;
374380 int i, j;
375381 for (i = 0; i < font_y; ++i) {
376382 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
387393 }
388394 }
389395
390−static int axis(double to, int max_steps, int * limit, char * * prefix)
396+static int axis(double to, int max_steps, double * limit, char * * prefix)
391397 {
392398 double scale = 1, step = 1;
393399 int i, prefix_num = 0;
@@ -422,8 +428,9 @@ static int stop(sox_effect_t * effp) · 28 unmodified lines
422428 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0,0);
423429 png_infop png_info = png_create_info_struct(png);
424430 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;
426432 char text[200], * prefix;
433+ double limit;
427434
428435 if (!file) {
429436 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
526533 " -z num Z-axis (colour) range in dB, default 120\n"
527534 " -g num Apply num dB gain; to shift Z-axis\n"
528535 " -w name Window: Hann (default), Hamming, Bartlett, Rectangular, Kaiser\n"
529− " -s num Display style (1 - 4), default 1\n"
530− " -a Toggle the presence of the axes' lines\n"
536+ " -s Slack overlap\n"
537+ " -a Suppress axes' lines\n"
531538 " -t text Title text\n"
532539 " -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",
534543 0, getopts, start, flow, drain, stop, NULL, sizeof(priv_t)};
535544 return &handler;
536545 }
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:
8+SOX=./sox # The actual sox executable
9+SSRC_PATH=/usr/local/bin # Path to the two ssrc executables
10+
11+RANGE=180
12+if [ "$1" -ne "" ]; then
13+ RANGE="$1"
14+fi
15+
16+# Temporary files
17+IN=/tmp/$0-in-$$.wav
18+OUT=/tmp/$0-out-$$.wav
19+TIME=/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
25+for 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"
46+done
47+
48+# Clean up
49+rm -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