1 <!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
4 <meta http-equiv=
"Content-Type" content=
"text/html; charset=UTF-8">
5 <meta http-equiv=
"Content-Style-Type" content=
"text/css">
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
}
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>
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>
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>
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>
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>
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">"<<"</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">">>"</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>