The Csound Blog by Jacob Joaquin email jacobjoaquin@gmail.com web www.thumbuki.com/csound/blog (C)2007 Jacob Joaquin Licensed under Creative Commons (see below) 2007.02.06 Robot Voices and Android Grooves One of my earliest synthesizer fascinations was the robotic voice produced by band vocoders[1]. While in college, I stumbled across the vocoder schematics in The Computer Music Tutorial by Curtis Roads[2]. Equipped with only Csound and my new-found knowledge, I created my first vocoder instrument. I have since designed many variations, and will likely to continue doing so for many years to come. Because robots rule. A Very Brief History The vocoder was invented by Homer Dudley at Bell Labs in the 1930's, as a potential method for saving phone-line bandwidth and for encryption purposes[3]. One of the first musical applications came from synth legend Bob Moog[4] and electronic composer Wendy Carlos[5] in 1970. For many years, the electronic voice prospered until the vocoder craze peaked in 1983 when Styx released "Mr. Roboto[6]." * For more accurate info on the history of the vocoder, check out the reference section near the end of this writeup. How does it work? Vocoded audio is constructed from two audio sources, commonly referred to the carrier and the modulator. Both the carrier and modulator signals are processed with two separate arrays of parallel, individually-tuned bandpass filters. The amplitudes of each signal emanating from the carrier's filter array is set to follow the amplitudes of the modulator's corresponding filter array. These synth units are known as "envelope followers[7]." The resulting signals are then summed and sent to the mixer or processed further. Here is the signal flow of a simple 4-band vocoder. (carrier in) (modulator in) | | | '------. .------'-----.------------.------------. | | | | | | | .-----~ | ~--.-----~ | ~--.-----~ | ~--: | | | | | | | | | | | | | | | | [bp] [bp] [bp] [bp] [bp] [bp] [bp] [bp] | | | | | | | | | | | | | | | | [follow] [follow] [follow] [follow] | | | | | | | | | '---. .---' | | \ / | '------------------(+)------------------' | | (out) * Requires a fixed-width font to view properly As a side note, all my time spent making terrible ANSI art[8] in 1993 and 1994 has finally paid off. The Example In this Csound example, I use a timbre-rich synthesizer voice as the carrier, and use drums as the modulator. The drums are copied from my first Csound Blog writeup[9]. I used the zak busses for sending the synth and drum signals to the vocoder. The p-fields are utilized so that each instance of the vocoder can have a different frequency range. Envelope following is achieved with the balance opcode. The Robot To reproduce the talking robot voice, use a a timbre-rich synthesizer sound as the carrier signal and a talking human voice for the modulator. You'll have to provide your own voice, as there is currently no practical way of embedding huge tracks of audio into a .csd file. Be patient, as it sometimes takes awhile to find the right combination of settings to get that slam'n robot sound. Further Study Since this instrument is a bare bones vocoder, there are plenty of modifications you can do to make it your own. You can run the original modulator signal through a highpass filter and sum this with the vocoded audio for more intelligible speech. Instead of running a carrier signal through a bandpass filter array, use an array of sine wave oscillators to follow the amplitudes produced by modulator filter array. The frequencies of the carrier and modulator filter arrays don't have to be identical, allowing you to achieve quasi-pitch shifting and voice scrambling. The bandpass frequencies don't necessarily have to be fixed either, so use enveloping or other sources of modulation for more profound effects. References [1] The Vocoder http://en.wikipedia.org/wiki/Vocoder [2] The Computer Music Tutorial by Curtis Roads http://amazon.com/s/ref=nb_ss_gw/105-8775364-2470843?url=search-alias%3Daps&field-keywords=the+computer+music+tutorial&Go.x=0&Go.y=0&Go=Go [3] Homer Dudley http://en.wikipedia.org/wiki/Vocoder [4] Bob Moog http://en.wikipedia.org/wiki/Bob_Moog [5] Wendy Carlos http://www.wendycarlos.com/vocoders.html [6] Mr. Roboto http://en.wikipedia.org/wiki/Mr._Roboto [7] Envelope Following http://en.wikipedia.org/wiki/Envelope_follower [8] Ansi Art http://en.wikipedia.org/wiki/ANSI_art [9] An Experiment in Csound Blogging http://www.thumbuki.com/csound/files/thumbuki20061222.csd Permalink http://www.thumbuki.com/20070206/robot-voices-and-android-grooves.html License (cc) Creative Commons Attribution-ShareAlike 2.5 You are free: * to Share -- to copy, distribute, display, and perform the work * to Remix -- to make derivative works Under the following conditions: * Attribution. You must attribute the work in the manner specified by the author or licensor. * Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one. * For any reuse or distribution, you must make clear to others the license terms of this work. * Any of these conditions can be waived if you get permission from the copyright holder. http://creativecommons.org/licenses/by-sa/2.5/ sr = 44100 kr = 4410 ksmps = 10 nchnls = 1 ; instr 20 Subtractive Chord ; instr 50 Kick Drun ; instr 51 Snare Drum ; instr 52 Electro Bell ; instr 53 Hi-Hat ; instr 55 Drum Mixer ; instr 100 Vocoder ; instr 200 Master Mixer ; instr 300 Clear Zak Channels ; Master Volume #define VOLUME #5000# ; Zak Busses # define ZACHANNELS #7# # define ZKCHANNELS #1# zakinit $ZACHANNELS, $ZKCHANNELS ; a-rate zak channels # define ZCARRIER #1# # define ZMODULATOR #2# # define ZKICK #3# # define ZSNARE #4# # define ZHIHAT #5# #define ZBELL #6# # define ZMIXER #7# ; k-rate zak channels ; none ; ---- Substractive Chord ---- instr 20 iamp = p4 ip0 = cpspch( p5 ) ip1 = cpspch( p5 + 0.07 ) * 1.001 ip2 = cpspch( p5 + 0.10 ) * 1.010 ip3 = cpspch( p5 + 1.00 ) * 0.998 ip4 = cpspch( p5 + 1.07 ) * 0.999 ip5 = cpspch( p5 + 1.04 ) * 0.994 ; Harmonic strength of gbuzz generators using exponential interpolation ih0 = 0.9 ih5 = 0.4 iinterp pow ( ih5 / ih0 ), ( 1 / 5 ) ih1 = ih0 * iinterp ih2 = ih1 * iinterp ih3 = ih2 * iinterp ih4 = ih3 * iinterp ih5 = ih4 * iinterp ; Array of gbuzz generators asig0 gbuzz 1, ip0, sr / 2 / ip0, 1, ih0, 2, -1 asig1 gbuzz 1, ip1, sr / 2 / ip1, 1, ih1, 2, -1 asig2 gbuzz 1, ip2, sr / 2 / ip2, 1, ih2, 2, -1 asig3 gbuzz 1, ip3, sr / 2 / ip3, 1, ih3, 2, -1 asig4 gbuzz 1, ip4, sr / 2 / ip4, 2, ih4, 2, -1 asig5 gbuzz 1, ip5, sr / 2 / ip5, 3, ih5, 2, -1 ; Mix signals and send to zak bus amix = asig0 + asig2 + asig3 + asig4 + asig5 zawm amix, $ZCARRIER endin ; ---- Kick Drum ---- instr 50 idur = 3 kenv1 expseg 900, 0.01, 50, idur - 0.01, 20 asig1 oscil3 1, kenv1, 1 kenv2 line 1, idur, 0 asig1 = asig1 * kenv2 asig2 gauss 1 kenv5 expseg 800, 0.1, 50, idur - 0.1, 20 asig2 tone asig2, kenv5 amix = asig1 + asig2 kenv5 expseg 500, 0.05, 60, idur - 0.05, 20 amix rezzy amix, kenv5, 10 kenv6 linseg 50, idur, 20 aosc oscil3 1, kenv6, 1 kenv4 expseg 2, 0.15, 1, idur - 0.15, 1 kenv4 = kenv4 - 1 amix = ( amix * 0.7 + aosc * 1.8 ) * kenv4 zawm amix, $ZKICK endin ; ---- Snare Drum ---- instr 51 idur = p3 atri oscil3 1, 111, 2 ; triange wave areal, aimag hilbert atri ifshift = 175 asin oscil3 1, ifshift, 1 acos oscil3 1, ifshift, 1, .25 amod1 = areal * acos amod2 = aimag * asin ashift1 = ( amod1 + amod2 ) * 0.7 ifshift2 = 224 asin oscil3 1, ifshift2, 1 acos oscil3 1, ifshift2, 1, .25 amod1 = areal * acos amod2 = aimag * asin ashift2 = ( amod1 + amod2 ) * 0.7 kenv1 linseg 1, 0.15, 0, idur - 0.15, 0 ashiftmix = ( ashift1 + ashift2 ) * kenv1 aosc1 oscil3 1, 180, 1 aosc2 oscil3 1, 330, 1 kenv2 linseg 1, 0.08, 0, idur - 0.08, 0 aoscmix = ( aosc1 + aosc2 ) * kenv2 anoise gauss 1 anoise butterhp anoise, 2000 anoise butterlp anoise, 8000 anoise butterbr anoise, 4000, 200 kenv3 expseg 2, 0.15, 1, idur - 0.15, 1 anoise = anoise * ( kenv3 - 1 ) amix = aoscmix + ashiftmix + anoise * 4 kenv4 linseg 0, 0.01, 1, idur - 0.02, 1, 0.01, 0 amix = amix * kenv4 zaw amix, $ZSNARE endin ; ---- Electro Bell ---- instr 52 idur = p3 kenv expseg 2, 0.1, 1.15, idur - 0.1, 1 kenv = kenv - 1 aosc1 oscil3 kenv, 587, 4 aosc2 oscil3 kenv, 845, 4 amix = ( aosc1 + aosc2 ) amix butterbp amix, 2600, 800 zaw amix, $ZBELL endin ; ---- Hi-Hat ---- instr 53 idur = p3 ifreq = 50 a1 oscil 1, ifreq * 1, 4 a2 oscil 1, ifreq * 2.333, 4 a3 oscil 1, ifreq * 3.578, 4 a4 oscil 1, ifreq * 5.123, 4 a5 oscil 1, ifreq * 7.632, 4 a6 oscil 1, ifreq * 9.843, 4 amix = a1 + a2 + a3 + a4 + a5 + a6 kenv1 linseg 0, 0.01, 1, 0.08, 0, idur - 0.09, 0 amix = amix * kenv1 kenv2 linseg 1, 0.12, 0, idur - 0.12, 0 anoise gauss 1 amix = ( anoise * kenv2 ) * 3.5 + amix amix butterhp amix, 7000 amix = amix + rnd( .05 ) zaw amix, $ZHIHAT endin ; ---- Drum Mixer ---- instr 55 iamp = p4 a1 zar $ZKICK a2 zar $ZSNARE a3 zar $ZBELL a4 zar $ZHIHAT a1 = a1 * 3 a2 = a2 * 2.5 a3 = a3 * 6 a4 = a4 * .8 amix = ( a1 + a2 + a3 + a4 ) * iamp zawm amix, $ZMODULATOR endin ; ---- Vocoder ---- instr 100 idur = p3 igain = p4 ib0 = cpspch( p5 ) ib9 = cpspch( p6 ) ibandwidth = p7 acar zar $ZCARRIER amod zar $ZMODULATOR ; Exponential Interpolation icoef pow ( ib9 / ib0 ), ( 1 / 9 ) ib1 = ib0 * icoef ib2 = ib1 * icoef ib3 = ib2 * icoef ib4 = ib3 * icoef ib5 = ib4 * icoef ib6 = ib5 * icoef ib7 = ib6 * icoef ib8 = ib7 * icoef ib9 = ib8 * icoef ; Process carrier with bandpass array abpc0 butterbp acar, ib0, ib1 * ibandwidth abpc1 butterbp acar, ib1, ib2 * ibandwidth abpc2 butterbp acar, ib2, ib3 * ibandwidth abpc3 butterbp acar, ib3, ib3 * ibandwidth abpc4 butterbp acar, ib4, ib4 * ibandwidth abpc5 butterbp acar, ib5, ib5 * ibandwidth abpc6 butterbp acar, ib6, ib6 * ibandwidth abpc7 butterbp acar, ib7, ib7 * ibandwidth abpc8 butterbp acar, ib8, ib8 * ibandwidth abpc9 butterbp acar, ib9, ib9 * ibandwidth ; Process modulator with bandpass array abpm0 butterbp amod, ib0, ib0 * ibandwidth abpm1 butterbp amod, ib1, ib1 * ibandwidth abpm2 butterbp amod, ib2, ib2 * ibandwidth abpm3 butterbp amod, ib3, ib3 * ibandwidth abpm4 butterbp amod, ib4, ib4 * ibandwidth abpm5 butterbp amod, ib5, ib5 * ibandwidth abpm6 butterbp amod, ib6, ib6 * ibandwidth abpm7 butterbp amod, ib7, ib7 * ibandwidth abpm8 butterbp amod, ib8, ib8 * ibandwidth abpm9 butterbp amod, ib9, ib9 * ibandwidth ; Modulate the carrier with the balance array av0 balance abpc0, abpm0 av1 balance abpc1, abpm1 av2 balance abpc2, abpm2 av3 balance abpc3, abpm3 av4 balance abpc4, abpm4 av5 balance abpc5, abpm5 av6 balance abpc6, abpm6 av7 balance abpc7, abpm7 av8 balance abpc8, abpm8 av9 balance abpc9, abpm9 ; Mix and send to main mixer aenv linseg 0, 0.01, 1, idur - 0.02, 1, 0.01, 0 amix = ( av0 + av1 + av2 + av3 + av4 + av5 + av6 + av7 + av8 + av9 ) amix = amix * aenv * igain zawm amix, $ZMIXER endin ; ---- Master Mixer ---- instr 200 amix zar $ZMIXER out amix * $VOLUME endin ; ---- Clear Zak Channels ---- instr 300 zacl 0, $ZACHANNELS endin f1 0 65536 10 1 f2 0 65536 11 1 f4 0 8192 -7 1 2048 1 0 -1 2048 -1 t 0 111 ; ---- Buzz Synth ---- i20 0 4 1 7.00 i20 4 4 . 6.09 i20 8 4 . 7.02 i20 12 2 . 7.07 i20 14 2 . 7.05 ; ---- Vocoder ---- i100 0 8 1.4 7.00 11.00 .1 i100 8 8 . 8.00 12.00 . ; ---- Drums ---- i55 0 16 1 i50 0.0000 1 i50 0.5000 1 i50 1.5000 1 i50 2.5000 1 i50 2.7500 1 i50 3.5000 1 i51 1.0000 1 i51 1.7500 1 i51 2.2500 1 i51 3.0000 1 i51 3.7500 1 i53 0.0000 1 i53 0.5000 1 i53 1.0000 1 i53 1.5000 1 i53 2.0000 1 i53 2.5000 1 i53 3.0000 1 i53 3.5000 1 i52 3.5000 1 i50 4.0000 1 i50 4.5000 1 i50 5.5000 1 i50 6.5000 1 i50 6.7500 1 i50 7.5000 1 i51 5.0000 1 i51 5.7500 1 i51 6.2500 1 i51 7.0000 1 i51 7.7500 1 i53 4.0000 1 i53 4.5000 1 i53 5.0000 1 i53 5.5000 1 i53 6.0000 1 i53 6.5000 1 i53 7.0000 1 i53 7.5000 1 i52 7.5000 1 i50 8.0000 1 i50 8.5000 1 i50 9.5000 1 i50 10.5000 1 i50 10.7500 1 i50 11.5000 1 i51 9.0000 1 i51 9.7500 1 i51 10.2500 1 i51 11.0000 1 i51 11.7500 1 i53 8.0000 1 i53 8.5000 1 i53 9.0000 1 i53 9.5000 1 i53 10.0000 1 i53 10.5000 1 i53 11.0000 1 i53 11.5000 1 i52 11.5000 1 i50 12.0000 1 i50 12.5000 1 i50 13.5000 1 i50 14.5000 1 i50 14.7500 1 i50 15.5000 1 i51 13.0000 1 i51 13.7500 1 i51 14.2500 1 i51 15.0000 1 ;i51 15.7500 1 i53 12.0000 1 i53 12.5000 1 i53 13.0000 1 i53 13.5000 1 i53 14.0000 1 i53 14.5000 1 i53 15.0000 1 i53 15.5000 1 i52 15.5000 1 ; ---- Main Mixer ---- i200 0 16 ; ---- Zak Clear ---- i300 0 16 e