{
   "code" : "// Posted by Paul Miller\r\n// https://listarc.cal.bham.ac.uk/lists/sc-users-2016/msg52187.html\r\n\r\n//  code for building & testing IRs\r\n\r\n// setup\r\n(\r\ns.waitForBoot({\r\n\t{\r\n\t\t// init\r\n\t\t// free old buffers\r\n\t\tif (a.notNil, {\r\n\t\t\tif (a.buffer.notNil, {\r\n\t\t\t\ta.buffer.free;\r\n\t\t\t});\r\n\t\t\tif (a.target.notNil, {\r\n\t\t\t\ta.target.free;\r\n\t\t\t});\r\n\t\t\tif (a.irspectrum.notNil, {\r\n\t\t\t\ta.irspectrum.free;\r\n\t\t\t});\r\n\t\t});\r\n\t\ta = (); // settings dict\r\n\t\t//fft\r\n\t\ta.fftsize = 2048;\r\n\r\n\t\t// set target buffer for testing convolution with\r\n\t\ta.target= Buffer.read(s, Platform.resourceDir +/+ \"sounds/a11wlk01.wav\");\r\n\r\n\t\t// fill buffer using one of the following Examples:\r\n\r\n\t\t/*\r\n\t\t// ======= EX1 - create IR using dust & noise ======\r\n\t\t*/\r\n\t\t// CHANGE THESE SETTINGS:\r\n\t\ta.bufferTime = 3; // time in secs for new IR\r\n\t\ta.densityMin = 50; // min/max density of reflections\r\n\t\ta.densityMax = 500;\r\n\t\ta.filterFreqMin = 100; // min/max freq for filter sweep\r\n\t\ta.filterFreqMax = 8000;\r\n\t\tif (a.buffer.notNil, {\r\n\t\t\ta.buffer.free;\r\n\t\t});\r\n\t\ta.buffer = Buffer.alloc(s, s.sampleRate * a.bufferTime, 1);\r\n\t\ts.sync;\r\n\t\t// write into the buffer with a BufWr\r\n\t\ty = {\r\n\t\t\tvar sourceVolEnv, filterFreqEnv, densityEnv, source, filterFunc, outSound;\r\n\r\n\t\t\t// CHANGE ENVELOPES, SOURCE & FILTER SETTINGS\r\n\r\n\t\t\t//sourceVolEnv = EnvGen.kr(Env([1, 0], [a.bufferTime], -3), doneAction: 2);\r\n\t\t\t//sourceVolEnv = EnvGen.kr(Env([0, 1], [a.bufferTime], 3), doneAction: 2);  // reverse env\r\n\t\t\tsourceVolEnv = EnvGen.kr(Env([0.2, 1], [a.bufferTime], 6), doneAction: 2);  // reverse env\r\n\r\n\t\t\t// filterFreqEnv = EnvGen.kr(Env([1, 0], [a.bufferTime], -2),\r\n\t\t\t// levelScale: (a.filterFreqMax - a.filterFreqMin), levelBias: a.filterFreqMin, doneAction: 0);\r\n\t\t\tfilterFreqEnv = EnvGen.kr(Env([0, 1], [a.bufferTime], 6),\r\n\t\t\t\tlevelScale: (a.filterFreqMax - a.filterFreqMin), levelBias: a.filterFreqMin, doneAction: 0);  // reverse env\r\n\r\n\t\t\t// densityEnv = EnvGen.kr(Env([0, 1], [a.bufferTime], 2),\r\n\t\t\t// levelScale: (a.densityMax - a.densityMin), levelBias: a.densityMin, doneAction: 0);\r\n\t\t\tdensityEnv = EnvGen.kr(Env([1, 0], [a.bufferTime], -2),\r\n\t\t\t\tlevelScale: (a.densityMax - a.densityMin), levelBias: a.densityMin, doneAction: 0);  // reverse env\r\n\r\n\t\t\tsource = Dust.ar(densityEnv, 0.5) * WhiteNoise.ar;\r\n\t\t\t// source = Dust.ar(densityEnv, 0.5) * PinkNoise.ar;\r\n\t\t\t// source = Dust.ar(densityEnv, 0.5) * GrayNoise.ar;\r\n\r\n\t\t\t// filterFunc = {arg in, freq; LPF.ar(in, freq) };\r\n\t\t\t// filterFunc = {arg in, freq; HPF.ar(in, freq) };\r\n\t\t\tfilterFunc = {arg in, freq;\r\n\t\t\t\tvar allPass;\r\n\t\t\t\t//LPF.ar(in + AllpassC.ar(in, 0.1, 0.01, 0.5, mul: 0.75), freq);\r\n\t\t\t\t//LPF.ar(in + AllpassC.ar(in, 0.1, 0.1, 0.5, mul: 0.75), freq);\r\n\t\t\t\t//LPF.ar(in + AllpassC.ar(in, 0.01, XLine.kr(0.0001, 0.01, a.bufferTime), 0.2), freq);\r\n\t\t\t\tLPF.ar(in + AllpassC.ar(in * 0.5, 0.2, XLine.kr(0.001, 0.2, a.bufferTime), 0.5, mul: 0.5), freq);\r\n\t\t\t};\r\n\r\n\t\t\toutSound = filterFunc.value(sourceVolEnv * source, filterFreqEnv) * 100 / densityEnv;  // adjust volume with density\r\n\r\n\t\t\t// record buffer\r\n\t\t\tBufWr.ar(outSound, a.buffer, Phasor.ar(0, BufRateScale.kr(a.buffer), 0,\r\n\t\t\t\tBufFrames.kr(a.buffer)), loop: 0);\r\n\r\n\t\t\toutSound ! 2;\r\n\t\t}.play;\r\n\t\t// =======\r\n\r\n\t\t/*\r\n\t\t// ======= EX2 - load file from disk - MONO ONLY    ======\r\n\t\tif (a.buffer.notNil, {\r\n\t\t\ta.buffer.free;\r\n\t\t});\r\n\t\ta.buffer = Buffer.read(s, \"/path/to/monoSoundFile.wav\");  // e.g.\r\n\t\t//a.buffer = Buffer.read(s, \"/Users/paul/TESTING/TestSamples/_impulses/SavedImpulse_20160831222540.aif\");\r\n\t\t// =======\r\n\t\t*/\r\n\r\n\r\n\t\t/*\r\n\t\t// ======= EX3 - load file from disk & reverse it - MONO ONLY    ======\r\n\t\tif (a.buffer.notNil, {\r\n\t\t\ta.buffer.free;\r\n\t\t});\r\n\t\t// a.buffer = Buffer.read(s, \"/path/to/monoSoundFile.wav\");  // e.g.\r\n\t\t// a.buffer = Buffer.read(s, \"/Users/paul/TESTING/TestSamples/_impulses/LexiconHallMono1.wav\");\r\n\t\ta.buffer = Buffer.read(s, \"/Users/paul/TESTING/TestSamples/_impulses/FactoryHallMono.wav\");\r\n\t\ts.sync;\r\n\t\ta.buffer.loadToFloatArray(action: { arg array; a.floatArray = array.reverse; });\r\n\t\ts.sync;\r\n\t\t2.wait;\r\n\t\ta.buffer.free;\r\n\t\ta.buffer = Buffer.loadCollection(s, a.floatArray);\r\n\t\t*/\r\n\t\t// =======\r\n\r\n\r\n\t\t/*\r\n\t\t//  =======  EX4 - build buffer from floatArray - taken from PartConv help file\r\n\t\t// synthesise the honourable 'Dan Stowell' impulse response\r\n\t\ta.ir = ([1] ++0.dup(100) ++ ((1, 0.99998 .. 0).collect{|f| f =\r\n\t\tf.squared.squared; f = if(f.coin){0}{f.squared}; f =\r\n\t\tif(0.5.coin){0-f}{f} } * 0.1)\r\n\t\t).normalizeSum;\r\n\t\ta.ir = a.ir.reverse; // added for backwards reverb\r\n\t\tif (a.buffer.notNil, {\r\n\t\ta.buffer.free;\r\n\t\t});\r\n\t\ta.buffer = Buffer.loadCollection(s, a.ir);\r\n\t\t// a.ir.plot;\r\n\t\t*/\r\n\t\t// =======\r\n\r\n\r\n\t\ts.sync;\r\n\t\t\"Setup Completed\".postln;\r\n\r\n\t}.fork;\r\n});\r\n)\r\n//////////////////////////////////////////////////////\r\n\r\n// prepare irspectrum buffer\r\n(\r\n\t{\r\n\t\ts.sync;\r\n\t\ta.bufsize = PartConv.calcBufSize(a.fftsize, a.buffer);\r\n\t\tif (a.irspectrum.notNil, {\r\n\t\t\ta.irspectrum.free;\r\n\t\t});\r\n\t\ta.irspectrum = Buffer.alloc(s, a.bufsize, 1);\r\n\t\ta.irspectrum.preparePartConv(a.buffer, a.fftsize);\r\n\t\ts.sync;\r\n\t\t\"Prepare Buffer Completed\".postln;\r\n\t}.fork;\r\n)\r\n//////////////////////////////////////////////////////\r\n\r\n\r\n// examples to use the IR - all are mono, but duplicated in left/right speaker (using ! 2)\r\n\r\n// convolve with target soundfile\r\n(\r\n{ var input, convLevel = 0.6;\r\n\tinput = PlayBuf.ar(1, a.target.bufnum, loop:1);\r\n\tOut.ar(0, (convLevel * PartConv.ar(input, a.fftsize, a.irspectrum.bufnum, 0.5)) ! 2);\r\n}.play;\r\n)\r\n\r\n// convolve with target soundfile adding  input\r\n(\r\n{ var input, delayTime, inputDelay, inputLevel = 0.5, convLevel = 0.5;\r\n\tinput = PlayBuf.ar(1, a.target, loop:1);\r\n\tOut.ar(0, ((inputLevel * input) + (convLevel * PartConv.ar(input, a.fftsize, a.irspectrum.bufnum, 0.5))) ! 2);\r\n}.play;\r\n)\r\n\r\n// convolve with target soundfile adding delayed input\r\n(\r\n{ var input, delayTime, inputDelay, inputLevel = 0.5, convLevel = 0.5;\r\n\tinput = PlayBuf.ar(1, a.target, loop:1);\r\n\tdelayTime =  BufFrames.ir(a.buffer.bufnum) / BufSampleRate.ir(a.buffer.bufnum);\r\n\tinputDelay = DelayC.ar(input * inputLevel, delayTime, delayTime);\r\n\tOut.ar(0, (inputDelay + (convLevel * PartConv.ar(input, a.fftsize, a.irspectrum.bufnum, 0.5))) ! 2);\r\n}.play;\r\n)\r\n\r\n\r\n// convolve with live input\r\n(\r\n{ var input, convLevel = 0.8;\r\n\tinput= SoundIn.ar(0);\r\n\tOut.ar(0, (convLevel * PartConv.ar(input, a.fftsize, a.irspectrum.bufnum)) ! 2);\r\n}.play;\r\n)\r\n\r\n// convolve with live input adding input\r\n(\r\n{ var input, inputLevel = 0.7, convLevel = 0.7;\r\n\tinput = SoundIn.ar(0);\r\n\tOut.ar(0, ((inputLevel * input) + (convLevel * PartConv.ar(input, a.fftsize, a.irspectrum.bufnum))) ! 2);\r\n}.play;\r\n)\r\n\r\n\r\n// convolve with live input adding delayed input\r\n(\r\n{ var input, delayTime, delayedInput, inputLevel = 0.7, convLevel = 0.7;\r\n\tinput = SoundIn.ar(0);\r\n\tdelayTime =  BufFrames.ir(a.buffer.bufnum) / BufSampleRate.ir(a.buffer.bufnum);\r\n\tdelayedInput = DelayC.ar(input, delayTime, delayTime);\r\n\tOut.ar(0, ((inputLevel * delayedInput) + (convLevel * PartConv.ar(input, a.fftsize, a.irspectrum.bufnum))) ! 2);\r\n}.play;\r\n)\r\n\r\n//////////////////////////////////////////////////////\r\n\r\n\r\n// save ir buffer to disk\r\n(\r\na.savedBufferName = \"/Users/paul/TESTING/TestSamples/_impulses/SavedImpulse_\"   // e.g.\r\n\t++ Date.getDate.asSortableString\r\n\t++ \".aif\";\r\na.buffer.write(a.savedBufferName,  headerFormat: \"aiff\", sampleFormat: \"int24\");\r\n(\"Saved buffer to disk. filename: \" ++ a.savedBufferName).postln;\r\n)\r\n\r\n//////////////////////////////////////////////////////\r\n\r\n\r\n// free buffers when finished\r\n(\r\nif (a.notNil, {\r\n\tif (a.buffer.notNil, {\r\n\t\ta.buffer.free;\r\n\t});\r\n\tif (a.target.notNil, {\r\n\t\ta.target.free;\r\n\t});\r\n\tif (a.irspectrum.notNil, {\r\n\t\ta.irspectrum.free;\r\n\t});\r\n});\r\n)",
   "is_private" : null,
   "id" : "1-5hf",
   "labels" : [
      "reverb",
      "convolution",
      "reverse",
      "ir",
      "fft",
      "impulse response",
      "reverse reverb",
      "realtime",
      "real time"
   ],
   "description" : "Boilerplate code for creating and testing convolution reverb and impulse responses",
   "ancestor_list" : [],
   "name" : "Convolution reverb and impulse responses",
   "author" : "zecraum"
}
