History

more colour control

robs committed 18 years ago

Commit 784ea2a1 parent d2b295b2 files · +155 −101Browse files

Unified · Split

2 files
  1. soxeffect.7 +56 −30
  2. src/spectrogram.c +99 −71
soxeffect.7+56−30
@@ -470,7 +470,7 @@ This is just an alias for the · 469 unmodified lines
470.B vol470.B vol
471effect\*mhandy for those who prefer to work in dBs by default.471effect\*mhandy for those who prefer to work in dBs by default.
472.TP472.TP
473\fBhighpass\fR\^|\^\fBlowpass\fR [\fB-1\fR|\fB-2\fR] \fIfrequency\fR[\fBk\fR]\fR [\fRwidth\fR[\fBq\fR\^|\^\fBo\fR\^|\^\fBh\fR\^|\^\fBk\fR]]473\fBhighpass\fR\^|\^\fBlowpass\fR [\fB\-1\fR|\fB\-2\fR] \fIfrequency\fR[\fBk\fR]\fR [\fRwidth\fR[\fBq\fR\^|\^\fBo\fR\^|\^\fBh\fR\^|\^\fBk\fR]]
474Apply a high-pass or low-pass filter with 3dB point \fIfrequency\fR.474Apply a high-pass or low-pass filter with 3dB point \fIfrequency\fR.
475The filter can be either single-pole (with475The filter can be either single-pole (with
476.BR \-1 ),476.BR \-1 ),
@@ -511,7 +511,7 @@ default values if possible. Only plugins with at most one audio input · 34 unmodified lines
511and one audio output port can be used. If found, the environment varible511and one audio output port can be used. If found, the environment varible
512LADSPA_PATH will be used as search path for plugins.512LADSPA_PATH will be used as search path for plugins.
513.TP513.TP
514\fBlowpass\fR [\fB-1\fR|\fB-2\fR] \fIfrequency\fR[\fBk\fR]\fR [\fRwidth\fR[\fBq\fR\^|\^\fBo\fR\^|\^\fBh\fR\^|\^\fBk\fR]]514\fBlowpass\fR [\fB\-1\fR|\fB\-2\fR] \fIfrequency\fR[\fBk\fR]\fR [\fRwidth\fR[\fBq\fR\^|\^\fBo\fR\^|\^\fBh\fR\^|\^\fBk\fR]]
515Apply a low-pass filter.515Apply a low-pass filter.
516See the description of the \fBhighpass\fR effect for details.516See the description of the \fBhighpass\fR effect for details.
517.TP517.TP
@@ -634,7 +634,7 @@ using a pipe, e.g. · 116 unmodified lines
634 sox noisy.au -n trim 0 1 noiseprof | play noisy.au noisered634 sox noisy.au -n trim 0 1 noiseprof | play noisy.au noisered
635.EE635.EE
636.TP636.TP
637\fBnorm\fR [\fB-i\fR] [\fIlevel\fR]637\fBnorm\fR [\fB\-i\fR] [\fIlevel\fR]
638Normalise audio to 0dB FSD or to a given level relative to 0dB.638Normalise audio to 0dB FSD or to a given level relative to 0dB.
639Requires temporary file space to store the audio to be normalised.639Requires temporary file space to store the audio to be normalised.
640.SP640.SP
@@ -761,7 +761,7 @@ is the percentage of the audio band that is preserved (based on the 3dB point) · 120 unmodified lines
761during sample rate conversion, and761during sample rate conversion, and
762.B Rej dB762.B Rej dB
763is the level of noise rejection.763is the level of noise rejection.
764The default quality level is `high' (\fB-h\fR).764The default quality level is `high' (\fB\-h\fR).
765.SP765.SP
766See also766See also
767.BR resample ,767.BR resample ,
@@ -918,7 +918,7 @@ Requires temporary file space to store the audio to be repeated. · 150 unmodified lines
918Note that repeating once yields two copies: the original audio and the918Note that repeating once yields two copies: the original audio and the
919repeated audio.919repeated audio.
920.TP920.TP
921\fBreverb\fR [\fB-w\fR|\fB--wet-only\fR] [\fIreverberance\fR (50%) [\fIHF-damping\fR (50%)921\fBreverb\fR [\fB\-w\fR|\fB\-\-wet-only\fR] [\fIreverberance\fR (50%) [\fIHF-damping\fR (50%)
922[\fIroom-scale\fR (100%) [\fIstereo-depth\fR (100%)922[\fIroom-scale\fR (100%) [\fIstereo-depth\fR (100%)
923.br923.br
924[\fIpre-delay\fR (0ms) [\fIwet-gain\fR (0dB)]]]]]]924[\fIpre-delay\fR (0ms) [\fIwet-gain\fR (0dB)]]]]]]
@@ -1036,8 +1036,18 @@ The spectrogram is rendered in a Portable Network Graphic (PNG) file, · 111 unmodified lines
1036and shows time in the X-axis, frequency in the Y-axis, and audio signal1036and shows time in the X-axis, frequency in the Y-axis, and audio signal
1037magnitude in the Z-axis. Z-axis values are represented by the colour1037magnitude in the Z-axis. Z-axis values are represented by the colour
1038(or intensity) of the pixels in the X-Y plane.1038(or intensity) of the pixels in the X-Y plane.
1039.SP
1040This effect supports only one channel; for multi-channel input files,
1041use either SoX's
1042.B \-c 1
1043option with the output file (to obtain a spectrogram on the mix-down),
1044or the
1045.B remix
1046.I n
1047effect to select a particular channel. Be aware though, that both of
1048these methods affect the audio in the effects chain.
1039.RS1049.RS
1040.IP \fB-x\ \fInum\fR1050.IP \fB\-x\ \fInum\fR
1041X-axis pixels/second, default 100. This controls the width of the1051X-axis pixels/second, default 100. This controls the width of the
1042spectrogram;1052spectrogram;
1043.I num1053.I num
@@ -1060,7 +1070,7 @@ effect; e.g. · 16 unmodified lines
1060 sox audio.ogg -n trim 1:00 spectrogram1070 sox audio.ogg -n trim 1:00 spectrogram
1061.EE1071.EE
1062starts the spectrogram at 1 minute through the audio.1072starts the spectrogram at 1 minute through the audio.
1063.IP \fB-y\ \fInum\fR1073.IP \fB\-y\ \fInum\fR
1064Y-axis resolution (1 - 4), default 2.1074Y-axis resolution (1 - 4), default 2.
1065This controls the height of the spectrogram;1075This controls the height of the spectrogram;
1066.I num1076.I num
@@ -1084,24 +1094,28 @@ e.g. · 17 unmodified lines
1084.EE1094.EE
1085allows detailed analysis of frequencies up to 2kHz (half the sampling1095allows detailed analysis of frequencies up to 2kHz (half the sampling
1086rate).1096rate).
1087.IP \fB-z\ \fInum\fR1097.IP \fB\-z\ \fInum\fR
1088Z-axis (colour) range in dB, default 120. This sets the dynamic-range1098Z-axis (colour) range in dB, default 120. This sets the dynamic-range
1089of the spectrogram to be \-\fInum\fR\ dBFS to 0\ dBFS.1099of the spectrogram to be \-\fInum\fR\ dBFS to 0\ dBFS.
1090.I Num1100.I Num
1091may range from 40 to 180. Decreasing dynamic-range, effectively1101may range from 20 to 180. Decreasing dynamic-range, effectively
1092increases the `contrast' of the spectrogram display, and vice versa.1102increases the `contrast' of the spectrogram display, and vice versa.
1093.IP \fB-g\ \fInum\fR1103.IP \fB\-Z\ \fInum\fR
1094Apply1104Sets the upper limit of the Z-axis in dBFS.
1095.I num1105A negative
1096dB gain (or attenuation if
1097.I num1106.I num
1098is negative) to the audio before displaying it. Appling gain or1107effectively increases the `brightness' of the spectrogram display,
1099attenuation shifts the the range of the Z-axis and effectively controls1108and vice versa.
1100the `brightness' of the spectrogram display. Note that the audio in the1109.IP \fB\-q\ \fInum\fR
1101SoX effects chain remains unaffected by this option (cf. the1110Sets the Z-axis quantisation, i.e. the number of different colours (or
1102.B gain1111intensities) in which to render Z-axis
1103effect).1112values. A small number (e.g. 4) will give a `poster'-like effect making
1104.IP \fB-w\ \fIname\fR1113it easier to discern magnitude bands of similar level. Smaller numbers
1114also usually
1115result in a smaller PNG files. The number given specifies the number of
1116colours to use inside the Z-axis range; two colours are reserved to
1117represent out-of-range values.
1118.IP \fB\-w\ \fIname\fR
1105Window: Hann (default), Hamming, Bartlett, Rectangular or Kaiser. The1119Window: Hann (default), Hamming, Bartlett, Rectangular or Kaiser. The
1106spectrogram is produced using the Discrete Fourier Transform (DFT)1120spectrogram is produced using the Discrete Fourier Transform (DFT)
1107algorithm. A significant parameter to this algorithm is the choice of1121algorithm. A significant parameter to this algorithm is the choice of
@@ -1109,30 +1123,42 @@ algorithm. A significant parameter to this algorithm is the choice of · 1 unmodified line
1109all-round frequency-resolution and dynamic-range properties. For better1123all-round frequency-resolution and dynamic-range properties. For better
1110frequency resolution (but lower dynamic-range), select a Hamming window;1124frequency resolution (but lower dynamic-range), select a Hamming window;
1111for higher dynamic-range (but poorer frequency-resolution), select a1125for higher dynamic-range (but poorer frequency-resolution), select a
1112Kaiser window. Selecting a window other than Hann will usually require1126Kaiser window. Bartlett and Rectangular windows are also available.
1127Selecting a window other than Hann will usually require
1113a corresponding 1128a corresponding
1114.B \-z1129.B \-z
1115setting.1130setting.
1116.IP \fB-s\fR1131.IP \fB\-s\fR
1117Allow slack overlapping of DFT windows.1132Allow slack overlapping of DFT windows.
1118This can, in some cases, increase image sharpness and give greater adherence1133This can, in some cases, increase image sharpness and give greater adherence
1119to the1134to the
1120.B \-x1135.B \-x
1121value, but at the expense of a little spectral loss.1136value, but at the expense of a little spectral loss.
1122.IP \fB-m\fR1137.IP \fB\-m\fR
1123Creates a monochrome spectrogram (the default is colour).1138Creates a monochrome spectrogram (the default is colour).
1124.IP \fB-l\fR1139.IP \fB\-h\fR
1140Selects a high-colour palette\*mless visually pleasing than the default
1141colour palette, but may make it easier to differentiate different levels.
1142Also works with
1143.B \-m
1144to create a hybrid monochrome/colour palette.
1145.IP \fB\-p\ \fInum\fR
1146Permute the colours in a colour or hybrid palette.
1147The
1148.I num
1149parameter (from 1 to 6) selects the permutation.
1150.IP \fB\-l\fR
1125Creates a `printer friendly' spectrogram with a light background (the1151Creates a `printer friendly' spectrogram with a light background (the
1126default has a dark background).1152default has a dark background).
1127.IP \fB-a\fR1153.IP \fB\-a\fR
1128Suppress the display of the axes lines. This is sometimes useful in1154Suppress the display of the axis lines. This is sometimes useful in
1129helping to discern artefacts at the spectrogram edges.1155helping to discern artefacts at the spectrogram edges.
1130.IP \fB-t\ \fItext\fR1156.IP \fB\-t\ \fItext\fR
1131Set the image title\*mtext to display above the spectrogram.1157Set the image title\*mtext to display above the spectrogram.
1132.IP \fB-c\ \fItext\fR1158.IP \fB\-c\ \fItext\fR
1133Set the image comment\*mtext to display below and to the left of the1159Set the image comment\*mtext to display below and to the left of the
1134spectrogram.1160spectrogram.
1135.IP \fB-o\ \fItext\fR1161.IP \fB\-o\ \fItext\fR
1136Name of the spectrogram output PNG file, default `spectrogram.png'.1162Name of the spectrogram output PNG file, default `spectrogram.png'.
1137.RE1163.RE
1138For the ability to perform off-line processing of spectral data, see the1164For the ability to perform off-line processing of spectral data, see the
@@ -1291,7 +1317,7 @@ Though this effect is used to generate audio, an input file must still · 152 unmodified lines
1291be given, the characteristics of which will be used to set the1317be given, the characteristics of which will be used to set the
1292synthesised audio length, the number of channels, and the sampling rate;1318synthesised audio length, the number of channels, and the sampling rate;
1293however, since the input file's audio is not normally needed, a `null1319however, since the input file's audio is not normally needed, a `null
1294file' (with the special name \fB-n\fR) is often given instead (and the1320file' (with the special name \fB\-n\fR) is often given instead (and the
1295length specified as a parameter to \fBsynth\fR or by another given1321length specified as a parameter to \fBsynth\fR or by another given
1296effect that can has an associated length).1322effect that can has an associated length).
1297.SP1323.SP
src/spectrogram.c+99−71
@@ -89,18 +89,16 @@ static enum_item const window_options[] = { · 88 unmodified lines
89 89
90typedef struct {90typedef struct {
91 int y_size, dft_size, rows, cols, step_size, block_steps, block_num;91 int y_size, dft_size, rows, cols, step_size, block_steps, block_num;
92 double buf[MAX_DFT_SIZE];
93 double dft_buf[MAX_DFT_SIZE];
94 double window[MAX_DFT_SIZE];
95 int bit_rev_table[100]; /* For Ooura fft */
96 double sin_cos_table[dft_sc_len(MAX_DFT_SIZE)]; /* ditto */
97 double magnitudes[(MAX_DFT_SIZE >> 1) + 1];
98 float * dBfs;
99 double pixels_per_sec, block_norm, max;
100 int dB_range, gain, style, read, end, end_min, last_end;92 int dB_range, gain, style, read, end, end_min, last_end;
93 int spectrum_points, perm;
101 char const * out_name, * title, * comment;94 char const * out_name, * title, * comment;
102 sox_bool slack_overlap, no_axes;95 sox_bool high_colour, slack_overlap, no_axes, truncated;
103 win_type_t win_type;96 win_type_t win_type;
97 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];
99 int bit_rev_table[100]; /* For Ooura fft */
100 double sin_cos_table[dft_sc_len(MAX_DFT_SIZE)]; /* ditto */
101 float * dBfs;
104} priv_t;102} priv_t;
105 103
106#define GETOPT_NUMERIC(ch, name, min, max) case ch:{ \104#define GETOPT_NUMERIC(ch, name, min, max) case ch:{ \
@@ -142,13 +140,16 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 35 unmodified lines
142 140
143 --argv, ++argc, optind = 1, opterr = 0; /* re-jig for getopt */141 --argv, ++argc, optind = 1, opterr = 0; /* re-jig for getopt */
144 p->pixels_per_sec = 100, p->y_size = 2, p->dB_range = 120;/* non-0 defaults */142 p->pixels_per_sec = 100, p->y_size = 2, p->dB_range = 120;/* non-0 defaults */
143 p->spectrum_points = 249, p->perm = 1;
145 p->style = 1, p->out_name = "spectrogram.png", p->comment = "Created by SoX";144 p->style = 1, p->out_name = "spectrogram.png", p->comment = "Created by SoX";
146 145
147 while ((c = getopt(argc, argv, "+x:y:z:g:w:st:c:amlo:")) != -1) switch (c) {146 while ((c = getopt(argc, argv, "+x:y:z:Z:q:p:w:st:c:amlho:")) != -1) switch (c) {
148 GETOPT_NUMERIC('x', pixels_per_sec, 1 , 5000)147 GETOPT_NUMERIC('x', pixels_per_sec, 1 , 5000)
149 GETOPT_NUMERIC('y', y_size , 1 , 1 + MAX_DFT_SIZE_SHIFT)148 GETOPT_NUMERIC('y', y_size , 1 , 1 + MAX_DFT_SIZE_SHIFT)
150 GETOPT_NUMERIC('z', dB_range , 40 , 180)149 GETOPT_NUMERIC('z', dB_range , 20 , 180)
151 GETOPT_NUMERIC('g', gain ,-100, 100)150 GETOPT_NUMERIC('Z', gain ,-100, 100)
151 GETOPT_NUMERIC('q', spectrum_points, 0 , p->spectrum_points)
152 GETOPT_NUMERIC('p', perm , 1 , 6)
152 case 'w': p->win_type = enum_option(c, window_options); break;153 case 'w': p->win_type = enum_option(c, window_options); break;
153 case 's': p->slack_overlap = sox_true; break;154 case 's': p->slack_overlap = sox_true; break;
154 case 't': p->title = optarg; break;155 case 't': p->title = optarg; break;
@@ -156,11 +157,14 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 1 unmodified line
156 case 'a': p->no_axes = sox_true; break;157 case 'a': p->no_axes = sox_true; break;
157 case 'm': monochrome = sox_true; break;158 case 'm': monochrome = sox_true; break;
158 case 'l': light_background = sox_true; break;159 case 'l': light_background = sox_true; break;
160 case 'h': p->high_colour = sox_true; break;
159 case 'o': p->out_name = optarg; break;161 case 'o': p->out_name = optarg; break;
160 default: sox_fail("unknown option `-%c'", optopt); return lsx_usage(effp);162 default: sox_fail("unknown option `-%c'", optopt); return lsx_usage(effp);
161 }163 }
162 p->y_size -= 1;164 p->gain = - p->gain;
165 --p->y_size, --p->perm;
163 p->style = 2 * monochrome + light_background;166 p->style = 2 * monochrome + light_background;
167 p->spectrum_points += 2;
164 argc -= optind, optind = callers_optind, opterr = callers_opterr;168 argc -= optind, optind = callers_optind, opterr = callers_opterr;
165 return argc || p->win_type == INT_MAX? lsx_usage(effp) : SOX_SUCCESS;169 return argc || p->win_type == INT_MAX? lsx_usage(effp) : SOX_SUCCESS;
166}170}
@@ -219,6 +223,7 @@ static int do_column(sox_effect_t * effp) · 52 unmodified lines
219 223
220 if (p->cols == MAX_COLS) {224 if (p->cols == MAX_COLS) {
221 sox_warn("PNG truncated at %g seconds", (double)MAX_COLS * p->step_size * p->block_steps / effp->in_signal.rate);225 sox_warn("PNG truncated at %g seconds", (double)MAX_COLS * p->step_size * p->block_steps / effp->in_signal.rate);
226 p->truncated = sox_true;
222 return SOX_EOF;227 return SOX_EOF;
223 }228 }
224 ++p->cols;229 ++p->cols;
@@ -275,7 +280,7 @@ static int drain(sox_effect_t * effp, sox_sample_t * obuf_, sox_size_t * osamp) · 50 unmodified lines
275{280{
276 priv_t * p = (priv_t *)effp->priv;281 priv_t * p = (priv_t *)effp->priv;
277 282
278 if (p->cols != MAX_COLS) {283 if (!p->truncated) {
279 sox_sample_t * ibuf = calloc(p->dft_size, sizeof(*ibuf));284 sox_sample_t * ibuf = calloc(p->dft_size, sizeof(*ibuf));
280 sox_sample_t * obuf = calloc(p->dft_size, sizeof(*obuf));285 sox_sample_t * obuf = calloc(p->dft_size, sizeof(*obuf));
281 sox_size_t isamp = (p->dft_size - p->step_size) / 2;286 sox_size_t isamp = (p->dft_size - p->step_size) / 2;
@@ -298,52 +303,72 @@ static int drain(sox_effect_t * effp, sox_sample_t * obuf_, sox_size_t * osamp) · 16 unmodified lines
298 return SOX_SUCCESS;303 return SOX_SUCCESS;
299}304}
300 305
301#define spectrum_points (1 + 250)306enum {Background, Text, Labels, Grid, fixed_palette};
302enum {Background = spectrum_points, Text, Labels, Grid, palette_size};
303 307
304static unsigned colour(double x, int range)308static unsigned colour(priv_t const * p, double x)
305{309{
306 x = range_limit(x, -range, 0);310 unsigned c = x < -p->dB_range? 0 : x >= 0? p->spectrum_points - 1 :
307 return (1 + x / range) * (spectrum_points - 1) + .5;311 1 + (1 + x / p->dB_range) * (p->spectrum_points - 2);
312 return fixed_palette + c;
308}313}
309 314
310static void make_palette(png_byte * palette, int style)315static void make_palette(priv_t const * p, png_color * palette)
311{316{
312 int i, j, at;317 int i;
313 for (i = j = 0; j < spectrum_points; i += 3, ++j) {318
314 double r, g, b, x = (double)j / (spectrum_points - 1);319 if (p->style & 1) {
315 if (style > 1)320 memcpy(palette++, (p->style & 2)? "\337\337\337":"\335\330\320", 3);
316 palette[i+2] = palette[i+1] = palette[i+0] = style == 2? j : 255 - j;321 memcpy(palette++, "\0\0\0" , 3);
317 else {322 memcpy(palette++, "\077\077\077", 3);
318 at = style? (spectrum_points - 1) * 3 - i : i;323 memcpy(palette++, "\077\077\077", 3);
319 if (x < .16) r = 0;324 } else {
320 else if (x < .72) r = .99 * sin((x - .16) / .56 * M_PI / 2);325 memcpy(palette++, "\0\0\0" , 3);
321 else r = .01 * (x - .72) / .28 + .99;326 memcpy(palette++, "\377\377\377", 3);
322 if (x < .52) g = 0;327 memcpy(palette++, "\277\277\277", 3);
323 else if (x < .86) g = .99 * .5 * (1 - cos((x - .52) / .34 * M_PI));328 memcpy(palette++, "\177\177\177", 3);
324 else g = .01 * (x - .86) / .14 + .99;
325 if (x < .34) b = .5 * sin((x - .00) / .34 * M_PI / 2);
326 else if (x < .63) b = .5 * .5 * (1 + cos((x - .34) / .29 * M_PI));
327 else b = (1 - cos((x - .63) / .37 * M_PI / 2));
328 palette[at + 0] = r * 255 + .5;
329 palette[at + 1] = g * 255 + .5;
330 palette[at + 2] = b * 255 + .5;
331 }
332 }329 }
333 i = spectrum_points * 3;330 for (i = 0; i < p->spectrum_points; ++i) {
334 switch (style) {331 double c[3] , x = (double)i / (p->spectrum_points - 1);
335 case 0: case 2:332 int at = (p->style & 1)? p->spectrum_points - 1 - i : i;
336 memcpy(palette + i, "\0\0\0" , 3), i+= 3;333 if (p->style > 1) {
337 memcpy(palette + i, "\377\377\377", 3), i+= 3;334 c[2] = c[1] = c[0] = x;
338 memcpy(palette + i, "\277\277\277", 3), i+= 3;335 if (p->high_colour) {
339 memcpy(palette + i, "\177\177\177", 3), i+= 3;336 c[(1 + p->perm) % 3] = x < .4? 0 : 5 / 3. * (x - .4);
340 return;337 if (p->perm < 3)
341 case 1: memcpy(palette + i, "\335\330\320", 3), i+= 3; break;338 c[(2 + p->perm) % 3] = x < .4? 0 : 5 / 3. * (x - .4);
342 default: memcpy(palette + i, "\337\337\337", 3), i+= 3;339 }
340 palette[at].red = .5 + 255 * c[0];
341 palette[at].green= .5 + 255 * c[1];
342 palette[at].blue = .5 + 255 * c[2];
343 continue;
344 }
345 if (p->high_colour) {
346 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}};
348 int j, phase_num = min(6, x * 7);
349 for (j = 0; j < 3; ++j) switch (states[j][phase_num]) {
350 case 0: c[j] = 0; break;
351 case 1: c[j] = 1; break;
352 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;
354 case 4: c[j] = 7 * x - phase_num; break;
355 case 5: c[j] = 1 - (7 * x - phase_num); break;
356 }
357 } else {
358 if (x < .16) c[0] = 0;
359 else if (x < .72) c[0] = .99 * sin((x - .16) / .56 * M_PI / 2);
360 else c[0] = .01 * (x - .72) / .28 + .99;
361 if (x < .52) c[1] = 0;
362 else if (x < .86) c[1] = .99 * .5 * (1 - cos((x - .52) / .34 * M_PI));
363 else c[1] = .01 * (x - .86) / .14 + .99;
364 if (x < .34) c[2] = .5 * sin((x - .00) / .34 * M_PI / 2);
365 else if (x < .63) c[2] = .5 * .5 * (1 + cos((x - .34) / .29 * M_PI));
366 else c[2] = (1 - cos((x - .63) / .37 * M_PI / 2));
367 }
368 palette[at].red = .5 + 255 * c[p->perm % 3];
369 palette[at].green= .5 + 255 * c[(1 + p->perm + (p->perm % 2)) % 3];
370 palette[at].blue = .5 + 255 * c[(2 + p->perm - (p->perm % 2)) % 3];
343 }371 }
344 memcpy(palette + i, "\0\0\0" , 3), i+= 3;
345 memcpy(palette + i, "\077\077\077", 3), i+= 3;
346 memcpy(palette + i, "\077\077\077", 3), i+= 3;
347}372}
348 373
349static const Bytef fixed[] =374static const Bytef fixed[] =
@@ -405,7 +430,7 @@ static int axis(double to, int max_steps, double * limit, char * * prefix) · 55 unmodified lines
405 scale = pow(10., -3. * prefix_num);430 scale = pow(10., -3. * prefix_num);
406 }431 }
407 *prefix = "pnum-kMGTPE" + prefix_num + (prefix_num? 4 : 11);432 *prefix = "pnum-kMGTPE" + prefix_num + (prefix_num? 4 : 11);
408 *limit = to * scale + .5;433 *limit = to * scale;
409 return step * scale + .5;434 return step * scale + .5;
410}435}
411 436
@@ -427,7 +452,7 @@ static int stop(sox_effect_t * effp) · 15 unmodified lines
427 png_bytepp png_rows = malloc(rows * sizeof(*png_rows));452 png_bytepp png_rows = malloc(rows * sizeof(*png_rows));
428 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0,0);453 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0,0);
429 png_infop png_info = png_create_info_struct(png);454 png_infop png_info = png_create_info_struct(png);
430 png_byte palette[palette_size * 3];455 png_color palette[256];
431 int i, j, step, tick_len = 2 + do_frame;456 int i, j, step, tick_len = 2 + do_frame;
432 char text[200], * prefix;457 char text[200], * prefix;
433 double limit;458 double limit;
@@ -443,10 +468,10 @@ static int stop(sox_effect_t * effp) · 9 unmodified lines
443 sox_debug("signal-max=%g", p->max);468 sox_debug("signal-max=%g", p->max);
444 font = malloc(font_len);469 font = malloc(font_len);
445 assert(uncompress(font, &font_len, fixed, sizeof(fixed)-1) == Z_OK);470 assert(uncompress(font, &font_len, fixed, sizeof(fixed)-1) == Z_OK);
446 make_palette(palette, p->style);471 make_palette(p, palette);
447 memset(pixels, Background, cols * rows * sizeof(*pixels));472 memset(pixels, Background, cols * rows * sizeof(*pixels));
448 png_init_io(png, file);473 png_init_io(png, file);
449 png_set_PLTE(png, png_info, (png_colorp)palette, palette_size);474 png_set_PLTE(png, png_info, palette, fixed_palette + p->spectrum_points);
450 png_set_IHDR(png, png_info, (size_t)cols, (size_t)rows, 8,475 png_set_IHDR(png, png_info, (size_t)cols, (size_t)rows, 8,
451 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,476 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
452 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);477 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
@@ -461,7 +486,7 @@ static int stop(sox_effect_t * effp) · 8 unmodified lines
461 /* Spectrogram */486 /* Spectrogram */
462 for (j = 0; j < p->rows; ++j) {487 for (j = 0; j < p->rows; ++j) {
463 for (i = 0; i < p->cols; ++i)488 for (i = 0; i < p->cols; ++i)
464 pixel(left + i, below + j) = colour(p->dBfs[i*p->rows + j], p->dB_range);489 pixel(left + i, below + j) = colour(p, p->dBfs[i*p->rows + j]);
465 if (do_frame) /* Frame verticals */490 if (do_frame) /* Frame verticals */
466 pixel(left - 1, below + j) = pixel(left + p->cols,below + j) = Grid;491 pixel(left - 1, below + j) = pixel(left + p->cols,below + j) = Grid;
467 }492 }
@@ -503,7 +528,7 @@ static int stop(sox_effect_t * effp) · 35 unmodified lines
503 /* Z-axis */528 /* Z-axis */
504 print_at(cols - right - 2 - font_X, below - 13, Text, "dBFS");/* Axis label */529 print_at(cols - right - 2 - font_X, below - 13, Text, "dBFS");/* Axis label */
505 for (j = 0; j < p->rows; ++j) { /* Spectrum */530 for (j = 0; j < p->rows; ++j) { /* Spectrum */
506 png_byte b = colour(p->dB_range * (j / (p->rows - 1.) - 1), p->dB_range);531 png_byte b = colour(p, p->dB_range * (j / (p->rows - 1.) - 1));
507 for (i = 0; i < spectrum_width; ++i)532 for (i = 0; i < spectrum_width; ++i)
508 pixel(cols - right - 1 - i, below + j) = b;533 pixel(cols - right - 1 - i, below + j) = b;
509 }534 }
@@ -528,18 +553,21 @@ sox_effect_handler_t const * sox_spectrogram_effect_fn(void) · 18 unmodified lines
528{553{
529 static sox_effect_handler_t handler = {554 static sox_effect_handler_t handler = {
530 "spectrogram", "[options]\n"555 "spectrogram", "[options]\n"
531 " -x num X-axis pixels/second, default 100\n"556 "\t-x num\tX-axis pixels/second, default 100\n"
532 " -y num Y-axis resolution (1 - 4), default 2\n"557 "\t-y num\tY-axis resolution (1 - 4), default 2\n"
533 " -z num Z-axis (colour) range in dB, default 120\n"558 "\t-z num\tZ-axis range in dB, default 120\n"
534 " -g num Apply num dB gain; to shift Z-axis\n"559 "\t-Z num\tZ-axis maximum in dBFS, default 0\n"
535 " -w name Window: Hann (default), Hamming, Bartlett, Rectangular, Kaiser\n"560 "\t-q num\tZ-axis quantisation, default 249\n"
536 " -s Slack overlap\n"561 "\t-w name\tWindow: Hann (default), Hamming, Bartlett, Rectangular, Kaiser\n"
537 " -a Suppress axes' lines\n"562 "\t-s\tSlack overlap\n"
538 " -t text Title text\n"563 "\t-a\tSuppress axis lines\n"
539 " -c text Comment text\n"564 "\t-l\tLight background\n"
540 " -l Light background\n"565 "\t-m\tMonochrome\n"
541 " -m Monochrome display\n"566 "\t-h\tHigh colour\n"
542 " -o text output file name, default `spectrogram.png'\n",567 "\t-p num\tPermute colours\n"
568 "\t-t text\tTitle text\n"
569 "\t-c text\tComment text\n"
570 "\t-o text\toutput file name, default `spectrogram.png'\n",
543 0, getopts, start, flow, drain, stop, NULL, sizeof(priv_t)};571 0, getopts, start, flow, drain, stop, NULL, sizeof(priv_t)};
544 return &handler;572 return &handler;
545}573}

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