Unified · Split
| @@ -26,7 +26,6 @@ · 25 unmodified lines | ||
| 26 | 26 | # --------------------------------------------------------------------------- |
| 27 | 27 | |
| 28 | 28 | SOX=../src/sox |
| 29 | −PLAY=../src/play | |
| 30 | 29 | |
| 31 | 30 | rm -f 2tones.ul # Make sure we append to a file that's initially empty |
| 32 | 31 | |
| @@ -45,4 +44,4 @@ done · 12 unmodified lines | ||
| 45 | 44 | $SOX -c 1 -r 8000 alert.ul alert.au # Add a file header |
| 46 | 45 | rm 2tones.ul alert.ul # Tidy up intermediate files |
| 47 | 46 | |
| 48 | −$PLAY alert.au | |
| 47 | +$SOX alert.au -d | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | #!/bin/sh |
| 2 | 2 | |
| 3 | −# SoX script: synth.sh (c) 2008 robs@users.sourceforge.net | |
| 3 | +# SoX script: synth.sh (c) 2008-9 robs@users.sourceforge.net | |
| 4 | 4 | # |
| 5 | 5 | # This program is free software; you can redistribute it and/or modify it |
| 6 | 6 | # under the terms of the GNU General Public License as published by the |
| @@ -17,7 +17,6 @@ · 10 unmodified lines | ||
| 17 | 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | 18 | |
| 19 | 19 | sox=../src/sox |
| 20 | −play=../src/play | |
| 21 | 20 | |
| 22 | 21 | G0="pl %-26 pl %-19 pl %-14 pl %-10 pl %-7 pl %-2" |
| 23 | 22 | A0="pl %-24 pl %-17 pl %-12 pl %-8 pl %-5 pl %0" |
| @@ -26,12 +25,22 @@ D0="pl %-24 pl %-19 pl %-12 pl %-7 pl %-3 pl %0" · 2 unmodified lines | ||
| 26 | 25 | E0="pl %-22 pl %-17 pl %-10 pl %-5 pl %-1 pl %2" |
| 27 | 26 | Bb0="pl %-23 pl %-16 pl %-11 pl %-7 pl %-4 pl %1" |
| 28 | 27 | |
| 29 | −o="overdrive 40 gain -8" | |
| 30 | −e="delay 0 .02 .04 .06 .08 .1 remix - $o fade 0" | |
| 31 | −s="$sox -q -n -p synth 0 0 0 80 87" | |
| 32 | −l="$sox -q -n -p synth 0 0 0 80 0 0" | |
| 28 | +o="overdrive 27 gain -11" | |
| 29 | +e="delay 0 .02 .04 .06 .08 .1 remix - overdrive 33 gain -8 fade 0" | |
| 30 | +s="$sox -q -n -p synth 0 0 1 60 90" | |
| 31 | +l="$sox -q -n -p synth 0 0 0 50 20" | |
| 33 | 32 | |
| 34 | −$play -m -v .8 \ | |
| 33 | +b="$sox -np synth 0 0 0 30 20 pl" | |
| 34 | +c3="fade h 0 .75" | |
| 35 | +c="fade h 0 .25" | |
| 36 | +cs="fade h 0 .25 .05" | |
| 37 | +m="fade h 0 .5" | |
| 38 | +sb="fade h 0 1" | |
| 39 | +r="$sox -np trim 0 .25" | |
| 40 | +r2="$sox -np trim 0 .5" | |
| 41 | +r3="$sox -np trim 0 .75" | |
| 42 | + | |
| 43 | +$sox -m -v .8 \ | |
| 35 | 44 | "|$sox \ |
| 36 | 45 | \"|$sox -n -p synth noise fade 0 .5 .48 trim 0 .15\" \ |
| 37 | 46 | \"|$sox -n -p synth noise fade h 0 .26 .11 gain -35 lowpass -1 12k\" \ |
| @@ -63,15 +72,15 @@ equalizer 1500 10 8 pad 0 .21 remix 1 1 reverb 10 repeat 56" \ · 25 unmodified lines | ||
| 63 | 72 | \"|$l pl %10 $o trim 0 .5 bend .2,-300,.1\" \ |
| 64 | 73 | \"|$l pl %5 $o trim 0 .5 bend .2,-200,.1\" \ |
| 65 | 74 | \"|$l pl %0 $o fade 0 .55 .1 bend .2,-200,.1\" \ |
| 66 | −\"|$l pl %0 $o fade 0 2 .1\" \ | |
| 75 | +\"|$l pl %0 $o fade h 0 2 .5\" \ | |
| 67 | 76 | \"|$sox -n -p trim 0 3.95\" \ |
| 68 | 77 | \"|$l pl %12 $o trim 0 .5 bend .2,-200,.1\" \ |
| 69 | 78 | \"|$l pl %12 $o trim 0 .5 bend .2,-200,.1\" \ |
| 70 | 79 | \"|$l pl %12 $o fade 0 .8 .1 bend .2,-200,.1\" \ |
| 71 | 80 | \"|$l pl %12 $o trim 0 .3 bend .1,-200,.1\" \ |
| 72 | −\"|$l pl %12 $o trim 0 1.95 bend .3,-50,1\" \ | |
| 73 | −\"|$l pl %10 $o trim 0 2 bend .3,-50,1\" \ | |
| 74 | −\"|$l pl %9 $o trim 0 2 gain -3\" \ | |
| 81 | +\"|$l pl %12 $o fade 0 1.95 .6 bend .0,-50,1.75 gain 3\" \ | |
| 82 | +\"|$l pl %10 $o fade 0 2 .6 bend .0,-50,1.9\" \ | |
| 83 | +\"|$l pl %9 $o trim 0 2 gain -1\" \ | |
| 75 | 84 | \"|$l pl %8 $o fade h 0 1 .3\" \ |
| 76 | 85 | \"|$l pl %8 $o fade h 0 1 .1 gain 1.5\" \ |
| 77 | 86 | \"|$l pl %2 pl %7 delay 0 .02 remix - $o trim 0 .25\" \ |
| @@ -83,4 +92,100 @@ equalizer 1500 10 8 pad 0 .21 remix 1 1 reverb 10 repeat 56" \ · 5 unmodified lines | ||
| 83 | 92 | \"|$l pl %2 pl %7 delay 0 .02 remix - $o trim 0 .25\" \ |
| 84 | 93 | \"|$l pl %-5 $o trim 0 .25\" \ |
| 85 | 94 | \"|$l pl %2 pl %7 delay 0 .02 remix - $o fade h 0 6 6\" \ |
| 86 | −-p gain -4 remix 1 1 flanger" | |
| 95 | +-p gain -4 remix 1 1 flanger" \ | |
| 96 | +"|$sox \ | |
| 97 | +\"|$sox -n -p trim 0 1.5\" \ | |
| 98 | +\"|$b G1 $m contrast\" \ | |
| 99 | +\"|$b A1 $c3 contrast\" \ | |
| 100 | +\"|$b G#1 $c\" \ | |
| 101 | +\"|$b A1 $c3\" \ | |
| 102 | +\"|$r\" \ | |
| 103 | +\ | |
| 104 | +\"|$b C2 $cs\" \ | |
| 105 | +\"|$b C2 $cs\" \ | |
| 106 | +\"|$r\" \ | |
| 107 | +\"|$b B1 $cs\" \ | |
| 108 | +\"|$b C2 $c3\" \ | |
| 109 | +\"|$r\" \ | |
| 110 | +\ | |
| 111 | +\"|$b D2 $cs\" \ | |
| 112 | +\"|$b D2 $cs\" \ | |
| 113 | +\"|$r\" \ | |
| 114 | +\"|$b C#2 $cs\" \ | |
| 115 | +\"|$b D2 $c\" \ | |
| 116 | +\"|$b C#2 $m\" \ | |
| 117 | +\"|$r\" \ | |
| 118 | +\ | |
| 119 | +\"|$b D2 $cs\" \ | |
| 120 | +\"|$b D2 $cs\" \ | |
| 121 | +\"|$r\" \ | |
| 122 | +\"|$b C#2 $cs\" \ | |
| 123 | +\"|$b D2 $c\" \ | |
| 124 | +\"|$b C#2 $c\" \ | |
| 125 | +\"|$b D2 $c\" \ | |
| 126 | +\"|$b E2 $c\" \ | |
| 127 | +\ | |
| 128 | +\"|$b A1 $c3 contrast\" \ | |
| 129 | +\"|$b B1 $c\" \ | |
| 130 | +\"|$b A1 $c\" \ | |
| 131 | +\"|$b G#1 $c\" \ | |
| 132 | +\"|$b A1 $c\" \ | |
| 133 | +\"|$b B1 $c\" \ | |
| 134 | +\ | |
| 135 | +\"|$b C2 $c3\" \ | |
| 136 | +\"|$b B1 $c\" \ | |
| 137 | +\"|$b C2 $c\" \ | |
| 138 | +\"|$b D2 $c\" \ | |
| 139 | +\"|$b C2 $c\" \ | |
| 140 | +\"|$b B1 $c\" \ | |
| 141 | +\ | |
| 142 | +\"|$b D2 $c3\" \ | |
| 143 | +\"|$b E2 $c\" \ | |
| 144 | +\"|$b D2 $c\" \ | |
| 145 | +\"|$b C#2 $c\" \ | |
| 146 | +\"|$b D2 $c\" \ | |
| 147 | +\"|$b E2 $c\" \ | |
| 148 | +\ | |
| 149 | +\"|$b D2 $c3\" \ | |
| 150 | +\"|$b C#2 $c\" \ | |
| 151 | +\"|$b D2 $c\" \ | |
| 152 | +\"|$b E2 $c\" \ | |
| 153 | +\"|$b D2 $c\" \ | |
| 154 | +\"|$b C#2 $c\" \ | |
| 155 | +\ | |
| 156 | +\"|$b A1 $cs\" \ | |
| 157 | +\"|$b A1 $cs\" \ | |
| 158 | +\"|$r\" \ | |
| 159 | +\"|$b G#1 $c\" \ | |
| 160 | +\"|$b A1 $c3\" \ | |
| 161 | +\"|$b B1 $c\" \ | |
| 162 | +\ | |
| 163 | +\"|$b C2 $c\" \ | |
| 164 | +\"|$b B1 $c\" \ | |
| 165 | +\"|$b C2 $c\" \ | |
| 166 | +\"|$b D2 $c\" \ | |
| 167 | +\"|$b C2 $c3\" \ | |
| 168 | +\"|$r\" \ | |
| 169 | +\ | |
| 170 | +\"|$b D2 $m\" \ | |
| 171 | +\"|$b E2 $m\" \ | |
| 172 | +\"|$b D2 $c\" \ | |
| 173 | +\"|$b C#2 $c\" \ | |
| 174 | +\"|$b D2 $c\" \ | |
| 175 | +\"|$b E2 $c\" \ | |
| 176 | +\ | |
| 177 | +\"|$b F2 $m\" \ | |
| 178 | +\"|$b Bb1 $m\" \ | |
| 179 | +\"|$b C2 $c\" \ | |
| 180 | +\"|$b F2 $c\" \ | |
| 181 | +\"|$b D2 $c\" \ | |
| 182 | +\"|$b Bb1 $c\" \ | |
| 183 | +\ | |
| 184 | +\"|$b E1 $m\" \ | |
| 185 | +\"|$b E2 $m\" \ | |
| 186 | +\"|$b D2 $c\" \ | |
| 187 | +\"|$b E2 $m\" \ | |
| 188 | +\"|$b B1 $c\" \ | |
| 189 | +\ | |
| 190 | +\"|$b E1 $sb\" \ | |
| 191 | +-p lowpass -1 1k remix 1p-12 1p-12" -d | |
| @@ -273,7 +273,7 @@ if [ $soxver -ge 1403 ]; then · 272 unmodified lines | ||
| 273 | 273 | echo; echo "Plucked scale:" |
| 274 | 274 | |
| 275 | 275 | options= |
| 276 | − overdrive= | |
| 276 | + overdrive="gain -3" | |
| 277 | 277 | for f in pluck pluck_dist; do |
| 278 | 278 | next_file $f 42 |
| 279 | 279 | note=-29 |
| @@ -289,14 +289,13 @@ if [ $soxver -ge 1403 ]; then · 9 unmodified lines | ||
| 289 | 289 | $input -t s32 - synth .4 pluck %$note $options >> tmp.s32 |
| 290 | 290 | note=$(($note - 1)) |
| 291 | 291 | done |
| 292 | − $input -t s32 - synth pluck %$note $options fade h 0 2 .1 >> tmp.s32 | |
| 292 | + $input -t s32 - synth pluck %$note $options fade t 0 4 3.6 >> tmp.s32 | |
| 293 | 293 | |
| 294 | − $sox -r $rate -c 1 tmp.s32 $output compand .1,.2 6:-70,-60,-20 -7 -15 .1 \ | |
| 295 | − $overdrive pad 0 2 remix 1 1 reverb 30 | |
| 294 | + $sox -r $rate -c 1 tmp.s32 $output $overdrive remix 1 1 reverb 30 | |
| 296 | 295 | |
| 297 | 296 | rm -f tmp.s32 |
| 298 | − options="0 0 60 60" | |
| 299 | − overdrive="overdrive 30 gain -9" | |
| 297 | + options="0 0 60 75 0" | |
| 298 | + overdrive="overdrive gain -10" | |
| 300 | 299 | done |
| 301 | 300 | fi |
| 302 | 301 | |
| @@ -1891,8 +1891,8 @@ The following (one long) command plays a chime sound: · 1890 unmodified lines | ||
| 1891 | 1891 | and this plays a guitar chord: |
| 1892 | 1892 | .EX |
| 1893 | 1893 | .ne 2 |
| 1894 | − play -n synth -j -2 pl %-26 pl %-22 pl %-19 pl %-14 pl %-7 \\ | |
| 1895 | − pl %-2 delay 0 .05 .1 .15 .2 .25 remix - fade 0 4 .1 norm -1 | |
| 1894 | + play -n synth pl G2 pl B2 pl D3 pl G3 pl D4 pl G4 \\ | |
| 1895 | + delay 0 .05 .1 .15 .2 .25 remix - fade 0 4 .1 norm -1 | |
| 1896 | 1896 | .EE |
| 1897 | 1897 | .TP |
| 1898 | 1898 | \fBdither\fR [\fB\-a\fR] [\fB\-S\fR\^|\^\fB\-s\fR\^|\^\fB\-f \fIfilter\fR] |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #define LSX_EFF_ALIAS |
| 22 | 22 | #include "sox_i.h" |
| 23 | 23 | #include <string.h> |
| 24 | +#include <ctype.h> | |
| 24 | 25 | |
| 25 | 26 | int lsx_usage(sox_effect_t * effp) |
| 26 | 27 | { |
| @@ -290,9 +291,24 @@ static double calc_note_freq(double note, int key) · 263 unmodified lines | ||
| 290 | 291 | return 440 * pow(2., note / 12); |
| 291 | 292 | } |
| 292 | 293 | |
| 294 | +int lsx_parse_note(char const * text, char * * end_ptr) | |
| 295 | +{ | |
| 296 | + int result = INT_MAX; | |
| 297 | + | |
| 298 | + if (*text >= 'A' && *text <= 'G') { | |
| 299 | + result = (int)(5/3. * (*text++ - 'A') + 9.5) % 12 - 9; | |
| 300 | + if (*text == 'b') {--result; ++text;} | |
| 301 | + else if (*text == '#') {++result; ++text;} | |
| 302 | + if (isdigit(*text)) | |
| 303 | + result += 12 * (*text++ - '4'); | |
| 304 | + } | |
| 305 | + *end_ptr = (char *)text; | |
| 306 | + return result; | |
| 307 | +} | |
| 308 | + | |
| 293 | 309 | /* Read string 'text' and convert to frequency. |
| 294 | 310 | * 'text' can be a positive number which is the frequency in Hz. |
| 295 | − * If 'text' starts with a hash '%' and a following number the corresponding | |
| 311 | + * If 'text' starts with a '%' and a following number the corresponding | |
| 296 | 312 | * note is calculated. |
| 297 | 313 | * Return -1 on error. |
| 298 | 314 | */ |
| @@ -306,6 +322,10 @@ double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key) · 7 unmodified lines | ||
| 306 | 322 | return -1; |
| 307 | 323 | return calc_note_freq(result, key); |
| 308 | 324 | } |
| 325 | + if (*text >= 'A' && *text <= 'G') { | |
| 326 | + int result = lsx_parse_note(text, end_ptr); | |
| 327 | + return result == INT_MAX? - 1 : calc_note_freq((double)result, key); | |
| 328 | + } | |
| 309 | 329 | result = strtod(text, end_ptr); |
| 310 | 330 | if (end_ptr) { |
| 311 | 331 | if (*end_ptr == text) |
| @@ -2091,7 +2091,7 @@ static lsx_enum_item const encodings[] = { · 2090 unmodified lines | ||
| 2091 | 2091 | |
| 2092 | 2092 | static int enum_option(int option_index, lsx_enum_item const * items) |
| 2093 | 2093 | { |
| 2094 | − lsx_enum_item const * p = lsx_find_enum_text(lsx_optarg, items); | |
| 2094 | + lsx_enum_item const * p = lsx_find_enum_text(lsx_optarg, items, 0); | |
| 2095 | 2095 | if (p == NULL) { |
| 2096 | 2096 | size_t len = 1; |
| 2097 | 2097 | char * set = lsx_malloc(len); |
| @@ -565,7 +565,8 @@ void lsx_debug(const char *, ...) PRINTF; · 564 unmodified lines | ||
| 565 | 565 | typedef struct {char const *text; unsigned value;} lsx_enum_item; |
| 566 | 566 | #define LSX_ENUM_ITEM(prefix, item) {#item, prefix##item}, |
| 567 | 567 | |
| 568 | −lsx_enum_item const * lsx_find_enum_text(char const * text, lsx_enum_item const * lsx_enum_items); | |
| 568 | +lsx_enum_item const * lsx_find_enum_text(char const * text, lsx_enum_item const * lsx_enum_items, unsigned flags); | |
| 569 | +#define LSX_FET_CASE 1 | |
| 569 | 570 | lsx_enum_item const * lsx_find_enum_value(unsigned value, lsx_enum_item const * lsx_enum_items); |
| 570 | 571 | int lsx_enum_option(int c, lsx_enum_item const * items); |
| 571 | 572 | sox_bool lsx_strends(char const * str, char const * end); |
| @@ -82,6 +82,7 @@ void lsx_generate_wave_table( · 81 unmodified lines | ||
| 82 | 82 | double max, /* Maximum value on the y-axis. (e.g. +1) */ |
| 83 | 83 | double phase); /* Phase at 1st point; 0..2pi. (e.g. pi/2 for cosine) */ |
| 84 | 84 | char const * lsx_parsesamples(sox_rate_t rate, const char *str, size_t *samples, int def); |
| 85 | +int lsx_parse_note(char const * text, char * * end_ptr); | |
| 85 | 86 | double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key); |
| 86 | 87 | #define lsx_parse_frequency(a, b) lsx_parse_frequency_k(a, b, INT_MAX) |
| 87 | 88 | FILE * lsx_open_input_file(sox_effect_t * effp, char const * filename); |
| @@ -283,7 +284,7 @@ char * lsx_usage_lines(char * * usage, char const * const * lines, size_t n); · 195 unmodified lines | ||
| 283 | 284 | #define TEXTUAL_PARAMETER(name, enum_table) { \ |
| 284 | 285 | lsx_enum_item const * e; \ |
| 285 | 286 | if (argc == 0) break; \ |
| 286 | − e = lsx_find_enum_text(*argv, enum_table); \ | |
| 287 | + e = lsx_find_enum_text(*argv, enum_table, 0); \ | |
| 287 | 288 | if (e != NULL) { \ |
| 288 | 289 | p->name = e->value; \ |
| 289 | 290 | --argc, ++argv; \ |
| @@ -6,6 +6,25 @@ · 5 unmodified lines | ||
| 6 | 6 | * This source code is freely redistributable and may be used for any purpose. |
| 7 | 7 | * This copyright notice must be maintained. The authors are not responsible |
| 8 | 8 | * for the consequences of using this software. |
| 9 | + * | |
| 10 | + * Except for synth types: pluck, tpdf, & brownnoise, and sweep types: linear | |
| 11 | + * square & exp, which are: | |
| 12 | + * | |
| 13 | + * Copyright (c) 2006-2009 robs@users.sourceforge.net | |
| 14 | + * | |
| 15 | + * This library is free software; you can redistribute it and/or modify it | |
| 16 | + * under the terms of the GNU Lesser General Public License as published by | |
| 17 | + * the Free Software Foundation; either version 2.1 of the License, or (at | |
| 18 | + * your option) any later version. | |
| 19 | + * | |
| 20 | + * This library is distributed in the hope that it will be useful, but | |
| 21 | + * WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 22 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser | |
| 23 | + * General Public License for more details. | |
| 24 | + * | |
| 25 | + * You should have received a copy of the GNU Lesser General Public License | |
| 26 | + * along with this library; if not, write to the Free Software Foundation, | |
| 27 | + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 9 | 28 | */ |
| 10 | 29 | |
| 11 | 30 | #include "sox_i.h" |
| @@ -152,12 +171,12 @@ typedef struct { · 140 unmodified lines | ||
| 152 | 171 | double p1, p2, p3; /* Use depends on synth type */ |
| 153 | 172 | |
| 154 | 173 | /* internal stuff */ |
| 155 | − double cycle_start_time_s; | |
| 156 | − double last_out; | |
| 174 | + double lp_last_out, hp_last_out, hp_last_in, ap_last_out, ap_last_in; | |
| 175 | + double cycle_start_time_s, c0, c1, c2, c3, c4; | |
| 157 | 176 | PinkNoise pink_noise; |
| 158 | 177 | |
| 159 | 178 | double * buffer; |
| 160 | − size_t buffer_len, pos, dx, dy, acc; | |
| 179 | + size_t buffer_len, pos; | |
| 161 | 180 | } channel_t; |
| 162 | 181 | |
| 163 | 182 | |
| @@ -208,12 +227,12 @@ static void set_default_parameters(channel_t * chan, size_t c) · 44 unmodified lines | ||
| 208 | 227 | chan->p1 = 0.1; |
| 209 | 228 | chan->p2 = 0.5; |
| 210 | 229 | chan->p3 = 0.6; |
| 211 | − } else if (chan->p2 < 0) { /* try a symetric waveform */ | |
| 230 | + } else if (chan->p2 < 0) { /* try a symmetric waveform */ | |
| 212 | 231 | if (chan->p1 <= 0.5) { |
| 213 | 232 | chan->p2 = (1 - 2 * chan->p1) / 2; |
| 214 | 233 | chan->p3 = chan->p2 + chan->p1; |
| 215 | 234 | } else { |
| 216 | − /* symetric is not possible, fall back to asymetrical triangle */ | |
| 235 | + /* symetric is not possible, fall back to asymmetrical triangle */ | |
| 217 | 236 | chan->p2 = chan->p1; |
| 218 | 237 | chan->p3 = 1; |
| 219 | 238 | } |
| @@ -237,7 +256,7 @@ static void set_default_parameters(channel_t * chan, size_t c) · 17 unmodified lines | ||
| 237 | 256 | if (chan->p1 < 0) |
| 238 | 257 | chan->p1 = .4; |
| 239 | 258 | if (chan->p2 < 0) |
| 240 | − chan->p2 = 0; | |
| 259 | + chan->p2 = .2, chan->p3 = .9; | |
| 241 | 260 | |
| 242 | 261 | default: break; |
| 243 | 262 | } |
| @@ -267,12 +286,15 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 23 unmodified lines | ||
| 267 | 286 | priv_t * p = (priv_t *) effp->priv; |
| 268 | 287 | channel_t master, * chan = &master; |
| 269 | 288 | int key = INT_MAX, argn = 0; |
| 270 | − char dummy; | |
| 289 | + char dummy, * end_ptr; | |
| 271 | 290 | --argc, ++argv; |
| 272 | 291 | |
| 273 | 292 | if (argc && !strcmp(*argv, "-n")) p->no_headroom = sox_true, ++argv, --argc; |
| 274 | 293 | |
| 275 | − if (argc > 1 && !strcmp(*argv, "-j") && sscanf(argv[1], "%i %c", &key, &dummy) == 1) { | |
| 294 | + if (argc > 1 && !strcmp(*argv, "-j") && ( | |
| 295 | + sscanf(argv[1], "%i %c", &key, &dummy) == 1 || ( | |
| 296 | + (key = lsx_parse_note(argv[1], &end_ptr)) != INT_MAX && | |
| 297 | + !*end_ptr))) { | |
| 276 | 298 | argc -= 2; |
| 277 | 299 | argv += 2; |
| 278 | 300 | } |
| @@ -299,8 +321,7 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 20 unmodified lines | ||
| 299 | 321 | } |
| 300 | 322 | |
| 301 | 323 | while (argn < argc) { /* type [combine] [f1[-f2] [off [ph [p1 [p2 [p3]]]]]] */ |
| 302 | − char * end_ptr; | |
| 303 | − lsx_enum_item const *enum_p = lsx_find_enum_text(argv[argn], synth_type); | |
| 324 | + lsx_enum_item const * enum_p = lsx_find_enum_text(argv[argn], synth_type, LSX_FET_CASE); | |
| 304 | 325 | |
| 305 | 326 | if (enum_p == NULL) { |
| 306 | 327 | lsx_fail("no type given"); |
| @@ -314,7 +335,7 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 7 unmodified lines | ||
| 314 | 335 | break; |
| 315 | 336 | |
| 316 | 337 | /* maybe there is a combine-type in next arg */ |
| 317 | − enum_p = lsx_find_enum_text(argv[argn], combine_type); | |
| 338 | + enum_p = lsx_find_enum_text(argv[argn], combine_type, LSX_FET_CASE); | |
| 318 | 339 | if (enum_p != NULL) { |
| 319 | 340 | chan->combine = enum_p->value; |
| 320 | 341 | if (++argn == argc) |
| @@ -322,16 +343,21 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 1 unmodified line | ||
| 322 | 343 | } |
| 323 | 344 | |
| 324 | 345 | /* read frequencies if given */ |
| 325 | − if (isdigit((int) argv[argn][0]) || | |
| 326 | − argv[argn][0] == '.' || argv[argn][0] == '%') { | |
| 346 | + if (!lsx_find_enum_text(argv[argn], synth_type, LSX_FET_CASE) && | |
| 347 | + argv[argn][0] != '-') { | |
| 327 | 348 | static const char sweeps[] = ":+/-"; |
| 328 | 349 | |
| 329 | 350 | chan->freq2 = chan->freq = lsx_parse_frequency_k(argv[argn], &end_ptr, key); |
| 330 | − if (chan->freq < 0) { | |
| 351 | + if (chan->freq < (chan->type == synth_pluck? 27.5 : 0) || | |
| 352 | + (chan->type == synth_pluck && chan->freq > 4220)) { | |
| 331 | 353 | lsx_fail("invalid freq"); |
| 332 | 354 | return SOX_EOF; |
| 333 | 355 | } |
| 334 | 356 | if (*end_ptr && strchr(sweeps, *end_ptr)) { /* freq2 given? */ |
| 357 | + if (chan->type >= synth_noise) { | |
| 358 | + lsx_fail("can't sweep this type"); | |
| 359 | + return SOX_EOF; | |
| 360 | + } | |
| 335 | 361 | chan->sweep = strchr(sweeps, *end_ptr) - sweeps; |
| 336 | 362 | chan->freq2 = lsx_parse_frequency_k(end_ptr + 1, &end_ptr, key); |
| 337 | 363 | if (chan->freq2 < 0) { |
| @@ -384,7 +410,7 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 46 unmodified lines | ||
| 384 | 410 | static int start(sox_effect_t * effp) |
| 385 | 411 | { |
| 386 | 412 | priv_t * p = (priv_t *)effp->priv; |
| 387 | − size_t i, j; | |
| 413 | + size_t i, j, k; | |
| 388 | 414 | |
| 389 | 415 | p->samples_done = 0; |
| 390 | 416 | |
| @@ -399,24 +425,64 @@ static int start(sox_effect_t * effp) · 8 unmodified lines | ||
| 399 | 425 | *chan = p->getopts_channels[i % p->getopts_nchannels]; |
| 400 | 426 | set_default_parameters(chan, i); |
| 401 | 427 | if (chan->type == synth_pluck) { |
| 402 | − int32_t r = 0; | |
| 403 | − double colour = pow(2., 4 * (chan->p2 - 1)); | |
| 404 | − double dc = 0, a = 6.9 / (chan->p2 < .25? chan->p2 / .25 * 11 + 7 : | |
| 405 | − chan->p2 <= .55? 18 : (1-chan->p2) / .45 * 3 + 15); | |
| 406 | − chan->buffer_len = effp->in_signal.rate / chan->freq + .5; | |
| 407 | − chan->dx = chan->freq * 1000 + .5; | |
| 408 | − chan->dy = effp->in_signal.rate / chan->buffer_len * 1000 + .5; | |
| 409 | − chan->pos = chan->acc = 0; | |
| 410 | − chan->buffer = malloc(chan->buffer_len * sizeof(*chan->buffer)); | |
| 411 | − chan->buffer[0] = 0; | |
| 412 | − for (j = 1; j < chan->buffer_len; dc += chan->buffer[j++]) | |
| 413 | − do chan->buffer[j] = | |
| 414 | − chan->buffer[j - 1] + (chan->p3 == 0? DRANQD1:dranqd1(r)) * colour; | |
| 415 | − while (fabs(chan->buffer[j]) > 1); | |
| 416 | − for (dc /= chan->buffer_len, j = 0; j < chan->buffer_len; ++j) | |
| 417 | − chan->buffer[j] = range_limit(chan->buffer[j] - dc, -1, 1) * a; | |
| 418 | − chan->p3 = .5 * exp(log(.6) / chan->freq / chan->p1); | |
| 419 | − lsx_debug("a=%g colour=%g", a, 1/colour); | |
| 428 | + double min, max, frac, p2; | |
| 429 | + double const decay_rate = -2; /* dB / s */ | |
| 430 | + double const decay_f = min(912, 266 + 106 * log(chan->freq)); | |
| 431 | + double d = sqr(dB_to_linear(decay_rate / chan->freq)); | |
| 432 | + d = (d * cos(2 * M_PI * decay_f / effp->in_signal.rate) - 1) / (d - 1); | |
| 433 | + chan->c0 = d - sqrt(d * d - 1); | |
| 434 | + chan->c1 = 1 - chan->c0; | |
| 435 | + | |
| 436 | + chan->c1 *= exp(-2e4/ (.05+chan->p1)/ chan->freq/ effp->in_signal.rate); | |
| 437 | + | |
| 438 | + chan->c2 = exp(-2 * M_PI * 10 / effp->in_signal.rate); | |
| 439 | + chan->c3 = (1 + chan->c2) * .5; | |
| 440 | + | |
| 441 | + if (effp->in_signal.rate < 44100 || effp->in_signal.rate > 48000) { | |
| 442 | + lsx_fail("sample rate for pluck must be 44100-48000; use `rate' to resample"); | |
| 443 | + return SOX_EOF; | |
| 444 | + } | |
| 445 | + d = chan->c0 / (chan->c0 + chan->c1); | |
| 446 | + | |
| 447 | + chan->buffer_len = effp->in_signal.rate / chan->freq - d; | |
| 448 | + frac = effp->in_signal.rate / chan->freq - d - chan->buffer_len; | |
| 449 | + chan->c4 = (1 - frac) / (1 + frac); | |
| 450 | + chan->pos = 0; | |
| 451 | + | |
| 452 | + chan->buffer = lsx_calloc(chan->buffer_len, sizeof(*chan->buffer)); | |
| 453 | + for (k = 0, p2 = chan->p2; k < 2 && p2 >= 0; ++k, p2 = chan->p3) { | |
| 454 | + double d1 = 0, d, colour = pow(2., 4 * (p2 - 1)); | |
| 455 | + int32_t r = p2 * 100 + .5; | |
| 456 | + for (j = 0; j < chan->buffer_len; ++j) { | |
| 457 | + do d = d1 + (chan->phase? DRANQD1:dranqd1(r)) * colour; | |
| 458 | + while (fabs(d) > 1); | |
| 459 | + chan->buffer[j] += d * (1 - .3 * k); | |
| 460 | + d1 = d * (colour != 1); | |
| 461 | +#ifdef TEST_PLUCK | |
| 462 | + chan->buffer[j] = sin(2 * M_PI * j / chan->buffer_len); | |
| 463 | +#endif | |
| 464 | + } | |
| 465 | + } | |
| 466 | + for (j = 0, min = max = 0; j < chan->buffer_len; ++j) { | |
| 467 | + double d, t = (double)j / chan->buffer_len; | |
| 468 | + chan->lp_last_out = d = | |
| 469 | + chan->buffer[j] * chan->c1 + chan->lp_last_out * chan->c0; | |
| 470 | + | |
| 471 | + chan->ap_last_out = | |
| 472 | + d * chan->c4 + chan->ap_last_in - chan->ap_last_out * chan->c4; | |
| 473 | + chan->ap_last_in = d; | |
| 474 | + | |
| 475 | + chan->buffer[j] = chan->buffer[j] * (1 - t) + chan->ap_last_out * t; | |
| 476 | + min = min(min, chan->buffer[j]); | |
| 477 | + max = max(max, chan->buffer[j]); | |
| 478 | + } | |
| 479 | + for (j = 0, d = 0; j < chan->buffer_len; ++j) { | |
| 480 | + chan->buffer[j] = (2 * chan->buffer[j] - max - min) / (max - min); | |
| 481 | + d += sqr(chan->buffer[j]); | |
| 482 | + } | |
| 483 | + lsx_debug("rms=%f c0=%f c1=%f c2=%f c3=%f df=%f d3f=%f", | |
| 484 | + 10 * log(d / chan->buffer_len), chan->c0, chan->c1, chan->c2, | |
| 485 | + chan->c3, decay_f, log(chan->c0)/ -2 / M_PI * effp->in_signal.rate); | |
| 420 | 486 | } |
| 421 | 487 | switch (chan->sweep) { |
| 422 | 488 | case Linear: chan->mult = p->samples_to_do? |
| @@ -587,22 +653,27 @@ static int flow(sox_effect_t * effp, const sox_sample_t * ibuf, sox_sample_t * o · 164 unmodified lines | ||
| 587 | 653 | break; |
| 588 | 654 | |
| 589 | 655 | case synth_brownnoise: |
| 590 | − do synth_out = chan->last_out + DRANQD1 * (1. / 16); | |
| 656 | + do synth_out = chan->lp_last_out + DRANQD1 * (1. / 16); | |
| 591 | 657 | while (fabs(synth_out) > 1); |
| 592 | − chan->last_out = synth_out; | |
| 658 | + chan->lp_last_out = synth_out; | |
| 593 | 659 | break; |
| 594 | 660 | |
| 595 | 661 | case synth_pluck: { |
| 596 | − size_t pos1 = chan->pos + 1 == chan->buffer_len? 0 : chan->pos + 1; | |
| 597 | − double t = (double)chan->acc / chan->dy; | |
| 598 | − synth_out = chan->buffer[chan->pos] * (1-t) + chan->buffer[pos1] * t; | |
| 599 | − for (chan->acc+=chan->dx; chan->acc>=chan->dy; chan->acc-=chan->dy) { | |
| 600 | − t = chan->buffer[chan->pos]; | |
| 601 | − chan->buffer[chan->pos] = | |
| 602 | − chan->p3 * (chan->buffer[chan->pos] + chan->last_out); | |
| 603 | − chan->last_out = t; | |
| 604 | − chan->pos = chan->pos + 1 == chan->buffer_len? 0 : chan->pos + 1; | |
| 605 | − } | |
| 662 | + double d = chan->buffer[chan->pos]; | |
| 663 | + | |
| 664 | + chan->hp_last_out = | |
| 665 | + (d - chan->hp_last_in) * chan->c3 + chan->hp_last_out * chan->c2; | |
| 666 | + chan->hp_last_in = d; | |
| 667 | + | |
| 668 | + synth_out = range_limit(chan->hp_last_out, -1, 1); | |
| 669 | + | |
| 670 | + chan->lp_last_out = d = d * chan->c1 + chan->lp_last_out * chan->c0; | |
| 671 | + | |
| 672 | + chan->ap_last_out = chan->buffer[chan->pos] = | |
| 673 | + (d - chan->ap_last_out) * chan->c4 + chan->ap_last_in; | |
| 674 | + chan->ap_last_in = d; | |
| 675 | + | |
| 676 | + chan->pos = chan->pos + 1 == chan->buffer_len? 0 : chan->pos + 1; | |
| 606 | 677 | break; |
| 607 | 678 | } |
| 608 | 679 | |
| @@ -58,14 +58,17 @@ char const * lsx_find_file_extension(char const * pathname) · 57 unmodified lines | ||
| 58 | 58 | return result; |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | −lsx_enum_item const * lsx_find_enum_text(char const * text, lsx_enum_item const * enum_items) | |
| 61 | +lsx_enum_item const * lsx_find_enum_text(char const * text, lsx_enum_item const * enum_items, unsigned flags) | |
| 62 | 62 | { |
| 63 | 63 | lsx_enum_item const * result = NULL; /* Assume not found */ |
| 64 | + sox_bool sensitive = !!(flags & LSX_FET_CASE); | |
| 64 | 65 | |
| 65 | 66 | while (enum_items->text) { |
| 66 | − if (strcasecmp(text, enum_items->text) == 0) | |
| 67 | + if ((!sensitive && !strcasecmp(text, enum_items->text)) || | |
| 68 | + ( sensitive && ! strcmp(text, enum_items->text))) | |
| 67 | 69 | return enum_items; /* Found exact match */ |
| 68 | − if (strncasecmp(text, enum_items->text, strlen(text)) == 0) { | |
| 70 | + if ((!sensitive && !strncasecmp(text, enum_items->text, strlen(text))) || | |
| 71 | + ( sensitive && ! strncmp(text, enum_items->text, strlen(text)))) { | |
| 69 | 72 | if (result != NULL && result->value != enum_items->value) |
| 70 | 73 | return NULL; /* Found ambiguity */ |
| 71 | 74 | result = enum_items; /* Found sub-string match */ |
| @@ -85,7 +88,7 @@ lsx_enum_item const * lsx_find_enum_value(unsigned value, lsx_enum_item const * · 13 unmodified lines | ||
| 85 | 88 | |
| 86 | 89 | int lsx_enum_option(int c, lsx_enum_item const * items) |
| 87 | 90 | { |
| 88 | − lsx_enum_item const * p = lsx_find_enum_text(lsx_optarg, items); | |
| 91 | + lsx_enum_item const * p = lsx_find_enum_text(lsx_optarg, items, sox_false); | |
| 89 | 92 | if (p == NULL) { |
| 90 | 93 | size_t len = 1; |
| 91 | 94 | char * set = lsx_malloc(len); |
| @@ -60,7 +60,7 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 59 unmodified lines | ||
| 60 | 60 | } |
| 61 | 61 | |
| 62 | 62 | if (have_type) { |
| 63 | − lsx_enum_item const * p = lsx_find_enum_text(type_ptr, vol_types); | |
| 63 | + lsx_enum_item const * p = lsx_find_enum_text(type_ptr, vol_types, 0); | |
| 64 | 64 | if (!p) |
| 65 | 65 | return lsx_usage(effp); |
| 66 | 66 | switch (p->value) { |