File: Qitch.schelp

package info (click to toggle)
supercollider-sc3-plugins 3.7.1~repack-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 14,332 kB
  • ctags: 11,704
  • sloc: cpp: 140,180; lisp: 14,746; ansic: 2,133; xml: 86; makefile: 82; haskell: 21; sh: 8
file content (134 lines) | stat: -rw-r--r-- 4,593 bytes parent folder | download | duplicates (4)
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
class:: Qitch
summary:: constant Q transform pitch follower
related:: Classes/Tartini, Classes/Pitch
categories:: UGens>Analysis>Pitch


Description::

This alternative pitch follower works in the frequency domain rather than link::Classes/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.

note::
You must load one of the auxilliary data files into a link::Classes/Buffer:: and pass the bufnum to the routine. These files take the form:

list::
## QspeckernN1024SR44100.wav
## QspeckernN2048SR44100.wav
## QspeckernN4096SR44100.wav
## QspeckernN8192SR44100.wav
## QspeckernN2048SR48000.wav
## QspeckernN4096SR48000.wav
::

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.
::

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.

The algorithms are based on the following papers:

Judith C. Brown and Miller S. Puckette, 1992, emphasis::"An efficient algorithm for the calculation of a constant Q transform"::. Journal of the Acoustical Society of America. 92(5); 2698-701.

Judith C. Brown, 1992, emphasis::"Musical Fundamental Frequency Tracking Using a Pattern Recognition Method"::. Journal of the Acoustical Society of America. 92(3); 1394-402.

Judith C. Brown and Miller S. Puckette, 1993, emphasis::"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.


Classmethods::

method::kr

argument::in
the audio rate input signal

argument::databufnum
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).  The data files should have come with this UGen.

argument::ampThreshold
Qitch outputs a 0 in strong::hasFreq:: if the input amplitude is below this threshold. Same as original link::Classes/Pitch::.

argument::algoflag
0 means use just the constant Q template pattern matcher. 1 flags the refinement based on the phase estimate.

argument::ampbufnum
you may provide an 11 component buffer with template amplitudes- see example below.

argument::minfreq
minimum output frequency in Hz

argument::maxfreq
maximum output frequency in Hz


Examples::

(use headphones!)

code::
s = Server.local;

//assumes data file is in SC home application directory; else provide full path
b = Buffer.read(s, "QspeckernN4096SR44100.wav");
//this line is absolutely essential! You must load the data required by the UGen!

b.numFrames //it's not that much data


(
a= SynthDef("testqitch",{arg infreq=440;
	var in, freq, hasFreq, out;

	in=SinOsc.ar(infreq);

	# freq, hasFreq = Qitch.kr(in, b.bufnum,0.01,1);

	Out.ar(0,[SinOsc.ar(freq,0.1),in]);
}).play(s);
)

a.set(\infreq,237);



c=Buffer.read(s,"/Volumes/data/audio/nikkisitar/warmup.wav"); //sitar test file, try anything you have on your disk

c.numFrames

( //sample tracking
SynthDef("pitchFollow1",{
	var in, amp, freq, hasFreq, out;

	in = PlayBuf.ar(1,c.bufnum, loop:1);
	amp = Amplitude.kr(in, 0.05, 0.05);

	# freq, hasFreq = Qitch.kr(in, b.bufnum, 0.1,1, -1,261, 800 );

	out = Mix.new(VarSaw.ar(freq * [0.5,1,2], 0, LFNoise1.kr(0.3,0.1,0.1), amp));

	Out.ar(0,[out,in])
}).play(s);
)


b = Buffer.read(s, "QspeckernN2048SR44100.wav"); //quicker response with this data set

d = Buffer.alloc(s,11); //make an amp template
d.setn(0, [1,0.98,0.92,0.88,0.84,0.8,0.76,0.72,1.68,1.64,1.6]); //must have 11 components

//analogous to example in the Pitch helpfile
(
SynthDef("pitchFollow1",{
	var in, amp, freq, hasFreq, out;
	in = Mix.new(SoundIn.ar([0,1]));
	amp = Amplitude.kr(in, 0.05, 0.05);
	# freq, hasFreq = Qitch.kr(in, b.bufnum, 0.02, 1, d.bufnum, 160, 880);

	//freq = Lag.kr(freq.cpsmidi.round(1).midicps, 0.05);
	out = Mix.new(VarSaw.ar(freq * [0.5,1,2], 0, LFNoise1.kr(0.3,0.1,0.1), amp));
	6.do({
		out = AllpassN.ar(out, 0.040, [0.040.rand,0.040.rand], 2)
	});
	Out.ar(0,out)
}).play(s);
)
::