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 141 142 143 144 145 146 147
|
<!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="1038.32">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco; color: #376c2a}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}
p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica}
p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #606060}
p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}
p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #cd1713}
p.p10 {margin: 0.0px 0.0px 0.0px 85.0px; text-indent: -85.0px; font: 9.0px Monaco; color: #737373}
p.p11 {margin: 0.0px 0.0px 0.0px 85.0px; text-indent: -85.0px; font: 9.0px Monaco; color: #cd1713}
p.p12 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #000000; min-height: 12.0px}
p.p13 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #ad140d}
p.p14 {margin: 0.0px 0.0px 0.0px 85.0px; text-indent: -85.0px; font: 9.0px Monaco; color: #ad140d}
p.p15 {margin: 0.0px 0.0px 0.0px 85.0px; text-indent: -85.0px; font: 9.0px Monaco}
span.s1 {font: 12.0px Helvetica; color: #000000}
span.s2 {color: #001bb9}
span.s3 {color: #000000}
span.s4 {color: #102ac3}
span.s5 {color: #606060}
span.s6 {color: #2c7014}
span.s7 {color: #ad140d}
span.Apple-tab-span {white-space:pre}
</style>
</head>
<body>
<p class="p1">//Copyright (C) 2006<span class="Apple-converted-space"> </span>Nick Collins distributed under the terms of the GNU General Public License</p>
<p class="p2"><br></p>
<p class="p3"><b>Qitch<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>constant Q transform pitch follower</b></p>
<p class="p4"><br></p>
<p class="p5"><b>#freq, hasFreq = Qitch.kr(in, databufnum,ampThreshold, algoflag, ampbufnum, minfreq, maxfreq)</b></p>
<p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></p>
<p class="p5">This alternative pitch follower works in the frequency domain rather than Pitch's time domain correlation. Tradeoffs are made between latency and frequency resolution. It is meant to provide a relatively stable resultant tracked pitch based on a harmonic template. <span class="Apple-converted-space"> </span></p>
<p class="p4"><br></p>
<p class="p5">You must load one of the auxilliary data files into a Buffer and pass the bufnum to the routine. These files take the form:</p>
<p class="p4"><br></p>
<p class="p6"><span class="s1"><span class="Apple-converted-space"> </span></span>QspeckernN1024SR44100.wav</p>
<p class="p6"><span class="s1"><span class="Apple-converted-space"> </span></span>QspeckernN2048SR44100.wav</p>
<p class="p6"><span class="s1"><span class="Apple-converted-space"> </span></span>QspeckernN4096SR44100.wav</p>
<p class="p6"><span class="s1"><span class="Apple-converted-space"> </span></span>QspeckernN8192SR44100.wav</p>
<p class="p6"><span class="s1"><span class="Apple-converted-space"> </span></span>QspeckernN2048SR48000.wav</p>
<p class="p6"><span class="s1"><span class="Apple-converted-space"> </span></span>QspeckernN4096SR48000.wav</p>
<p class="p4"><br></p>
<p class="p5">Only use the one for your output sampling rate. Bigger N means more stability and resolution but longer delay and higher average CPU cost. N= 2048 is a good tradeoff if you don't want to track over 1000Hz fundamentals. The 48000 SR files are untested and provided without any promises.<span class="Apple-converted-space"> </span></p>
<p class="p4"><br></p>
<p class="p5"><b>in</b>- the audio rate input signal</p>
<p class="p5"><b>databufnum</b>- you must provide the initialisation data required by Qitch. This in the form of a .wav file that must be loaded to a buffer (see examples below).<span class="Apple-converted-space"> </span>The data files should have come with this UGen.<span class="Apple-converted-space"> </span></p>
<p class="p5"><b>ampThreshold</b>- Qitch outputs a 0 in hasFreq if the input amplitude is below this threshold. Same as original Pitch.<span class="Apple-converted-space"> </span></p>
<p class="p5"><b>algoflag</b>- 0 means use just the constant Q template pattern matcher. 1 flags the refinement based on the phase estimate.</p>
<p class="p5"><b>ampbufnum</b>- you may provide an 11 component buffer with template amplitudes- see example below.<span class="Apple-converted-space"> </span></p>
<p class="p5"><b>minfreq</b>- minimum output frequency in Hz</p>
<p class="p5"><b>maxfreq</b>- maximum output frequency in Hz</p>
<p class="p4"><br></p>
<p class="p5">In technical terms, this UGen calculates an FFT, applying Brown and Puckette's efficient constant Q transform on a quartertone scale, base note F3= 174.6Hz. Cross correlation search leads to the best match for a harmonic spectrum grid with falling amplitude components. A further fine tuning takes place based on instantaneous frequency estimation (rate of change of phase) for the winning FFT bin.<span class="Apple-converted-space"> </span></p>
<p class="p4"><br></p>
<p class="p5">The algorithms are based on the following papers:</p>
<p class="p4"><span class="Apple-converted-space"> </span></p>
<p class="p5">Judith C. Brown and Miller S. Puckette, 1992, An efficient algorithm for the calculation of a constant Q transform. Journal of the Acoustical Society of America. 92(5); 2698-701.</p>
<p class="p4"><span class="Apple-converted-space"> </span></p>
<p class="p5">Judith C. Brown, 1992, Musical Fundamental Frequency Tracking Using a Pattern Recognition Method. Journal of the Acoustical Society of America. 92(3); 1394-402.</p>
<p class="p4"><span class="Apple-converted-space"> </span></p>
<p class="p5">Judith C. Brown and Miller S. Puckette, 1993, A High-Resolution Fundamental Frequency Determination Based on Phase Changes of the Fourier Transform. Journal of the Acoustical Society of America. 94(2); 662-7.</p>
<p class="p4"><span class="Apple-converted-space"> </span></p>
<p class="p4"><br></p>
<p class="p5"><b>Examples: (use headphones!)</b></p>
<p class="p4"><br></p>
<p class="p7">s = <span class="s2">Server</span>.local;</p>
<p class="p8"><br></p>
<p class="p9">//assumes data file is in SC home application directory; else provide full path</p>
<p class="p10"><span class="s3">b = </span><span class="s4">Buffer</span><span class="s3">.read(s, </span>"QspeckernN4096SR44100.wav"<span class="s3">);<span class="Apple-converted-space"> </span></span></p>
<p class="p11">//this line is absolutely essential! You must load the data required by the UGen!<span class="Apple-converted-space"> </span></p>
<p class="p12"><br></p>
<p class="p9"><span class="s3">b.numFrames </span>//it's not that much data</p>
<p class="p8"><br></p>
<p class="p8"><br></p>
<p class="p7">(</p>
<p class="p7">a= <span class="s2">SynthDef</span>(<span class="s5">"testqitch"</span>,{<span class="s2">arg</span> infreq=440;</p>
<p class="p7"><span class="Apple-tab-span"> </span><span class="s2">var</span> in, freq, hasFreq, out;</p>
<p class="p8"><span class="Apple-tab-span"> </span></p>
<p class="p7"><span class="Apple-tab-span"> </span>in=<span class="s2">SinOsc</span>.ar(infreq);</p>
<p class="p8"><span class="Apple-tab-span"> </span></p>
<p class="p7"><span class="Apple-tab-span"> </span># freq, hasFreq = <span class="s2">Qitch</span>.kr(in, b.bufnum,0.01,1);</p>
<p class="p8"><span class="Apple-tab-span"> </span></p>
<p class="p7"><span class="Apple-tab-span"> </span><span class="s2">Out</span>.ar(0,[<span class="s2">SinOsc</span>.ar(freq,0.1),in]);</p>
<p class="p7">}).play(s);</p>
<p class="p7">)</p>
<p class="p8"><br></p>
<p class="p7">a.set(<span class="s6">\infreq</span>,237);</p>
<p class="p8"><br></p>
<p class="p8"><br></p>
<p class="p8"><br></p>
<p class="p13"><span class="s3">c=</span><span class="s2">Buffer</span><span class="s3">.read(s,</span><span class="s5">"/Volumes/data/audio/nikkisitar/warmup.wav"</span><span class="s3">); </span>//sitar test file, try anything you have on your disk</p>
<p class="p8"><br></p>
<p class="p7">c.numFrames</p>
<p class="p8"><br></p>
<p class="p13"><span class="s3">( </span>//sample tracking</p>
<p class="p6"><span class="s2">SynthDef</span><span class="s3">(</span>"pitchFollow1"<span class="s3">,{</span></p>
<p class="p7"><span class="Apple-tab-span"> </span><span class="s2">var</span> in, amp, freq, hasFreq, out;</p>
<p class="p8"><span class="Apple-tab-span"> </span></p>
<p class="p7"><span class="Apple-tab-span"> </span>in = <span class="s2">PlayBuf</span>.ar(1,c.bufnum, loop:1);</p>
<p class="p7"><span class="Apple-tab-span"> </span>amp = <span class="s2">Amplitude</span>.kr(in, 0.05, 0.05);</p>
<p class="p8"><span class="Apple-tab-span"> </span></p>
<p class="p7"><span class="Apple-tab-span"> </span># freq, hasFreq = <span class="s2">Qitch</span>.kr(in, b.bufnum, 0.1,1, -1,261, 800 );</p>
<p class="p8"><span class="Apple-tab-span"> </span></p>
<p class="p7"><span class="Apple-tab-span"> </span>out = <span class="s2">Mix</span>.new(<span class="s2">VarSaw</span>.ar(freq * [0.5,1,2], 0, <span class="s2">LFNoise1</span>.kr(0.3,0.1,0.1), amp));</p>
<p class="p8"><span class="Apple-tab-span"> </span></p>
<p class="p7"><span class="Apple-tab-span"> </span><span class="s2">Out</span>.ar(0,[out,in])</p>
<p class="p7">}).play(s);</p>
<p class="p7">)</p>
<p class="p8"><br></p>
<p class="p8"><br></p>
<p class="p14"><span class="s3">b = </span><span class="s2">Buffer</span><span class="s3">.read(s, </span><span class="s5">"QspeckernN2048SR44100.wav"</span><span class="s3">); </span>//quicker response with this data set</p>
<p class="p8"><br></p>
<p class="p13"><span class="s3">d = </span><span class="s2">Buffer</span><span class="s3">.alloc(s,11); </span>//make an amp template</p>
<p class="p15">d.setn(0, [1,0.98,0.92,0.88,0.84,0.8,0.76,0.72,1.68,1.64,1.6]); <span class="s7">//must have 11 components</span></p>
<p class="p8"><br></p>
<p class="p13">//analogous to example in the Pitch helpfile<span class="Apple-converted-space"> </span></p>
<p class="p7">(</p>
<p class="p6"><span class="s2">SynthDef</span><span class="s3">(</span>"pitchFollow1"<span class="s3">,{</span></p>
<p class="p7"><span class="Apple-tab-span"> </span><span class="s2">var</span> in, amp, freq, hasFreq, out;</p>
<p class="p7"><span class="Apple-tab-span"> </span>in = <span class="s2">Mix</span>.new(<span class="s2">AudioIn</span>.ar([1,2]));</p>
<p class="p7"><span class="Apple-tab-span"> </span>amp = <span class="s2">Amplitude</span>.kr(in, 0.05, 0.05);</p>
<p class="p7"><span class="Apple-tab-span"> </span># freq, hasFreq = <span class="s2">Qitch</span>.kr(in, b.bufnum, 0.02, 1, d.bufnum, 160, 880);</p>
<p class="p8"><span class="Apple-tab-span"> </span></p>
<p class="p13"><span class="s3"><span class="Apple-tab-span"> </span></span>//freq = Lag.kr(freq.cpsmidi.round(1).midicps, 0.05);</p>
<p class="p7"><span class="Apple-tab-span"> </span>out = <span class="s2">Mix</span>.new(<span class="s2">VarSaw</span>.ar(freq * [0.5,1,2], 0, <span class="s2">LFNoise1</span>.kr(0.3,0.1,0.1), amp));</p>
<p class="p7"><span class="Apple-tab-span"> </span>6.do({</p>
<p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>out = <span class="s2">AllpassN</span>.ar(out, 0.040, [0.040.rand,0.040.rand], 2)</p>
<p class="p7"><span class="Apple-tab-span"> </span>});</p>
<p class="p7"><span class="Apple-tab-span"> </span><span class="s2">Out</span>.ar(0,out)</p>
<p class="p7">}).play(s);</p>
<p class="p7">)</p>
<p class="p8"><br></p>
<p class="p8"><br></p>
<p class="p4"><br></p>
<p class="p4"><br></p>
</body>
</html>
|