Skip to content

Instantly share code, notes, and snippets.

@schollz
Created July 5, 2024 17:37
Show Gist options
  • Save schollz/35accc76234ff22961ed45a7ad38c418 to your computer and use it in GitHub Desktop.
Save schollz/35accc76234ff22961ed45a7ad38c418 to your computer and use it in GitHub Desktop.
// var f = FoldersOfSound.new(Server.default);
// var server2 = Server.new(name, "192.168.0.24:57110", options, clientID)
// var f2 = FolderOfSound.new(server2);
// (
// s.waitForBoot({
// ~bikes=FoldersOfSound.new(s);
// ~birds=FoldersOfSound.new(s);
// });
// )
// (
// ~birds.playFolder(...)
// ~birds.remove(1);
// )
// (
// ~bikes.playFolder(...);
// ~bikes.setFadeIn(5.0);
// )
// (Routine {
// inf.do{
// 10.wait;
// ~bikes.remove(1);
// 30.wait;
// ~birds.setFadeIn(4);
// };
// }.play;)
FoldersOfSound {
var server;
var bufs;
var buses;
var syns;
var synlist;
var oscs;
var playi;
var fadein;
var fadeout;
var panRange;
var ampRange;
var randomSelection;
*new {
arg argServer;
^super.new.init(argServer);
}
playFolder {
arg folder, num;
var files = PathName.new(folder);
var audioFiles = [];
files.filesDo({arg file;
if (file.fullPath.endsWith(".ogg"),{
audioFiles=audioFiles.add(file.fullPath);
});
if (file.fullPath.endsWith(".wav"),{
audioFiles=audioFiles.add(file.fullPath);
});
if (file.fullPath.endsWith(".flac"),{
audioFiles=audioFiles.add(file.fullPath);
});
// if you have SuperCollider 3.13+ you can use mp3 files
// if (file.fullPath.endsWith(".mp3"),{
// audioFiles=audioFiles.add(file.fullPath);
// });
});
("[playFolder] loaded"+audioFiles.size+"files from"+folder).postln;
if (randomSelection>0,{
("[playFolder] playing random").postln;
// random selection
audioFiles.scramble.do({ arg v,i;
if (i<num,{
[i,v].postln;
this.play(v);
});
})
},{
("[playFolder] playing ordered").postln;
num.do({
if (playi>=audioFiles.size,{
playi=0;
});
this.play(audioFiles[playi]);
playi = playi+1;
});
});
}
remove {
arg num;
num.do({ arg i;
if (synlist.size>0,{
this.stop(synlist[0]);
});
});
}
stop {
arg fname;
if (syns.at(fname).notNil,{
var remove=1.neg;
if (syns.at(fname).isRunning,{
("stopping"+fname).postln;
syns.at(fname).set(\gate,0);
});
syns.put(fname,nil);
synlist.do({arg v,i;
if (v.asString==fname.asString,{
remove=i;
});
});
if (remove>1.neg,{
("dequeued"+fname).postln;
synlist.removeAt(remove);
});
});
}
play {
arg fname;
// the maximum number sounds is 10
// you could change to >10
if (synlist.size<10,{
["[play] playing ",fname].postln;
if (bufs.at(fname).isNil,{
bufs.put(fname,Buffer.read(server,fname,0,-1,action:{
"loooping audio file".postln;
syns.put(fname,Synth.before(syns.at("fx"),"looper"++bufs.at(fname).numChannels,[\ampRange,ampRange,\panRange,panRange,\fadein,fadein,\fadeout,fadeout,\buf,bufs.at(fname),\busReverb,buses.at("busReverb"),\busNoCompress,buses.at("busNoCompress"),\busCompress,buses.at("busCompress")]).onFree({
}));
NodeWatcher.register(syns.at(fname));
}));
},{
// only allow one sample of one kind to play at once
this.stop(fname);
syns.put(fname,Synth.before(syns.at("fx"),"looper"++bufs.at(fname).numChannels,[\ampRange,ampRange,\panRange,panRange,\fadein,fadein,\fadeout,fadeout,\buf,bufs.at(fname),\busReverb,buses.at("busReverb"),\busNoCompress,buses.at("busNoCompress"),\busCompress,buses.at("busCompress")]).onFree({
}));
NodeWatcher.register(syns.at(fname));
});
synlist=synlist.add(fname);
});
}
sound_delta {
arg folder, num;
if (num>0,{
this.playFolder(folder,num);
});
if (num<0,{
this.remove(num);
});
}
setAmpRange {
arg ampRange;
syns.keysValuesDo({ arg k, syn;
if (syn.isRunning,{
syn.set(\ampRange,ampRange);
});
});
}
setPanRange {
arg panRange;
syns.keysValuesDo({ arg k, syn;
if (syn.isRunning,{
syn.set(\panRange,panRange);
});
});
}
setOrdered {
arg ordered;
randomSelection = ordered;
}
setFadeIn {
arg argFadeIn;
fadein=argFadeIn;
}
setFadeOut {
arg argFadeOut;
fadeout = argFadeOut;
syns.keysValuesDo({ arg k, syn;
if (syn.isRunning,{
syn.set(\fadeout,fadeout);
});
});
}
setp {
arg parm, value;
syns.keysValuesDo({ arg k, syn;
if (syn.isRunning,{
syn.set(parm.asString,value);
});
});
}
// ~bikes.getNumber.postln;
// ~bikes.getNumber
// if (~bikes.getNumber>3,{
// ~bikes.remove(1);
// }, { // if false });
getNumber {
^synlist.size;
}
init {
arg argServer;
server=argServer;
playi = 0;
// default parameters for creating a synth
randomSelection = 1;
fadein=5.0;
fadeout=5.0;
ampRange=9.neg;
panRange=0.25;
// a simple SynthDef
// SynthDef("sine",{
// Out.ar(0,SinOsc.ar(440,0,0.1));
// }).add;
// Synth("sine")
// basic players
SynthDef("fx",{
arg busReverb,busCompress,busNoCompress;
var snd;
var sndReverb=In.ar(busReverb,2);
var sndCompress=In.ar(busCompress,2);
var sndNoCompress=In.ar(busNoCompress,2);
sndCompress=Compander.ar(sndCompress,sndCompress,0.05,slopeAbove:0.1,relaxTime:0.01);
sndNoCompress=Compander.ar(sndNoCompress,sndNoCompress,1,slopeAbove:0.1,relaxTime:0.01);
// change between Freverb2 or maybe Greyhole ?
sndReverb=FreeVerb2.ar(sndReverb[0],sndReverb[1],1.0,0.7);
// sndReverb = Greyhole.ar()
snd=sndCompress+sndNoCompress+sndReverb;
// if you have clipping you can prevent it with some wavefolders
// snd = snd / 10; // reduce the sound level
// snd = snd * -10.dbamp; // reduce by 10 db
// snd = Clip.ar(snd,-1,1); // clipping
// snd = snd.dist; // distortion
// snd = snd.tanh; // tanh wavefolder
// snd = Fold.ar(snd); // folding
Out.ar(0,snd*Line.ar(0,1,3));
}).add;
SynthDef("looper1",{
arg buf,busReverb,busCompress,busNoCompress,gate=1,rateMult=1.0,db=0.0,timescalein=0.05,fadein=5,fadeout=5,panRange=0.25,ampRange=9.neg;
var sndl,sndr;
var timescale = 1.0 / timescalein;
var snd=PlayBuf.ar(1,buf,rate:rateMult*BufRateScale.kr(buf),loop:1,trigger:Impulse.kr(0),startPos:BufFrames.ir(buf)*Rand(0,1));
//var lr=(0.8*LFNoise2.kr(1/timescale))+(0.1*LFNoise2.kr(10/timescale));
// try changing LFNoise2 to SinOsc or LFTri or LFSaw or LFPulse
// lr stands for left right
var lr = SinOsc.kr(1); // oscillating 1/second
// fb stands from front back
var fb=LFNoise2.kr(1/timescale)+(0.1*LFNoise2.kr(10/timescale));
var amp=(db+LinLin.kr(LFNoise2.kr(1/timescale)+(0.1*LFNoise2.kr(10/timescale)),1.1.neg,1.1,ampRange,0)).dbamp;
var pan=lr*panRange;
lr = Clip.kr(lr,-1,1);
fb = Clip.kr(fb,-1,1);
amp = Clip.kr(amp,-64,12);
pan = Clip.kr(pan,-1,1);
snd=HPF.ar(snd,LinLin.kr(fb,-1,1,20,1000));
sndl=snd;
sndr=snd;
// "Play point" to increase filtering change "100" to between 0 and 100
sndl=LPF.ar(sndl,LinLin.kr(lr,-1,1,135,100).midicps);
sndr=LPF.ar(sndr,LinLin.kr(lr,-1,1,100,135).midicps);
// try increasing the delay from 0.03 to something higher
sndl=SelectX.ar(((lr>0.1)*lr.abs),[sndl,DelayN.ar(sndl,0.03,Rand(0.0,0.03))]);
sndr=SelectX.ar(((lr<0.1.neg)*lr.abs),[sndr,DelayN.ar(sndr,0.03,Rand(0.0,0.03))]);
snd=Balance2.ar(sndl,sndr,pan,amp)*Line.kr(0,1,1);
// doneAction:2 means free the synth when the envelope is done
amp = amp * EnvGen.ar(Env.adsr(fadein,1,1,fadeout,curve:[4,4]),gate,doneAction:2);
snd=snd*amp;
// if you anticipate having 10+ sounds you can scale the amplitude so the
// mix doesn't overload
// snd = snd / 10; // where 10 is the number of sounds you anticipate having
// SendReply.kr(Impulse.kr(10),"/position",[buf,lr,fb,amp]);
// first send sound to compression bus
Out.ar(busCompress,(fb+1)/2*snd);
// then send sound to bus that doesn't do compression
Out.ar(busNoCompress,(1-((fb+1)/2))*snd);
// then send sound to reverb bus
// increase reverb by increasing 0.1 to 1?
Out.ar(busReverb,LinExp.kr(fb,1,-1,0.01,0.1)*snd);
}).add;
SynthDef("looper2",{
arg buf,busReverb,busCompress,busNoCompress,gate=1,rateMult=1.0,db=0.0,timescalein=0.05,fadein=5,fadeout=5,panRange=0.25,ampRange=9.neg;
var sndl,sndr;
var timescale = 1.0 / timescalein;
var snd=PlayBuf.ar(2,buf,rate:rateMult*BufRateScale.kr(buf),loop:1,trigger:Impulse.kr(0),startPos:BufFrames.ir(buf)*Rand(0,1));
var lr=(0.8*LFNoise2.kr(1/timescale))+(0.1*LFNoise2.kr(10/timescale));
var fb=LFNoise2.kr(1/timescale)+(0.1*LFNoise2.kr(10/timescale));
var amp=(db+LinLin.kr(LFNoise2.kr(1/timescale)+(0.1*LFNoise2.kr(10/timescale)),1.1.neg,1.1,ampRange,0)).dbamp;
var pan=lr*panRange;
lr = Clip.kr(lr,-1,1);
fb = Clip.kr(fb,-1,1);
amp = Clip.kr(amp,-64,12);
pan = Clip.kr(pan,-1,1);
snd=HPF.ar(snd,LinLin.kr(fb,-1,1,20,1000));
sndl=snd[0];
sndr=snd[1];
sndl=LPF.ar(sndl,LinLin.kr(lr,-1,1,135,100).midicps);
sndr=LPF.ar(sndr,LinLin.kr(lr,-1,1,100,135).midicps);
sndl=SelectX.ar(((lr>0.1)*lr.abs),[sndl,DelayN.ar(sndl,0.03,Rand(0.0,0.03))]);
sndr=SelectX.ar(((lr<0.1.neg)*lr.abs),[sndr,DelayN.ar(sndr,0.03,Rand(0.0,0.03))]);
snd=Balance2.ar(sndl,sndr,pan,amp)*Line.kr(0,1,1);
amp = amp * EnvGen.ar(Env.adsr(fadein,1,1,fadeout,curve:[4,4]),gate,doneAction:2);
snd=snd*amp;
// SendReply.kr(Impulse.kr(10),"/position",[buf,lr,fb,amp]);
Out.ar(busCompress,(fb+1)/2*snd);
Out.ar(busNoCompress,(1-((fb+1)/2))*snd);
Out.ar(busReverb,LinExp.kr(fb,1,-1,0.01,0.1)*snd);
}).add;
// initialize variables
syns = Dictionary.new();
buses = Dictionary.new();
bufs = Dictionary.new();
oscs = Dictionary.new();
synlist = Array.new();
server.sync;
// oscs.put("position",OSCFunc({ |msg|
// var oscRoute=msg[0];
// var synNum=msg[1];
// var dunno=msg[2];
// var bufNum=msg[3].asInteger;
// var lr=msg[4];
// var fb=msg[5];
// var amp=msg[6];
// NetAddr("127.0.0.1", 10111).sendMsg("lr",bufNum,lr);
// NetAddr("127.0.0.1", 10111).sendMsg("fb",bufNum,fb);
// NetAddr("127.0.0.1", 10111).sendMsg("amp",bufNum,amp);
// }, '/position'));
// define buses
buses.put("busCompress",Bus.audio(server,2));
buses.put("busNoCompress",Bus.audio(server,2));
buses.put("busReverb",Bus.audio(server,2));
server.sync;
// define fx
syns.put("fx",Synth.tail(server,"fx",[\busReverb,buses.at("busReverb"),\busNoCompress,buses.at("busNoCompress"),\busCompress,buses.at("busCompress")]));
server.sync;
"done loading.".postln;
}
free {
bufs.keysValuesDo({ arg k, val;
val.free;
});
oscs.keysValuesDo({ arg k, val;
val.free;
});
syns.keysValuesDo({ arg k, val;
val.free;
});
buses.keysValuesDo({ arg k, val;
buses.free;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment