Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / examples / demonstrations / HarmonicsVoice.html
blobed798f3a304e46839120ba80abb70efe554d5c79
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5 <meta http-equiv="Content-Style-Type" content="text/css">
6 <title></title>
7 <meta name="Generator" content="Cocoa HTML Writer">
8 <meta name="CocoaVersion" content="949.54">
9 <style type="text/css">
10 p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 22.0px Arial}
11 p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Arial; min-height: 15.0px}
12 p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Arial}
13 p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #ad1d13}
14 p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
15 p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}
16 p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #0019ba}
17 span.s1 {text-decoration: underline}
18 span.s2 {color: #0019ba}
19 span.s3 {color: #000000}
20 span.s4 {color: #ad1d13}
21 span.s5 {color: #2b6f11}
22 span.s6 {color: #606060}
23 span.Apple-tab-span {white-space:pre}
24 </style>
25 </head>
26 <body>
27 <p class="p1">Adding harmonics to a voice input</p>
28 <p class="p2"><br></p>
29 <p class="p3">One easy way to add harmonics is to use the <span class="s1">[PitchShift]</span> UGen. See its helpfile for more details.</p>
30 <p class="p2"><br></p>
31 <p class="p3">An alternative approach is to use the <span class="s1">[Pitch]</span> UGen to track the pitch contour, and use that in synthesis. This allows you to generate sounds matching the pitch of the input but with any kind of texture.</p>
32 <p class="p2"><br></p>
33 <p class="p4">// (Dan Stowell) (public domain 2006)</p>
34 <p class="p4">// USE HEADPHONES to prevent feedback.</p>
35 <p class="p5">(</p>
36 <p class="p5">x = {</p>
37 <p class="p5"><span class="s2"><span class="Apple-tab-span"> </span>var</span> son, freq, hasFreq, amp, out, harm;</p>
38 <p class="p4"><span class="s3"><span class="Apple-tab-span"> </span>son = </span><span class="s2">AudioIn</span><span class="s3">.ar(1); </span>// get first channel of sound input</p>
39 <p class="p5"><span class="Apple-tab-span"> </span># freq, hasFreq = <span class="s2">Pitch</span>.kr(son); <span class="s4">// Pitch of input signal</span></p>
40 <p class="p4"><span class="s3"><span class="Apple-tab-span"> </span>amp = </span><span class="s2">Amplitude</span><span class="s3">.ar(son); </span>// Amplitude of input signal</p>
41 <p class="p6"><span class="Apple-tab-span"> </span></p>
42 <p class="p5"><span class="Apple-tab-span"> </span>harm = <span class="s2">SinOsc</span>.ar(freq * 2, 0, amp * hasFreq);</p>
43 <p class="p6"><span class="Apple-tab-span"> </span></p>
44 <p class="p5"><span class="Apple-tab-span"> </span><span class="s2">Pan2</span>.ar(harm + son)</p>
45 <p class="p5">}.play;</p>
46 <p class="p5">)</p>
47 <p class="p6"><br></p>
48 <p class="p4"><span class="s3">x.free; </span>// Use this to stop the synth</p>
49 <p class="p2"><br></p>
50 <p class="p3">The above example adds only one harmonic. You can extend this to create multiple harmonics quite easily, for example by using an array of pitch ratios rather than a single ratio (and therefore creating an array of sine oscillators); or you could change the texture by using a more unusual oscillator (e.g. <span class="s1">[Saw]</span> or <span class="s1">[Gendy1]</span> or <span class="s1">[HenonN]</span>).</p>
51 <p class="p2"><br></p>
52 <p class="p3">If you want a large number of controllable overtones then a bank of separate sine oscillators will become quite computationally intensive, so a good alternative is to use the general wavetable oscillator <span class="s1">[Osc]</span> instead of SinOsc. The wavetable (a buffer) can be filled with a wave representing the harmonic profile you're interested in, and only one oscillator is needed to read it back.</p>
53 <p class="p2"><br></p>
54 <p class="p3">Let's implement this, and add a GUI for controlling the contents of the wavetable:</p>
55 <p class="p2"><br></p>
56 <p class="p4">// (Dan Stowell, kernel) (gpl 2006)</p>
57 <p class="p4">//first make and send the Synthdef so it's on the server</p>
58 <p class="p6"><br></p>
59 <p class="p5">(</p>
60 <p class="p7">SynthDef<span class="s3">(</span><span class="s5">\oscPlayer</span><span class="s3">, {</span>|bufnum,balance=0.5,smooth=0.1|</p>
61 <p class="p5"><span class="s2"><span class="Apple-tab-span"> </span>var</span> input,freq,hasFreq,amp,mix,wet;<span class="Apple-tab-span"> </span></p>
62 <p class="p4"><span class="s3"><span class="Apple-tab-span"> </span>input = </span><span class="s2">AudioIn</span><span class="s3">.ar(1); </span>// get first channel of sound input</p>
63 <p class="p5"><span class="Apple-tab-span"> </span>#freq,hasFreq = <span class="s2">Pitch</span>.kr(input); <span class="s4">// pitch of input signal</span></p>
64 <p class="p4"><span class="s3"><span class="Apple-tab-span"> </span>amp = </span><span class="s2">Amplitude</span><span class="s3">.ar(input); </span>// amplitude of input signal</p>
65 <p class="p5"><span class="Apple-tab-span"> </span>wet = <span class="s2">Osc</span>.ar(bufnum,<span class="s2">Lag</span>.kr(freq,smooth), 0, amp);</p>
66 <p class="p5"><span class="Apple-tab-span"> </span>mix = (input * (1-balance)) + (wet * balance);<span class="Apple-converted-space"> <span class="Apple-tab-span"> </span></span></p>
67 <p class="p5"><span class="Apple-tab-span"> </span><span class="s2">Out</span>.ar(0, <span class="s2">Pan2</span>.ar(mix));</p>
68 <p class="p5">}).add;</p>
69 <p class="p5">)</p>
70 <p class="p6"><br></p>
71 <p class="p4">// select a GUI server:</p>
72 <p class="p4"><span class="s2">GUI</span><span class="s3">.cocoa;<span class="Apple-tab-span"> </span></span>// use Mac OS X native GUI</p>
73 <p class="p4"><span class="s2">GUI</span><span class="s3">.swing;<span class="Apple-tab-span"> </span></span>// use Java GUI</p>
74 <p class="p6"><br></p>
75 <p class="p6"><br></p>
76 <p class="p4">// Now to instantiate the synth and build the GUI.</p>
77 <p class="p4">// USE HEADPHONES to prevent feedback.</p>
78 <p class="p5">(</p>
79 <p class="p5"><span class="s2">var</span> win,buf,m,harmonics,maxHarmonics=60,theSynth;</p>
80 <p class="p6"><br></p>
81 <p class="p5">win = <span class="s2">Window</span>(<span class="s6">"input harmonica"</span>,<span class="s2">Rect</span>(200,200,420,160)).front;</p>
82 <p class="p6"><br></p>
83 <p class="p5">harmonics = <span class="s2">Array</span>.fill(maxHarmonics,0);</p>
84 <p class="p4"><span class="s3">harmonics.put(0,1);<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// init array so first partial is alive</p>
85 <p class="p5">buf = <span class="s2">Buffer</span>.alloc(s, 4096, 1);<span class="Apple-tab-span"> </span><span class="s4">// create buffer</span></p>
86 <p class="p5">buf.sine1(harmonics);<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s4">// fill buffer</span></p>
87 <p class="p6"><br></p>
88 <p class="p5">theSynth = <span class="s2">Synth</span>(<span class="s5">\oscPlayer</span>, [<span class="s5">\bufnum</span>, buf.bufnum], s);</p>
89 <p class="p6"><br></p>
90 <p class="p5">m = <span class="s2">MultiSliderView</span>(win, <span class="s2">Rect</span>(5, 5, 350, 100))</p>
91 <p class="p5"><span class="Apple-tab-span"> </span>.value_(harmonics)</p>
92 <p class="p5"><span class="Apple-tab-span"> </span>.isFilled_(<span class="s2">true</span>)</p>
93 <p class="p5"><span class="Apple-tab-span"> </span>.valueThumbSize_(3.0)</p>
94 <p class="p5"><span class="Apple-tab-span"> </span>.indexThumbSize_(3.0)</p>
95 <p class="p5"><span class="Apple-tab-span"> </span>.gap_(2)</p>
96 <p class="p5"><span class="Apple-tab-span"> </span>.elasticMode_(1)</p>
97 <p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">|v|</span> buf.sine1(v.value)}); <span class="s4">// fill buffer again</span></p>
98 <p class="p6"><span class="Apple-tab-span"> </span></p>
99 <p class="p5"><span class="s2">Button</span>(win,<span class="s2">Rect</span>(5,110,70,20))</p>
100 <p class="p5"><span class="Apple-tab-span"> </span>.states_([[<span class="s6">"CLEAR"</span>,<span class="s2">Color</span>.green,<span class="s2">Color</span>.black]])</p>
101 <p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">var</span> temp;</p>
102 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>temp = <span class="s2">Array</span>.fill(maxHarmonics,0);</p>
103 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>buf.sine1(temp);</p>
104 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>m.value_(temp);</p>
105 <p class="p5"><span class="Apple-tab-span"> </span>});</p>
106 <p class="p6"><span class="Apple-tab-span"> </span></p>
107 <p class="p5"><span class="s2">Button</span>(win,<span class="s2">Rect</span>(80,110,65,20))</p>
108 <p class="p5"><span class="Apple-tab-span"> </span>.states_([[<span class="s6">"RAND"</span>,<span class="s2">Color</span>.green,<span class="s2">Color</span>.black]])</p>
109 <p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">|v|</span> <span class="s2">var</span> temp;</p>
110 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>temp = m.value.scramble;</p>
111 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>buf.sine1(temp);</p>
112 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>m.value_(temp);</p>
113 <p class="p5"><span class="Apple-tab-span"> </span>});</p>
114 <p class="p6"><span class="Apple-tab-span"> </span></p>
115 <p class="p5"><span class="s2">Button</span>(win,<span class="s2">Rect</span>(150,110,20,20))</p>
116 <p class="p5"><span class="Apple-tab-span"> </span>.states_([[<span class="s6">"&lt;&lt;"</span>,<span class="s2">Color</span>.green,<span class="s2">Color</span>.black]])</p>
117 <p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">|v|</span> <span class="s2">var</span> temp;</p>
118 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>temp = m.value.rotate(-1);</p>
119 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>buf.sine1(temp);</p>
120 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>m.value_(temp);</p>
121 <p class="p5"><span class="Apple-tab-span"> </span>});</p>
122 <p class="p6"><span class="Apple-tab-span"> </span></p>
123 <p class="p5"><span class="s2">Button</span>(win,<span class="s2">Rect</span>(175,110,20,20))</p>
124 <p class="p5"><span class="Apple-tab-span"> </span>.states_([[<span class="s6">"&gt;&gt;"</span>,<span class="s2">Color</span>.green,<span class="s2">Color</span>.black]])</p>
125 <p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">|v|</span> <span class="s2">var</span> temp;</p>
126 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>temp = m.value.rotate(1);</p>
127 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>buf.sine1(temp);</p>
128 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>m.value_(temp);</p>
129 <p class="p5"><span class="Apple-tab-span"> </span>});</p>
130 <p class="p6"><span class="Apple-tab-span"> </span></p>
131 <p class="p5"><span class="s2">Slider</span>(win, <span class="s2">Rect</span>(365,5,20,100))</p>
132 <p class="p5"><span class="Apple-tab-span"> </span>.value_(0.1)</p>
133 <p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">|v|</span> theSynth.set(<span class="s5">\smooth</span>,[0,1,<span class="s5">\lin</span>,0.001].asSpec.unmap(v.value))});</p>
134 <p class="p6"><span class="Apple-tab-span"> </span></p>
135 <p class="p5"><span class="s2">Slider</span>(win, <span class="s2">Rect</span>(390,5,20,100))</p>
136 <p class="p5"><span class="Apple-tab-span"> </span>.value_(0.5)</p>
137 <p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">|v|</span> theSynth.set(<span class="s5">\balance</span>,v.value)});</p>
138 <p class="p5">)</p>
139 </body>
140 </html>