Skip to content

Commit 18d21e2

Browse files
committed
Add new Autotuner fx
Implements a new autotune, which is closer to the Antares original. It doesn't use FFTs - instead everything happens in the time domain. This version of the effect has options for transpose, key and scale along with note as a target note. Performance should be better than the other autotuner effect which exists in SP currently. See @xavriley/qlibugens for the original plugin. Binaries are available on the Releases page.
1 parent 44b97f2 commit 18d21e2

File tree

8 files changed

+247
-1
lines changed

8 files changed

+247
-1
lines changed

Diff for: BUILD-LINUX.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ few dependencies:
4545
* Ruby + Dev tools (2.5+)
4646
* Erlang + Dev tools (21+)
4747
* SuperCollider + SC3 plugins
48-
*
48+
* (Optional) Additional SuperCollider plugins
4949

5050

5151
### 1.1 Raspberry Pi OS
@@ -61,6 +61,16 @@ sudo apt-get install -y \
6161
compton pulseaudio-module-jack
6262
```
6363

64+
### 1.2 (Optional) Additional SuperCollider Plugins
65+
66+
Some audio effects and synthesizer are not distributed with the `sc3-plugins-server` package and prebuilt binaries are not provided with the Sonic Pi repo. To use these with your version of Sonic Pi, you can find build instructions at the following repositories:
67+
68+
* https://github.com/xavriley/qlibugens/ - used by the `:autotuner_two` effect.
69+
* (more to follow as we implement other plugins)
70+
71+
After building the plugins, make sure you copy them to your [SuperCollider Extensions folder](https://doc.sccode.org/Guides/UsingExtensions.html) before starting Sonic Pi.
72+
73+
If you don't do this, everything else will still work as normal - you just won't be able to use these particular effects.
6474

6575
## 2. Preparing the Build
6676

Diff for: app/server/ruby/lib/sonicpi/synths/synthinfo.rb

+144
Original file line numberDiff line numberDiff line change
@@ -5419,6 +5419,149 @@ def specific_arg_info
54195419
end
54205420
end
54215421

5422+
class FXAutotuner2 < FXInfo
5423+
def name
5424+
"Autotuner2"
5425+
end
5426+
5427+
def introduced
5428+
Version.new(4,0,0)
5429+
end
5430+
5431+
def synth_name
5432+
"fx_autotuner_two"
5433+
end
5434+
5435+
def doc
5436+
"Another autotune effect. Used without any arguments, it tries to detect the pitch and shift it to the nearest exact note. This can help with out of tune singing, but it's also an interesting effect in its own right. When used with the note: arg, it tries to shift the input to match that note instead. This gives that classic \"robot singing\" sound that people associate with vocoders. This can then be changed using the control method to create new melodies.
5437+
5438+
```
5439+
with_fx :autotuner_two do |c|
5440+
```
5441+
5442+
```
5443+
sample \"~/Downloads/acappella.wav\" # any sample with a voice is good
5444+
```
5445+
5446+
```
5447+
sleep 4
5448+
```
5449+
5450+
```
5451+
# listen to standard auto-tune behaviour for 4 seconds
5452+
```
5453+
5454+
```
5455+
64.times do
5456+
```
5457+
5458+
```
5459+
# now start changing note: to get robot voice behaviour
5460+
```
5461+
5462+
```
5463+
control c, note: (scale :a2, :minor_pentatonic, num_octaves: 2).choose
5464+
```
5465+
5466+
```
5467+
sleep 0.5
5468+
```
5469+
5470+
```
5471+
end
5472+
```
5473+
5474+
```
5475+
end
5476+
```
5477+
"
5478+
end
5479+
5480+
def arg_defaults
5481+
super.merge({
5482+
:note => -1,
5483+
:note_slide => 0,
5484+
:note_slide_shape => 1,
5485+
:note_slide_curve => 0,
5486+
:transpose => 0,
5487+
:key => 0,
5488+
:scale => 0
5489+
})
5490+
end
5491+
5492+
def munge_opts(studio, args_h)
5493+
keys = {
5494+
nil => nil,
5495+
:c => 0,
5496+
:cs => 1,
5497+
:db => 1,
5498+
:d => 2,
5499+
:ds => 3,
5500+
:eb => 3,
5501+
:e => 4,
5502+
:f => 5,
5503+
:fs => 6,
5504+
:gb => 6,
5505+
:g => 7,
5506+
:gs => 8,
5507+
:ab => 8,
5508+
:a => 9,
5509+
:as => 10,
5510+
:bb => 10,
5511+
:b => 11
5512+
}
5513+
args_h[:key] = keys[args_h[:key]]
5514+
5515+
scales = {
5516+
nil => nil,
5517+
:none => 0,
5518+
:chromatic => 0,
5519+
:major => 1,
5520+
:major_pentatonic => 2,
5521+
:minor_pentatonic => 3
5522+
}
5523+
5524+
args_h[:scale] = scales[args_h[:scale]]
5525+
5526+
puts args_h
5527+
args_h
5528+
end
5529+
5530+
def specific_arg_info
5531+
{
5532+
:note =>
5533+
{
5534+
:doc => "Midi note to shift pitch to. The quality of the sound depends on how stable the pitch of the input is. If set, this will override the scale and key options. Set to -1 to turn this off.",
5535+
:validations => [v_between_inclusive(:note, -2, 127)],
5536+
:modulatable => true
5537+
},
5538+
5539+
:key =>
5540+
{
5541+
:doc => "Key to lock the output pitches to. One of :c, :cs, :d, :e, :f, :fs, :g, :gs, :a, :as, or :b.",
5542+
:validations => [v_one_of(:key, [nil, :c, :cs, :db, :d, :ds, :eb, :e, :f, :fs, :gb, :g, :gs, :ab, :a, :as, :bb, :b,
5543+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])],
5544+
:modulatable => false
5545+
},
5546+
5547+
:scale =>
5548+
{
5549+
:doc => "Scale to lock the output pitches to. One of :none, :chromatic, :major, :major_pentatonic or :minor_pentatonic.",
5550+
:validations => [v_one_of(:scale, [nil, :none, :chromatic, :major, :major_pentatonic, :minor_pentatonic,
5551+
0, 1, 2, 3])],
5552+
:modulatable => false
5553+
},
5554+
5555+
:transpose =>
5556+
{
5557+
:doc => "Number of semitones to shift the output up or down, with a maximum of +24 (two octaves up) and a minimum of -24 (two octaves down).",
5558+
:validations => [v_between_inclusive(:transpose, -24, 24)],
5559+
:modulatable => true
5560+
}
5561+
}
5562+
end
5563+
end
5564+
54225565
class FXMono < FXInfo
54235566
def name
54245567
"Mono"
@@ -8183,6 +8326,7 @@ class BaseInfo
81838326
:fx_level => FXLevel.new,
81848327
:fx_mono => FXMono.new,
81858328
:fx_autotuner => FXAutotuner.new,
8329+
:fx_autotuner_two => FXAutotuner2.new,
81868330
:fx_replace_level => FXLevel.new,
81878331
:fx_echo => FXEcho.new,
81888332
:fx_replace_echo => FXEcho.new,
3.14 KB
Binary file not shown.

Diff for: etc/synthdefs/designs/supercollider/autotuner_two.sc

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Autotune style plugin based on the orignal Antares patent (US Patent US5973252 - now expired). Uses Cycfi's Bitstream Autocorrelation (BACF) for pitch tracking.
2+
// See https://github.com/xavriley/qlibugens for details of the SC UGens
3+
4+
(
5+
SynthDef('sonic-pi-fx_autotuner_two', {|
6+
//standard args
7+
pre_amp=1,
8+
pre_amp_slide=0,
9+
pre_amp_slide_shape=1,
10+
pre_amp_slide_curve=0,
11+
amp=1,
12+
amp_slide=0,
13+
amp_slide_shape=1,
14+
amp_slide_curve=0,
15+
mix=1,
16+
mix_slide=0,
17+
mix_slide_shape=1,
18+
mix_slide_curve=0,
19+
pre_mix=1,
20+
pre_mix_slide=0,
21+
pre_mix_slide_shape=1,
22+
pre_mix_slide_curve=0
23+
out_bus=0,
24+
in_bus=0,
25+
// args specific to this synth
26+
note = -1,
27+
note_slide=0,
28+
note_slide_shape=1,
29+
note_slide_curve=0,
30+
min_freq = 50,
31+
transpose=0,
32+
key=0,
33+
scale=0|
34+
35+
var pitch_ratio,
36+
in,
37+
snd,
38+
freq,
39+
// args for Sonic Pi plumbing
40+
fxArgMix,
41+
fxArgPreMix,
42+
fxArgAmp,
43+
fxArgPreAmp,
44+
inLeft,
45+
inRight,
46+
fxArgInvPreMix,
47+
fxArgBypassL,
48+
fxArgBypassR,
49+
dryL,
50+
dryR,
51+
wetL,
52+
wetR,
53+
finL,
54+
finR;
55+
56+
// plumbing for Sonic Pi standard args
57+
fxArgMix = VarLag.kr(mix.clip(0,1), mix_slide, mix_slide_curve, mix_slide_shape);
58+
fxArgMix = LinLin.kr(fxArgMix, 0, 1, -1, 1);
59+
60+
fxArgPreMix = VarLag.kr(pre_mix.clip(0,1), pre_mix_slide, pre_mix_slide_curve, pre_mix_slide_shape);
61+
62+
fxArgAmp = VarLag.kr(amp, amp_slide, amp_slide_curve, amp_slide_shape);
63+
fxArgPreAmp = VarLag.kr(pre_amp, pre_amp_slide, pre_amp_slide_curve, pre_amp_slide_shape);
64+
65+
# inLeft, inRight = In.ar(in_bus, 2) * fxArgPreAmp;
66+
fxArgInvPreMix = 1 - fxArgPreMix;
67+
68+
fxArgBypassL = fxArgInvPreMix * inLeft;
69+
fxArgBypassR = fxArgInvPreMix * inRight;
70+
71+
dryL = fxArgPreMix * inLeft;
72+
dryR = fxArgPreMix * inRight;
73+
74+
// note represents a midi "target" pitch to tune to
75+
// without that arg, it works as a normal autotune, locking the
76+
// input to the nearest midi note
77+
note = note.varlag(note_slide, note_slide_curve, note_slide_shape);
78+
79+
wetL = BitstreamPitchCorrection.ar(inLeft, min_freq, transpose: transpose, key: key, scale: scale, target_note: note);
80+
wetR = wetL;
81+
82+
// plumbing for Sonic Pi output
83+
wetL = wetL + fxArgBypassL;
84+
wetR = wetR + fxArgBypassR;
85+
86+
finL = XFade2.ar(inLeft, wetL, fxArgMix, fxArgAmp);
87+
finR = XFade2.ar(inRight, wetR, fxArgMix, fxArgAmp);
88+
89+
Out.ar(out_bus, [finL, finR]);
90+
}
91+
).writeDefFile("/Users/sam/Development/RPi/sonic-pi/etc/synthdefs/compiled/")
92+
)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)