/*
there are two different ways to get soundfiles into SC:

1. loading a soundfile completely into a Buffer (RAM) and playing it afterwards 
-> many playback option and suitable for short files

2. loading a soundfile piecewise into a Buffer (streaming) and playing it at the same time 
-> less playback options but suitable for very long files

*/

// 1st method (memory playback)

// 1. step:  
// load a soundfile into a buffer in the server:
b = Buffer.loadDialog(s);   // for now only mono soundfiles!

// alternative way (adapt it to your path names!) :
b = Buffer.readChannel(s, "/Users/abart/snd/tam-tam.aif", channels: [0]);

// check it if needed:
b.query
b.play
b.plot

// the duration of the soundfile:
b.duration
// or
b.numFrames / b.sampleRate

// the buffer number (essential as reference within synthdefs)
b.bufnum

/*
a note on Buffer objects and buffers on the server:

above b is representing an instance of the class Buffer
-> it is nothing but an object in sclang, not the soundfile itself!

a buffer on the server is identified by a number (corresponding to Buffers bufnum)
-> on the server a buffer is an array of float numbers containing the sample data

the class Buffer and its instances communicate with the server in order to load soundfiles, 
empty and free buffers on the server and do all the bookkeeping

see Buffer.html, Glossary.html, Server-Architecture.html, ClientVsServer.html

*/

// list all buffers on the server:
s.cachedBuffersDo { arg buf; [buf.bufnum, buf.path].postln }

// 2. step: 
// write a synthdef with a bufnum as an argument:
// reminder: the numChannels argument of PlayBuf must be set
// to the number of channels of the buffer that your are going to use

(
SynthDef("sndtest", { arg buf=0, rate=1, loop=1, amp=1.0; 
	var sig;
	sig = PlayBuf.ar(1, buf, rate * BufRateScale.ir(buf), loop: loop);  
	sig = sig * amp;
	Out.ar(0, sig);
	}).store;
)	
	
// 3. step: 
// start a synth and set the argument buf to the actual bufnum of b	
	
y = Synth("sndtest", [buf: b.bufnum]);	
y.set(\rate, 2.4);
y.set(\rate, -1);	
y.set(\loop, 0);	

y.free;	
	
// in order to free the synth when PlayBufs is finished
// you can use the UGen FreeSelfWhenDone:
	
(
SynthDef("sndtest2", { arg buf=0, rate=1, loop=1, amp=1.0; 
	var sig;
	sig = PlayBuf.ar(1, buf, rate * BufRateScale.ir(buf), loop: loop);  
	FreeSelfWhenDone.kr(sig);
	sig = sig * amp;
	Out.ar(0, sig);
	}).play(s, [buf: b.bufnum, loop: 0]);
)	
	
// ... the synth node kills itself after playing

// other UGens that can play buffers:

(
y = SynthDef("sndtest3", { arg buf=0, amp=1.0; 
	var sig, phase;
	phase = LFDNoise3.ar(MouseY.kr(0.1, 20, \exponential)).range(0, BufFrames.ir(buf));
	sig = BufRd.ar(1, buf, phase, 1, 4);  
	sig = sig * amp;
	Out.ar(0, sig);
	}).play(s, [buf: b.bufnum]);
)	

( // TGrains numChannels argument refers to the number of outputs!!!
y = SynthDef("sndtest4", { arg buf=0, rate=1.0, amp=1.0; 
	var sig, trig, pos, dur, pan;
	trig = Impulse.kr(MouseY.kr(8, 100, \exponential));
	pos = MouseX.kr(0, BufDur.ir(buf));
	dur = 0.1;
	pan = WhiteNoise.kr;
	sig = TGrains.ar(2, trig, buf, rate + WhiteNoise.kr(0.02), pos, dur, pan, amp );  
	Out.ar(0, sig);
	}).play(s, [buf: b.bufnum]);
)	

( 
y = SynthDef("sndtest4b", { arg buf=0, rate=1, amp=1.0; 
	var sig, trig, pos, dur, pan, chord, diff;
	trig = Impulse.kr(60);
	pos = MouseX.kr(0, BufDur.ir(buf));
	dur = 0.1;
	diff = MouseY.kr(0.01, 1.0, \exponential);
	chord = [0, 7, 13].midiratio * rate;
	sig = chord.collect { arg c; 
		TGrains.ar(2, trig, buf, c + WhiteNoise.kr(diff), pos, dur, WhiteNoise.kr, amp ) 
	};  
	Out.ar(0, sig.sum * chord.size.reciprocal);
	}).play(s, [buf: b.bufnum]);
)	

// 2nd method (streaming)

// 1. step:  
// load a soundfile into a buffer in the server:
b = Buffer.cueSoundFile(s, "sounds/a11wlk01-44_1.aiff", 0, 1)    ;  

// only a fragment is loaded !
b.query
b.play
b.plot

// 2. step: 
// write a synthdef with a bufnum as an argument:
// reminder: the numChannels argument of DiskIn must be set
// to the number of channels of the buffer that your are going to use

(
SynthDef("streamtest", { arg buf=0, amp=1.0; 
	var sig;
	sig = DiskIn.ar(1, buf, 0);  
	sig = sig * amp;
	Out.ar(0, sig);
	}).store;
)	
	
// 3. step: 
// start a synth and set the argument buf to the actual bufnum of b	
y = Synth("streamtest", [buf: b.bufnum]);	

y.free;	

// 4. step:
// in order to play it again you have to cue the buffer again from start!
b.close;
b.cueSoundFile("sounds/a11wlk01-44_1.aiff", 0);
y = Synth("streamtest", [buf: b.bufnum]);	
y.free;	
// and so on ...

// -> if you have enough RAM use PlayBuf and the likes for more flexibility !