// a not that serious sound example for the use of the Vowel class

// 2011 Till Bovermann, using and altering a code example from the Vowel helpfile written by Florian Grond.


q = ();


NdefMixer(s)


(

q.freqs = {|i| 50 * 1.5.pow(i) }!9;

q.dt = 1.5 * 2.sqrt;

q.numHarms = 60;

)


(

SynthDef(\impulser, {|out = 0, pan = 0, dur = 35|

var amps = \amps.ir(1!q.numHarms);

var signal = Klank.ar(

`[q.freqs,amps,amps],

Decay.ar(

Impulse.ar( exp(1)/5.0 ), 

SinOsc.kr( pi/9.0, 1.0.rand ).range(0.05,0.7) 

)

) * EnvGen.kr(

Env.new([-40,-20, -30,-40].dbamp, [2, 1, 2].normalizeSum,'exp'), 

timeScale: dur, levelScale: 0.5, doneAction: 2

).tanh;

Out.ar(out, Pan2.ar(signal, pan));

}).add

)


Ndef(\grainOut).ar

Ndef(\grainOut).play




Tdef(\player).quant = q.dt


(

Tdef(\player, {

var harms, amps;

loop{

harms = {|i| (i+1) * q.freqs.choose }!q.numHarms;

amps  = Vowel(

[\a,\e,\i,\o,\u].choose,

[\bass,\tenor,\counterTenor,\alto,\soprano].choose

).ampAt(harms);



Synth.grain(\impulser, [\amps, amps, \out, Ndef(\grainOut).bus.index, \pan, 1.0.rand2]);

q.dt.wait;

}

}).play;

)


Tdef(\player).play

Tdef(\player).stop





Ndef(\drone).fadeTime = 10;

Ndef(\drone).xsetn(\freqs, [1, 2, 3, 4, 5] * 100)

Ndef(\drone).xsetn(\freqs, [10, 9, 8, 7, 6] * 50)

Ndef(\drone).xsetn(\freqs, [1, 2, 3, 4, 5] * 50)

Ndef(\drone).xsetn(\freqs, q.freqs[0..4]);


(

Spec.add(\filterFreq, \freq);

Spec.add(\dbGain, [-6, 6, \db]);

Spec.add(\filterSlope, [0.1, 6, \db]);


Ndef(\drone, {|filterFreq = 440, filterSlope = 1, dbGain = 0|

var freqs, signal;

freqs = \freqs.kr([10, 9, 8, 7, 6] * 50);

signal = (Splay.ar(Formants.ar(freqs.scramble, Vowel([\i, \a, \u, \o]), unfold: true).flat.scramble) * 0.1).tanh;

HighShelf.ar(signal, filterFreq, filterSlope, dbGain)

})

)



(

Ndef(\vowel, {|filterFreq = 440, filterSlope = 1, dbGain = 0|

var signal;

signal = Formants.ar(

(LFNoise2.kr(exp(1) / 20).exprange(100, 400) + LFNoise0.kr(exp(1) / 40).exprange(100, 400)).round(50), 

Vowel(\o, \soprano)

.brightenExp(SinOsc.kr(exp(1) / 50).range(0,1), 1),

unfold: true

).mean * 0.5;

HighShelf.ar(signal, filterFreq, filterSlope, dbGain)

})

)