1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="949.54">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 22.0px Arial}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Arial; min-height: 15.0px}
p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Arial}
p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #ad1d13}
p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}
p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #0019ba}
span.s1 {text-decoration: underline}
span.s2 {color: #0019ba}
span.s3 {color: #000000}
span.s4 {color: #ad1d13}
span.s5 {color: #2b6f11}
span.s6 {color: #606060}
span.Apple-tab-span {white-space:pre}
</style>
</head>
<body>
<p class="p1">Adding harmonics to a voice input</p>
<p class="p2"><br></p>
<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>
<p class="p2"><br></p>
<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>
<p class="p2"><br></p>
<p class="p4">// (Dan Stowell) (public domain 2006)</p>
<p class="p4">// USE HEADPHONES to prevent feedback.</p>
<p class="p5">(</p>
<p class="p5">x = {</p>
<p class="p5"><span class="s2"><span class="Apple-tab-span"> </span>var</span> son, freq, hasFreq, amp, out, harm;</p>
<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>
<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>
<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>
<p class="p6"><span class="Apple-tab-span"> </span></p>
<p class="p5"><span class="Apple-tab-span"> </span>harm = <span class="s2">SinOsc</span>.ar(freq * 2, 0, amp * hasFreq);</p>
<p class="p6"><span class="Apple-tab-span"> </span></p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="s2">Pan2</span>.ar(harm + son)</p>
<p class="p5">}.play;</p>
<p class="p5">)</p>
<p class="p6"><br></p>
<p class="p4"><span class="s3">x.free; </span>// Use this to stop the synth</p>
<p class="p2"><br></p>
<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>
<p class="p2"><br></p>
<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>
<p class="p2"><br></p>
<p class="p3">Let's implement this, and add a GUI for controlling the contents of the wavetable:</p>
<p class="p2"><br></p>
<p class="p4">// (Dan Stowell, kernel) (gpl 2006)</p>
<p class="p4">//first make and send the Synthdef so it's on the server</p>
<p class="p6"><br></p>
<p class="p5">(</p>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<p class="p5"><span class="Apple-tab-span"> </span><span class="s2">Out</span>.ar(0, <span class="s2">Pan2</span>.ar(mix));</p>
<p class="p5">}).add;</p>
<p class="p5">)</p>
<p class="p6"><br></p>
<p class="p4">// select a GUI server:</p>
<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>
<p class="p4"><span class="s2">GUI</span><span class="s3">.swing;<span class="Apple-tab-span"> </span></span>// use Java GUI</p>
<p class="p6"><br></p>
<p class="p6"><br></p>
<p class="p4">// Now to instantiate the synth and build the GUI.</p>
<p class="p4">// USE HEADPHONES to prevent feedback.</p>
<p class="p5">(</p>
<p class="p5"><span class="s2">var</span> win,buf,m,harmonics,maxHarmonics=60,theSynth;</p>
<p class="p6"><br></p>
<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>
<p class="p6"><br></p>
<p class="p5">harmonics = <span class="s2">Array</span>.fill(maxHarmonics,0);</p>
<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>
<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>
<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>
<p class="p6"><br></p>
<p class="p5">theSynth = <span class="s2">Synth</span>(<span class="s5">\oscPlayer</span>, [<span class="s5">\bufnum</span>, buf.bufnum], s);</p>
<p class="p6"><br></p>
<p class="p5">m = <span class="s2">MultiSliderView</span>(win, <span class="s2">Rect</span>(5, 5, 350, 100))</p>
<p class="p5"><span class="Apple-tab-span"> </span>.value_(harmonics)</p>
<p class="p5"><span class="Apple-tab-span"> </span>.isFilled_(<span class="s2">true</span>)</p>
<p class="p5"><span class="Apple-tab-span"> </span>.valueThumbSize_(3.0)</p>
<p class="p5"><span class="Apple-tab-span"> </span>.indexThumbSize_(3.0)</p>
<p class="p5"><span class="Apple-tab-span"> </span>.gap_(2)</p>
<p class="p5"><span class="Apple-tab-span"> </span>.elasticMode_(1)</p>
<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>
<p class="p6"><span class="Apple-tab-span"> </span></p>
<p class="p5"><span class="s2">Button</span>(win,<span class="s2">Rect</span>(5,110,70,20))</p>
<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>
<p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">var</span> temp;</p>
<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>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>buf.sine1(temp);</p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>m.value_(temp);</p>
<p class="p5"><span class="Apple-tab-span"> </span>});</p>
<p class="p6"><span class="Apple-tab-span"> </span></p>
<p class="p5"><span class="s2">Button</span>(win,<span class="s2">Rect</span>(80,110,65,20))</p>
<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>
<p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">|v|</span> <span class="s2">var</span> temp;</p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>temp = m.value.scramble;</p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>buf.sine1(temp);</p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>m.value_(temp);</p>
<p class="p5"><span class="Apple-tab-span"> </span>});</p>
<p class="p6"><span class="Apple-tab-span"> </span></p>
<p class="p5"><span class="s2">Button</span>(win,<span class="s2">Rect</span>(150,110,20,20))</p>
<p class="p5"><span class="Apple-tab-span"> </span>.states_([[<span class="s6">"<<"</span>,<span class="s2">Color</span>.green,<span class="s2">Color</span>.black]])</p>
<p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">|v|</span> <span class="s2">var</span> temp;</p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>temp = m.value.rotate(-1);</p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>buf.sine1(temp);</p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>m.value_(temp);</p>
<p class="p5"><span class="Apple-tab-span"> </span>});</p>
<p class="p6"><span class="Apple-tab-span"> </span></p>
<p class="p5"><span class="s2">Button</span>(win,<span class="s2">Rect</span>(175,110,20,20))</p>
<p class="p5"><span class="Apple-tab-span"> </span>.states_([[<span class="s6">">>"</span>,<span class="s2">Color</span>.green,<span class="s2">Color</span>.black]])</p>
<p class="p5"><span class="Apple-tab-span"> </span>.action_({<span class="s2">|v|</span> <span class="s2">var</span> temp;</p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>temp = m.value.rotate(1);</p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>buf.sine1(temp);</p>
<p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>m.value_(temp);</p>
<p class="p5"><span class="Apple-tab-span"> </span>});</p>
<p class="p6"><span class="Apple-tab-span"> </span></p>
<p class="p5"><span class="s2">Slider</span>(win, <span class="s2">Rect</span>(365,5,20,100))</p>
<p class="p5"><span class="Apple-tab-span"> </span>.value_(0.1)</p>
<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>
<p class="p6"><span class="Apple-tab-span"> </span></p>
<p class="p5"><span class="s2">Slider</span>(win, <span class="s2">Rect</span>(390,5,20,100))</p>
<p class="p5"><span class="Apple-tab-span"> </span>.value_(0.5)</p>
<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>
<p class="p5">)</p>
</body>
</html>
|