Sonic Pi script to emulate the tonespace MIDI harmonizer from mucoder.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use_real_time # Preventing latency | |
use_tuning :just, :c # Just Intonation, chords are diatonic in C major | |
with_fx :compressor, threshold: 0.1 do # Preventing clipping | |
with_fx :reverb do # Everything on the same reverb | |
with_fx :lpf, cutoff_slide: 0.02 do |filtre| # Everything on the same breath-controlled filter | |
baritone = synth :hoover, note: 0, release: 1000, amp: 0 # “Classic early 90’s rave synth” | |
tenor = synth :chipbass, note: 0, release: 1000, amp: 0 # “A 16 step triangle wave modelled after the 2A03 chip found in voice 3 of the NES games console.” | |
alto = synth :beep, note: 0, release: 1000, amp: 0 # Sine wave | |
soprano = synth :chiplead, note: 0, release: 1000, amp: 0 # “A slightly clipped square (pulse) wave with phases of 12.5%, 25% or 50% modelled after the 2A03 chip found in voices 1 and 2 of the NES games console.” | |
live_loop :notes do | |
note_on, velocity = sync "/midi/USB_Midi_Cable/4/1/note_on" # Incoming notes from Yamaha WX-11 wind controller | |
if velocity > 0 # Only use actual note-ons | |
tick # Used to rotate chords | |
deg=note_on % 12 # Which degree in the C major scale? | |
case deg | |
when 1, 3, 6, 8, 10 # No chord outside of the C major scale | |
shord=[0, 0, 0] | |
when 0 # When the incoming note is a C, any octave, build a chord using the tonespace sequence | |
shord=(ring | |
[4, 7, 11], # CM7 [CEGB] | |
[5, 7, 11], # CM7sus4 [CFGB] | |
[4, 7, 9], # CM6 [CEGA] | |
[5, 7, 9], # CM6sus4 [CFGA] | |
[2, 4, 7], # CMadd9 [CDEG] | |
[4, 7, 0], # CM [CEG] | |
[2, 7, 0], # Csus2 [CDG] | |
[5, 7, 0], # Csus4 [CFG] | |
[4, 0, 0], # CM3 [CE] | |
[7, 0, 0], # CP5 [CG] | |
[5, 0, 0], # CP4 [CF] | |
[2, 0, 0], # CM2 [CD] | |
[9, 0, 0], # CM6 [CA] | |
[11, 0, 0], # C_M7 [CB] | |
[0, 0, 0], # C | |
).look | |
when 2 # When the incoming note is a D… | |
shord=(ring | |
[3, 7, 10], # Dm7 [DFAC] | |
[5, 7, 10], # Dm7sus4 [DGAC] | |
[5, 7, 9], # DM6sus4 [DGAB] | |
[3, 7, 9], # Dm6 [DFAB] | |
[2, 3, 7], # Dmadd9 [DEFA] | |
[3, 7, 0], # Dm [DFA] | |
[2, 7, 0], # Dsus2 [DEA] | |
[5, 7, 0], # Dsus4 [DGA] | |
[3, 5, 0], # Dadd4no5 [DFG] | |
[3, 0, 0], # Dm3 [DF] | |
[7, 0, 0], # DP5 [DA] | |
[5, 0, 0], # DP4 [DG] | |
[2, 0, 0], # DM2 [DE] | |
[9, 0, 0], # DM6 [DB] | |
[10, 0, 0], # D_m7 [DC] | |
[0, 0, 0], # D | |
).look | |
when 4 # Incoming E | |
shord=(ring | |
[3, 7, 10], # Em7 [EGBD] | |
[3, 8, 10], # Em7#5 [EGCD] | |
[5, 7, 10], # E7sus4 [EABD] | |
[3, 7, 0], # Em [EGB] | |
[5, 7, 0], # Esus4 [EAB] | |
[5, 8, 0], # Esus4#5 [EAC] | |
[3, 5, 0], # Eadd4no5 [EGA] | |
[3, 0, 0], # Em3 [EG] | |
[7, 0, 0], # EP5 [EB] | |
[5, 0, 0], # EP4 [EA] | |
[8, 0, 0], # Em6 [EC] | |
[10, 0, 0], # Em7 [ED] | |
[1, 0, 0], # Em2 [EF] | |
[0, 0, 0], # E | |
).look | |
when 5 # Incoming F… | |
shord=(ring | |
[4, 7, 11], # FM7 [FACE] | |
[4, 7, 9], # FM6 [FACD] | |
[2, 4, 7], # FMadd9 [FGAC] | |
[4, 7, 0], # FM [FAC] | |
[4, 6, 0], # Fb5 [FAB] | |
[2, 7, 0], # Fsus2 [FGC] | |
[4, 0, 0], # FM3 [FA] | |
[7, 0, 0], # FP5 [FC] | |
[2, 0, 0], # FM2 [FG] | |
[6, 0, 0], # Fd5 [FB] | |
[9, 0, 0], # FM6 [FD] | |
[11, 0, 0], # FM7 [FE] | |
[0, 0, 0], # F | |
).look | |
when 7 # Incoming G… | |
shord=(ring | |
[4, 7, 10], # G7 [GBDF] | |
[4, 9, 10], # G7add6 [GBEF] | |
[5, 7, 10], # G7sus4 [GCDF] | |
[4, 7, 9], # GM6 [GBDE] | |
[5, 7, 9], # GM6sus4 [GCDE] | |
[2, 4, 7], # GMadd9 [GABD] | |
[4, 7, 0], # GM [GBD] | |
[2, 7, 0], # Gsus2 [GAD] | |
[5, 7, 0], # Gsus4 [GCD] | |
[4, 0, 0], # GM3 [GB] | |
[7, 0, 0], # GP5 [GD] | |
[5, 0, 0], # GP4 [GC] | |
[2, 0, 0], # GM2 [GA] | |
[9, 0, 0], # GM6 [GE] | |
[10, 0, 0], # Gm7 [GF] | |
[0, 0, 0], # G | |
).look | |
when 9 # Incoming A… | |
shord=(ring | |
[3, 7, 10], # Am7 [ACEG] | |
[3, 8, 10], # Am7#5 [ACFG] | |
[5, 7, 10], # A7sus4 [ADEG] | |
[2, 3, 7], # Amadd9 [ABCE] | |
[3, 7, 0], # Am [ACE] | |
[2, 7, 0], # Asus2 [ABE] | |
[5, 7, 0], # Asus4 [ADE] | |
[5, 8, 0], # Asus4#5 [ADF] | |
[3, 5, 0], # Aadd4no5 [ACD] | |
[3, 0, 0], # Am3 [AC] | |
[7, 0, 0], # AP5 [AE] | |
[5, 0, 0], # AP4 [AD] | |
[2, 0, 0], # AM2 [AB] | |
[8, 0, 0], # Am6 [AF] | |
[10, 0, 0], # Am7 [AG] | |
[0, 0, 0], # A | |
).look | |
when 11 # Incoming B… | |
shord=(ring | |
[3, 6, 10], # Bm7b5 [BDFA] | |
[3, 8, 10], # Bm7#5 [BDGA] | |
[3, 6, 0], # Bdim [BDF] | |
[5, 7, 0], # Bsus4#5 [BEG] | |
[3, 5, 0], # Badd4no5 [BDE] | |
[3, 0, 0], # Bm3 [BD] | |
[5, 0, 0], # BP4 [BE] | |
[6, 0, 0], # Bd5 [BF] | |
[8, 0, 0], # Bm6 [BG] | |
[10, 0, 0], # Bm7 [BA] | |
[1, 0, 0], # Bm2 [BC] | |
[0, 0, 0], # B | |
).look | |
end | |
control baritone, note: note_on, amp: velocity / 127.0 # Incoming note, “hoover” sound | |
control tenor, note: note_on + shord[0], amp: velocity / 150.0 # Typically a third or fourth above the incoming note, “chipbass” sound | |
control alto, note: note_on + shord[1], amp: velocity / 150.0 # Typically a fifth above the incoming note, sinewave | |
control soprano, note: note_on + shord[2], amp: velocity / 127.0 # Typically a seventh above the incoming note, “chiplead” sound | |
end | |
end | |
live_loop :windy do # Use the incoming breath control, MIDI CC#2, to modulate the low-pass filter | |
control_change, breath = sync "/midi/USB_Midi_Cable/4/1/control_change" | |
if control_change==2 | |
control filtre, cutoff: breath | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment