History

synth pluck improvements

robs committed 17 years ago

Commit 8f84c481 parent 7e6aa6d11 files · +275 −76Browse files

Unified · Split

11 files
  1. scripts/alert.sh +1 −2
  2. scripts/synth.sh +117 −12
  3. scripts/testtones.sh +5 −6
  4. sox.1 +2 −2
  5. src/effects_i.c +21 −1
  6. src/sox.c +1 −1
  7. src/sox.h +2 −1
  8. src/sox_i.h +2 −1
  9. src/synth.c +116 −45
  10. src/util.c +7 −4
  11. src/vol.c +1 −1
scripts/alert.sh+1−2
@@ -26,7 +26,6 @@ · 25 unmodified lines
26# ---------------------------------------------------------------------------26# ---------------------------------------------------------------------------
27 27
28SOX=../src/sox28SOX=../src/sox
29PLAY=../src/play
30 29
31rm -f 2tones.ul # Make sure we append to a file that's initially empty30rm -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$SOX -c 1 -r 8000 alert.ul alert.au # Add a file header44$SOX -c 1 -r 8000 alert.ul alert.au # Add a file header
46rm 2tones.ul alert.ul # Tidy up intermediate files45rm 2tones.ul alert.ul # Tidy up intermediate files
47 46
48$PLAY alert.au47$SOX alert.au -d
scripts/synth.sh+117−12
@@ -1,6 +1,6 @@
1#!/bin/sh1#!/bin/sh
2 2
3# SoX script: synth.sh (c) 2008 robs@users.sourceforge.net3# SoX script: synth.sh (c) 2008-9 robs@users.sourceforge.net
4#4#
5# This program is free software; you can redistribute it and/or modify it5# This program is free software; you can redistribute it and/or modify it
6# under the terms of the GNU General Public License as published by the6# under the terms of the GNU General Public License as published by the
@@ -17,7 +17,6 @@ · 10 unmodified lines
17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 18
19sox=../src/sox19sox=../src/sox
20play=../src/play
21 20
22G0="pl %-26 pl %-19 pl %-14 pl %-10 pl %-7 pl %-2"21G0="pl %-26 pl %-19 pl %-14 pl %-10 pl %-7 pl %-2"
23A0="pl %-24 pl %-17 pl %-12 pl %-8 pl %-5 pl %0"22A0="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
26E0="pl %-22 pl %-17 pl %-10 pl %-5 pl %-1 pl %2"25E0="pl %-22 pl %-17 pl %-10 pl %-5 pl %-1 pl %2"
27Bb0="pl %-23 pl %-16 pl %-11 pl %-7 pl %-4 pl %1"26Bb0="pl %-23 pl %-16 pl %-11 pl %-7 pl %-4 pl %1"
28 27
29o="overdrive 40 gain -8"28o="overdrive 27 gain -11"
30e="delay 0 .02 .04 .06 .08 .1 remix - $o fade 0"29e="delay 0 .02 .04 .06 .08 .1 remix - overdrive 33 gain -8 fade 0"
31s="$sox -q -n -p synth 0 0 0 80 87"30s="$sox -q -n -p synth 0 0 1 60 90"
32l="$sox -q -n -p synth 0 0 0 80 0 0"31l="$sox -q -n -p synth 0 0 0 50 20"
33 32
34$play -m -v .8 \33b="$sox -np synth 0 0 0 30 20 pl"
34c3="fade h 0 .75"
35c="fade h 0 .25"
36cs="fade h 0 .25 .05"
37m="fade h 0 .5"
38sb="fade h 0 1"
39r="$sox -np trim 0 .25"
40r2="$sox -np trim 0 .5"
41r3="$sox -np trim 0 .75"
42
43$sox -m -v .8 \
35"|$sox \44"|$sox \
36\"|$sox -n -p synth noise fade 0 .5 .48 trim 0 .15\" \45\"|$sox -n -p synth noise fade 0 .5 .48 trim 0 .15\" \
37\"|$sox -n -p synth noise fade h 0 .26 .11 gain -35 lowpass -1 12k\" \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\"|$l pl %10 $o trim 0 .5 bend .2,-300,.1\" \72\"|$l pl %10 $o trim 0 .5 bend .2,-300,.1\" \
64\"|$l pl %5 $o trim 0 .5 bend .2,-200,.1\" \73\"|$l pl %5 $o trim 0 .5 bend .2,-200,.1\" \
65\"|$l pl %0 $o fade 0 .55 .1 bend .2,-200,.1\" \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\"|$sox -n -p trim 0 3.95\" \76\"|$sox -n -p trim 0 3.95\" \
68\"|$l pl %12 $o trim 0 .5 bend .2,-200,.1\" \77\"|$l pl %12 $o trim 0 .5 bend .2,-200,.1\" \
69\"|$l pl %12 $o trim 0 .5 bend .2,-200,.1\" \78\"|$l pl %12 $o trim 0 .5 bend .2,-200,.1\" \
70\"|$l pl %12 $o fade 0 .8 .1 bend .2,-200,.1\" \79\"|$l pl %12 $o fade 0 .8 .1 bend .2,-200,.1\" \
71\"|$l pl %12 $o trim 0 .3 bend .1,-200,.1\" \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\" \81\"|$l pl %12 $o fade 0 1.95 .6 bend .0,-50,1.75 gain 3\" \
73\"|$l pl %10 $o trim 0 2 bend .3,-50,1\" \82\"|$l pl %10 $o fade 0 2 .6 bend .0,-50,1.9\" \
74\"|$l pl %9 $o trim 0 2 gain -3\" \83\"|$l pl %9 $o trim 0 2 gain -1\" \
75\"|$l pl %8 $o fade h 0 1 .3\" \84\"|$l pl %8 $o fade h 0 1 .3\" \
76\"|$l pl %8 $o fade h 0 1 .1 gain 1.5\" \85\"|$l pl %8 $o fade h 0 1 .1 gain 1.5\" \
77\"|$l pl %2 pl %7 delay 0 .02 remix - $o trim 0 .25\" \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\"|$l pl %2 pl %7 delay 0 .02 remix - $o trim 0 .25\" \92\"|$l pl %2 pl %7 delay 0 .02 remix - $o trim 0 .25\" \
84\"|$l pl %-5 $o trim 0 .25\" \93\"|$l pl %-5 $o trim 0 .25\" \
85\"|$l pl %2 pl %7 delay 0 .02 remix - $o fade h 0 6 6\" \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
scripts/testtones.sh+5−6
@@ -273,7 +273,7 @@ if [ $soxver -ge 1403 ]; then · 272 unmodified lines
273 echo; echo "Plucked scale:"273 echo; echo "Plucked scale:"
274 274
275 options=275 options=
276 overdrive=276 overdrive="gain -3"
277 for f in pluck pluck_dist; do277 for f in pluck pluck_dist; do
278 next_file $f 42278 next_file $f 42
279 note=-29279 note=-29
@@ -289,14 +289,13 @@ if [ $soxver -ge 1403 ]; then · 9 unmodified lines
289 $input -t s32 - synth .4 pluck %$note $options >> tmp.s32289 $input -t s32 - synth .4 pluck %$note $options >> tmp.s32
290 note=$(($note - 1))290 note=$(($note - 1))
291 done291 done
292 $input -t s32 - synth pluck %$note $options fade h 0 2 .1 >> tmp.s32292 $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 \294 $sox -r $rate -c 1 tmp.s32 $output $overdrive remix 1 1 reverb 30
295 $overdrive pad 0 2 remix 1 1 reverb 30
296 295
297 rm -f tmp.s32296 rm -f tmp.s32
298 options="0 0 60 60"297 options="0 0 60 75 0"
299 overdrive="overdrive 30 gain -9"298 overdrive="overdrive gain -10"
300 done299 done
301fi300fi
302 301
sox.1+2−2
@@ -1891,8 +1891,8 @@ The following (one long) command plays a chime sound: · 1890 unmodified lines
1891and this plays a guitar chord:1891and this plays a guitar chord:
1892.EX1892.EX
1893.ne 21893.ne 2
1894 play -n synth -j -2 pl %-26 pl %-22 pl %-19 pl %-14 pl %-7 \\1894 play -n synth pl G2 pl B2 pl D3 pl G3 pl D4 pl G4 \\
1895 pl %-2 delay 0 .05 .1 .15 .2 .25 remix - fade 0 4 .1 norm -11895 delay 0 .05 .1 .15 .2 .25 remix - fade 0 4 .1 norm -1
1896.EE1896.EE
1897.TP1897.TP
1898\fBdither\fR [\fB\-a\fR] [\fB\-S\fR\^|\^\fB\-s\fR\^|\^\fB\-f \fIfilter\fR]1898\fBdither\fR [\fB\-a\fR] [\fB\-S\fR\^|\^\fB\-s\fR\^|\^\fB\-f \fIfilter\fR]
src/effects_i.c+21−1
@@ -21,6 +21,7 @@ · 20 unmodified lines
21#define LSX_EFF_ALIAS21#define LSX_EFF_ALIAS
22#include "sox_i.h"22#include "sox_i.h"
23#include <string.h>23#include <string.h>
24#include <ctype.h>
24 25
25int lsx_usage(sox_effect_t * effp)26int 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 return 440 * pow(2., note / 12);291 return 440 * pow(2., note / 12);
291}292}
292 293
294int 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/* Read string 'text' and convert to frequency.309/* Read string 'text' and convert to frequency.
294 * 'text' can be a positive number which is the frequency in Hz.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 corresponding311 * If 'text' starts with a '%' and a following number the corresponding
296 * note is calculated.312 * note is calculated.
297 * Return -1 on error.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 return -1;322 return -1;
307 return calc_note_freq(result, key);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 result = strtod(text, end_ptr);329 result = strtod(text, end_ptr);
310 if (end_ptr) {330 if (end_ptr) {
311 if (*end_ptr == text)331 if (*end_ptr == text)
src/sox.c+1−1
@@ -2091,7 +2091,7 @@ static lsx_enum_item const encodings[] = { · 2090 unmodified lines
2091 2091
2092static int enum_option(int option_index, lsx_enum_item const * items)2092static 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 if (p == NULL) {2095 if (p == NULL) {
2096 size_t len = 1;2096 size_t len = 1;
2097 char * set = lsx_malloc(len);2097 char * set = lsx_malloc(len);
src/sox.h+2−1
@@ -565,7 +565,8 @@ void lsx_debug(const char *, ...) PRINTF; · 564 unmodified lines
565typedef struct {char const *text; unsigned value;} lsx_enum_item;565typedef struct {char const *text; unsigned value;} lsx_enum_item;
566#define LSX_ENUM_ITEM(prefix, item) {#item, prefix##item},566#define LSX_ENUM_ITEM(prefix, item) {#item, prefix##item},
567 567
568lsx_enum_item const * lsx_find_enum_text(char const * text, lsx_enum_item const * lsx_enum_items);568lsx_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
569lsx_enum_item const * lsx_find_enum_value(unsigned value, lsx_enum_item const * lsx_enum_items);570lsx_enum_item const * lsx_find_enum_value(unsigned value, lsx_enum_item const * lsx_enum_items);
570int lsx_enum_option(int c, lsx_enum_item const * items);571int lsx_enum_option(int c, lsx_enum_item const * items);
571sox_bool lsx_strends(char const * str, char const * end);572sox_bool lsx_strends(char const * str, char const * end);
src/sox_i.h+2−1
@@ -82,6 +82,7 @@ void lsx_generate_wave_table( · 81 unmodified lines
82 double max, /* Maximum value on the y-axis. (e.g. +1) */82 double max, /* Maximum value on the y-axis. (e.g. +1) */
83 double phase); /* Phase at 1st point; 0..2pi. (e.g. pi/2 for cosine) */83 double phase); /* Phase at 1st point; 0..2pi. (e.g. pi/2 for cosine) */
84char const * lsx_parsesamples(sox_rate_t rate, const char *str, size_t *samples, int def);84char const * lsx_parsesamples(sox_rate_t rate, const char *str, size_t *samples, int def);
85int lsx_parse_note(char const * text, char * * end_ptr);
85double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key);86double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key);
86#define lsx_parse_frequency(a, b) lsx_parse_frequency_k(a, b, INT_MAX)87#define lsx_parse_frequency(a, b) lsx_parse_frequency_k(a, b, INT_MAX)
87FILE * lsx_open_input_file(sox_effect_t * effp, char const * filename);88FILE * 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#define TEXTUAL_PARAMETER(name, enum_table) { \284#define TEXTUAL_PARAMETER(name, enum_table) { \
284 lsx_enum_item const * e; \285 lsx_enum_item const * e; \
285 if (argc == 0) break; \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 if (e != NULL) { \288 if (e != NULL) { \
288 p->name = e->value; \289 p->name = e->value; \
289 --argc, ++argv; \290 --argc, ++argv; \
src/synth.c+116−45
@@ -6,6 +6,25 @@ · 5 unmodified lines
6 * This source code is freely redistributable and may be used for any purpose.6 * This source code is freely redistributable and may be used for any purpose.
7 * This copyright notice must be maintained. The authors are not responsible7 * This copyright notice must be maintained. The authors are not responsible
8 * for the consequences of using this software.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#include "sox_i.h"30#include "sox_i.h"
@@ -152,12 +171,12 @@ typedef struct { · 140 unmodified lines
152 double p1, p2, p3; /* Use depends on synth type */171 double p1, p2, p3; /* Use depends on synth type */
153 172
154 /* internal stuff */173 /* internal stuff */
155 double cycle_start_time_s;174 double lp_last_out, hp_last_out, hp_last_in, ap_last_out, ap_last_in;
156 double last_out;175 double cycle_start_time_s, c0, c1, c2, c3, c4;
157 PinkNoise pink_noise;176 PinkNoise pink_noise;
158 177
159 double * buffer;178 double * buffer;
160 size_t buffer_len, pos, dx, dy, acc;179 size_t buffer_len, pos;
161} channel_t;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 chan->p1 = 0.1;227 chan->p1 = 0.1;
209 chan->p2 = 0.5;228 chan->p2 = 0.5;
210 chan->p3 = 0.6;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 if (chan->p1 <= 0.5) {231 if (chan->p1 <= 0.5) {
213 chan->p2 = (1 - 2 * chan->p1) / 2;232 chan->p2 = (1 - 2 * chan->p1) / 2;
214 chan->p3 = chan->p2 + chan->p1;233 chan->p3 = chan->p2 + chan->p1;
215 } else {234 } else {
216 /* symetric is not possible, fall back to asymetrical triangle */235 /* symetric is not possible, fall back to asymmetrical triangle */
217 chan->p2 = chan->p1;236 chan->p2 = chan->p1;
218 chan->p3 = 1;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 if (chan->p1 < 0)256 if (chan->p1 < 0)
238 chan->p1 = .4;257 chan->p1 = .4;
239 if (chan->p2 < 0)258 if (chan->p2 < 0)
240 chan->p2 = 0;259 chan->p2 = .2, chan->p3 = .9;
241 260
242 default: break;261 default: break;
243 }262 }
@@ -267,12 +286,15 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 23 unmodified lines
267 priv_t * p = (priv_t *) effp->priv;286 priv_t * p = (priv_t *) effp->priv;
268 channel_t master, * chan = &master;287 channel_t master, * chan = &master;
269 int key = INT_MAX, argn = 0;288 int key = INT_MAX, argn = 0;
270 char dummy;289 char dummy, * end_ptr;
271 --argc, ++argv;290 --argc, ++argv;
272 291
273 if (argc && !strcmp(*argv, "-n")) p->no_headroom = sox_true, ++argv, --argc;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 argc -= 2;298 argc -= 2;
277 argv += 2;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 while (argn < argc) { /* type [combine] [f1[-f2] [off [ph [p1 [p2 [p3]]]]]] */323 while (argn < argc) { /* type [combine] [f1[-f2] [off [ph [p1 [p2 [p3]]]]]] */
302 char * end_ptr;324 lsx_enum_item const * enum_p = lsx_find_enum_text(argv[argn], synth_type, LSX_FET_CASE);
303 lsx_enum_item const *enum_p = lsx_find_enum_text(argv[argn], synth_type);
304 325
305 if (enum_p == NULL) {326 if (enum_p == NULL) {
306 lsx_fail("no type given");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 break;335 break;
315 336
316 /* maybe there is a combine-type in next arg */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 if (enum_p != NULL) {339 if (enum_p != NULL) {
319 chan->combine = enum_p->value;340 chan->combine = enum_p->value;
320 if (++argn == argc)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 /* read frequencies if given */345 /* read frequencies if given */
325 if (isdigit((int) argv[argn][0]) ||346 if (!lsx_find_enum_text(argv[argn], synth_type, LSX_FET_CASE) &&
326 argv[argn][0] == '.' || argv[argn][0] == '%') {347 argv[argn][0] != '-') {
327 static const char sweeps[] = ":+/-";348 static const char sweeps[] = ":+/-";
328 349
329 chan->freq2 = chan->freq = lsx_parse_frequency_k(argv[argn], &end_ptr, key);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 lsx_fail("invalid freq");353 lsx_fail("invalid freq");
332 return SOX_EOF;354 return SOX_EOF;
333 }355 }
334 if (*end_ptr && strchr(sweeps, *end_ptr)) { /* freq2 given? */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 chan->sweep = strchr(sweeps, *end_ptr) - sweeps;361 chan->sweep = strchr(sweeps, *end_ptr) - sweeps;
336 chan->freq2 = lsx_parse_frequency_k(end_ptr + 1, &end_ptr, key);362 chan->freq2 = lsx_parse_frequency_k(end_ptr + 1, &end_ptr, key);
337 if (chan->freq2 < 0) {363 if (chan->freq2 < 0) {
@@ -384,7 +410,7 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 46 unmodified lines
384static int start(sox_effect_t * effp)410static int start(sox_effect_t * effp)
385{411{
386 priv_t * p = (priv_t *)effp->priv;412 priv_t * p = (priv_t *)effp->priv;
387 size_t i, j;413 size_t i, j, k;
388 414
389 p->samples_done = 0;415 p->samples_done = 0;
390 416
@@ -399,24 +425,64 @@ static int start(sox_effect_t * effp) · 8 unmodified lines
399 *chan = p->getopts_channels[i % p->getopts_nchannels];425 *chan = p->getopts_channels[i % p->getopts_nchannels];
400 set_default_parameters(chan, i);426 set_default_parameters(chan, i);
401 if (chan->type == synth_pluck) {427 if (chan->type == synth_pluck) {
402 int32_t r = 0;428 double min, max, frac, p2;
403 double colour = pow(2., 4 * (chan->p2 - 1));429 double const decay_rate = -2; /* dB / s */
404 double dc = 0, a = 6.9 / (chan->p2 < .25? chan->p2 / .25 * 11 + 7 :430 double const decay_f = min(912, 266 + 106 * log(chan->freq));
405 chan->p2 <= .55? 18 : (1-chan->p2) / .45 * 3 + 15);431 double d = sqr(dB_to_linear(decay_rate / chan->freq));
406 chan->buffer_len = effp->in_signal.rate / chan->freq + .5;432 d = (d * cos(2 * M_PI * decay_f / effp->in_signal.rate) - 1) / (d - 1);
407 chan->dx = chan->freq * 1000 + .5;433 chan->c0 = d - sqrt(d * d - 1);
408 chan->dy = effp->in_signal.rate / chan->buffer_len * 1000 + .5;434 chan->c1 = 1 - chan->c0;
409 chan->pos = chan->acc = 0;435
410 chan->buffer = malloc(chan->buffer_len * sizeof(*chan->buffer));436 chan->c1 *= exp(-2e4/ (.05+chan->p1)/ chan->freq/ effp->in_signal.rate);
411 chan->buffer[0] = 0;437
412 for (j = 1; j < chan->buffer_len; dc += chan->buffer[j++])438 chan->c2 = exp(-2 * M_PI * 10 / effp->in_signal.rate);
413 do chan->buffer[j] =439 chan->c3 = (1 + chan->c2) * .5;
414 chan->buffer[j - 1] + (chan->p3 == 0? DRANQD1:dranqd1(r)) * colour;440
415 while (fabs(chan->buffer[j]) > 1);441 if (effp->in_signal.rate < 44100 || effp->in_signal.rate > 48000) {
416 for (dc /= chan->buffer_len, j = 0; j < chan->buffer_len; ++j)442 lsx_fail("sample rate for pluck must be 44100-48000; use `rate' to resample");
417 chan->buffer[j] = range_limit(chan->buffer[j] - dc, -1, 1) * a;443 return SOX_EOF;
418 chan->p3 = .5 * exp(log(.6) / chan->freq / chan->p1);444 }
419 lsx_debug("a=%g colour=%g", a, 1/colour);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 switch (chan->sweep) {487 switch (chan->sweep) {
422 case Linear: chan->mult = p->samples_to_do?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 break;653 break;
588 654
589 case synth_brownnoise: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 while (fabs(synth_out) > 1);657 while (fabs(synth_out) > 1);
592 chan->last_out = synth_out;658 chan->lp_last_out = synth_out;
593 break;659 break;
594 660
595 case synth_pluck: {661 case synth_pluck: {
596 size_t pos1 = chan->pos + 1 == chan->buffer_len? 0 : chan->pos + 1;662 double d = chan->buffer[chan->pos];
597 double t = (double)chan->acc / chan->dy;663
598 synth_out = chan->buffer[chan->pos] * (1-t) + chan->buffer[pos1] * t;664 chan->hp_last_out =
599 for (chan->acc+=chan->dx; chan->acc>=chan->dy; chan->acc-=chan->dy) {665 (d - chan->hp_last_in) * chan->c3 + chan->hp_last_out * chan->c2;
600 t = chan->buffer[chan->pos];666 chan->hp_last_in = d;
601 chan->buffer[chan->pos] =667
602 chan->p3 * (chan->buffer[chan->pos] + chan->last_out);668 synth_out = range_limit(chan->hp_last_out, -1, 1);
603 chan->last_out = t;669
604 chan->pos = chan->pos + 1 == chan->buffer_len? 0 : chan->pos + 1;670 chan->lp_last_out = d = d * chan->c1 + chan->lp_last_out * chan->c0;
605 }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 break;677 break;
607 }678 }
608 679
src/util.c+7−4
@@ -58,14 +58,17 @@ char const * lsx_find_file_extension(char const * pathname) · 57 unmodified lines
58 return result;58 return result;
59}59}
60 60
61lsx_enum_item const * lsx_find_enum_text(char const * text, lsx_enum_item const * enum_items)61lsx_enum_item const * lsx_find_enum_text(char const * text, lsx_enum_item const * enum_items, unsigned flags)
62{62{
63 lsx_enum_item const * result = NULL; /* Assume not found */63 lsx_enum_item const * result = NULL; /* Assume not found */
64 sox_bool sensitive = !!(flags & LSX_FET_CASE);
64 65
65 while (enum_items->text) {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 return enum_items; /* Found exact match */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 if (result != NULL && result->value != enum_items->value)72 if (result != NULL && result->value != enum_items->value)
70 return NULL; /* Found ambiguity */73 return NULL; /* Found ambiguity */
71 result = enum_items; /* Found sub-string match */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
86int lsx_enum_option(int c, lsx_enum_item const * items)89int 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 if (p == NULL) {92 if (p == NULL) {
90 size_t len = 1;93 size_t len = 1;
91 char * set = lsx_malloc(len);94 char * set = lsx_malloc(len);
src/vol.c+1−1
@@ -60,7 +60,7 @@ static int getopts(sox_effect_t * effp, int argc, char **argv) · 59 unmodified lines
60 }60 }
61 61
62 if (have_type) {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 if (!p)64 if (!p)
65 return lsx_usage(effp);65 return lsx_usage(effp);
66 switch (p->value) {66 switch (p->value) {

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