// title: freeze playback // author: LFSaw // description: // Explore options to freeze playback of a sound file // (a) by playhead movement // (b) by FFT freeze // code: q = q ? (); // load buffers // e.g. mono sound (see below) q.audioBuffer = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav"); ( Ndef(\freezePlayer).addSpec( \lpFreq, \freq, \hpFreq, \freq, \shift, [0.125, 4, \exp], \freezeRate, [10, 100, \exp], // how fast to go back and forth \rateDir, [-1, 1, \lin], // direction of movement in the buffer, if 1 or -1, use normal playback \rate, [0.125, 16, \exp], // how fast the buffer should play back/forth in normal mode \modSource, [0, 2, \lin, 0], // [SinOsc, LFPulse, LFTri] ); // make sure to check number of channels of the buffer(s) to be used Ndef(\freezePlayer, {|bufnum = 0| var numChannels = 1; var chain, efx; var rateDir = \rateDir.kr(0); // var wet = \wet.kr(0) > 0; var wet = rateDir.abs < 1; var rateScale = BufRateScale.kr(bufnum); // possible modulation sources are e.g. LFPulse, LFTri, SinOsc.. // for the system to work properly, the integrated signal should be 0, (i.e. going equal parts backwards and forwards). var modSource = LinSelectX.kr(\modSource.kr(0), [ SinOsc.kr(\freezeRate.kr(20), phase: 0).range(-1, 1), LFPulse.kr(\freezeRate.kr(20), iphase: 0).range(-1, 1), LFTri.kr(\freezeRate.kr(20), iphase: 0).range(-1, 1) ]); var rateFX = ( ((1-wet) * rateDir.sign) // normal playback + (wet * (modSource + rateDir)) // "freeze" ) * \rate.kr(1) * rateScale; var snd = PlayBuf.ar( numChannels: numChannels, bufnum: bufnum, rate: rateFX, trigger: \trig.tr(1), loop: 1 ); snd = LPF.ar(HPF.ar(snd, \hpFreq.kr(10)), \lpFreq.kr(10000)); }); ); Ndef(\freezePlayer).set(\bufnum, q.audioBuffer.bufnum); Ndef(\freezePlayer).edit; // q.audioBuffer.play //////////////// frequency-domain ( Ndef(\freezePlayerFFT).addSpec( \lpFreq, \freq, \hpFreq, \freq, \wet, [0, 1, \lin, 1], \frShift, [0.25, 4, \exp], \frDiff, [0, 1, \lin, 1] ); Ndef(\freezePlayerFFT, {|bufnum = 0| var numChannels = 1; var chain, efx; var wet = \wet.kr(0) > 0; var buffer = q.audioBuffer; var snd = PlayBuf.ar( numChannels: numChannels, bufnum: bufnum, rate: \rate.kr(1) * BufRateScale.kr(bufnum) * (1-wet), trigger: \trig.tr(1), loop: 1 ); // FFT processing chain = FFT(LocalBuf(4096), snd); // encode to frequency domain chain = PV_Diffuser(chain, \frDiff.kr(0) * wet); chain = PV_Freeze(chain, wet); chain = PV_BinShift(chain, \frShift.kr(1)); efx = IFFT(chain); // decode to time domain snd = Select.ar(wet, [snd, efx]); // snd = efx; snd = LPF.ar(HPF.ar(snd, \hpFreq.kr(10)), \lpFreq.kr(10000)); }); ) Ndef(\freezePlayerFFT).set(\bufnum, q.audioBuffer.bufnum); Ndef(\freezePlayerFFT).play Ndef(\freezePlayerFFT).edit