diff --git a/release-packaging/Classes/FluidBufVoiceAllocator.sc b/release-packaging/Classes/FluidBufVoiceAllocator.sc new file mode 100644 index 00000000..aab9e38c --- /dev/null +++ b/release-packaging/Classes/FluidBufVoiceAllocator.sc @@ -0,0 +1,62 @@ +FluidBufVoiceAllocator : FluidBufProcessor { + *kr { |sourceA, startFrameA = 0, numFramesA = -1, startChanA = 0, numChansA = -1, sourceB, startFrameB = 0, numFramesB = -1, startChanB = 0, numChansB = -1, destA, destB, destC, numVoices = 1, prioritisedVoices = 0, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 1, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, trig = 1, blocking = 0| + + sourceA.isNil.if {"FluidBufVoiceAllocator: Invalid source 1 buffer".throw}; + sourceB.isNil.if {"FluidBufVoiceAllocator: Invalid source 2 buffer".throw}; + sourceA = sourceA.asUGenInput; + sourceB = sourceB.asUGenInput; + + destA.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destB.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destC.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destA = destA.asUGenInput; + destB = destB.asUGenInput; + destC = destC.asUGenInput; + + ^FluidProxyUgen.kr(this.objectClassName++\Trigger, -1, sourceA, startFrameA, numFramesA, startChanA, numChansA, sourceB, startFrameB, numFramesB, startChanB, numChansB, destA, destB, destC, numVoices, numVoices, prioritisedVoices, birthLowThreshold, birthHighThreshold, minTrackLen, trackMagRange, trackFreqRange, trackProb, trig, blocking); + } + + *process { |server, sourceA, startFrameA = 0, numFramesA = -1, startChanA = 0, numChansA = -1, sourceB, startFrameB = 0, numFramesB = -1, startChanB = 0, numChansB = -1, destA, destB, destC, numVoices = 1, prioritisedVoices = 0, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 1, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, freeWhenDone = true, action| + + sourceA.isNil.if {"FluidBufVoiceAllocator: Invalid source 1 buffer".throw}; + sourceB.isNil.if {"FluidBufVoiceAllocator: Invalid source 2 buffer".throw}; + sourceA = sourceA.asUGenInput; + sourceB = sourceB.asUGenInput; + + destA.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destB.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destC.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destA = destA.asUGenInput; + destB = destB.asUGenInput; + destC = destC.asUGenInput; + + ^this.new( + server, nil, [destA, destB, destC] + ).processList( + [sourceA, startFrameA, numFramesA, startChanA, numChansA, sourceB, startFrameB, numFramesB, startChanB, numChansB, destA, destB, destC, numVoices, numVoices, prioritisedVoices, birthLowThreshold, birthHighThreshold, minTrackLen, trackMagRange, trackFreqRange, trackProb, 0], freeWhenDone, action + ) + } + + *processBlocking { |server, sourceA, startFrameA = 0, numFramesA = -1, startChanA = 0, numChansA = -1, sourceB, startFrameB = 0, numFramesB = -1, startChanB = 0, numChansB = -1, destA, destB, destC, numVoices = 1, prioritisedVoices = 0, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 1, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, freeWhenDone = true, action| + + sourceA.isNil.if {"FluidBufVoiceAllocator: Invalid source 1 buffer".throw}; + sourceB.isNil.if {"FluidBufVoiceAllocator: Invalid source 2 buffer".throw}; + sourceA = sourceA.asUGenInput; + sourceB = sourceB.asUGenInput; + + destA.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destB.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destC.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destA = destA.asUGenInput; + destB = destB.asUGenInput; + destC = destC.asUGenInput; + + ^this.new( + server, nil, [destA, destB, destC] + ).processList( + [sourceA, startFrameA, numFramesA, startChanA, numChansA, sourceB, startFrameB, numFramesB, startChanB, numChansB, destA, destB, destC, numVoices, numVoices, prioritisedVoices, birthLowThreshold, birthHighThreshold, minTrackLen, trackMagRange, trackFreqRange, trackProb, 1], freeWhenDone, action + ) + } +} + +FluidBufVoiceAllocatorTrigger : FluidProxyUgen {} diff --git a/release-packaging/Classes/FluidVoiceAllocator.sc b/release-packaging/Classes/FluidVoiceAllocator.sc new file mode 100644 index 00000000..9496f6df --- /dev/null +++ b/release-packaging/Classes/FluidVoiceAllocator.sc @@ -0,0 +1,37 @@ +FluidVoiceAllocator : MultiOutUGen { + + *kr { arg in, in2, numVoices = 1, prioritisedVoices = 0, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 1, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, maxNumVoices; + + maxNumVoices = maxNumVoices ? numVoices; + + ^this.multiNew('control',*(in.asArray ++ in2.asArray ++ numVoices ++ maxNumVoices ++ prioritisedVoices ++ birthLowThreshold ++ birthHighThreshold ++ minTrackLen ++ trackMagRange ++ trackFreqRange ++ trackProb)).reshape(3,maxNumVoices); + } + + init {arg ...theInputs; + inputs = theInputs; + this.specialIndex = (inputs.size - 10).max(0); + ^this.initOutputs(inputs[inputs.size - 8] * 3,rate); + } + + checkInputs { + if(((inputs.size - 9).mod(2)) != 0) { + ^(": the 2 input arrays must be of equal length."); + }; + ^this.checkValidInputs; + } + + initOutputs{|numChans,rate| + if(numChans.isNil or: {numChans < 1}) + { + Error("No input channels").throw + }; + + channels = Array.fill(numChans, { |i| + OutputProxy('control',this,i); + }); + ^channels + } + + numOutputs { ^(channels.size); } +} +