5 a = Volume(s, 0, s.options.numOutputBusChannels);
8 z = {SinOsc.ar(440, 0, 0.1)}.play
26 var startBus, numChans, <min, <max, server, persist, <ampSynth, <>window, <volume, spec;
27 var <lag, sdname, gui, <isPlaying, <muteamp, cpFun, <isMuted=false, <isPrepping;
28 var <synthNumChans; // the actual number of channels, which might be set automatically
30 *new { arg server, startBus = 0, numChans, min = -90, max = 6, persist = false;
31 ^super.newCopyArgs(startBus, numChans, min, max, server, persist).initVolume;
36 server = server ?? {Server.default};
42 ServerBoot.add {|aServer|
43 if (aServer == server) {
51 SynthDef(sdname = (\volumeAmpControl ++ synthNumChans).asSymbol,
52 { arg volumeAmp = 1, volumeLag = 0.1, volumeGate=1;
54 Linen.kr(volumeGate, releaseTime: 0.05, doneAction:2),
55 In.ar(startBus, synthNumChans) * Lag.kr(volumeAmp, volumeLag) );
59 play {arg mute = false;
62 (isPlaying || isPrepping).not.if({
63 server.serverRunning.if({
66 synthNumChans = server.options.numOutputBusChannels;
68 synthNumChans = numChans;
76 CmdPeriod.add(cpFun = {
79 nodeIDToFree = ampSynth.nodeID;
80 { server.nodeAllocator
81 .freePerm(nodeIDToFree);
92 // we have permanent node IDs so we should use them
93 nodeID = server.nodeAllocator.allocPerm(1);
94 ampSynth = Synth.basicNew(sdname, server, nodeID);
95 server.sendBundle(nil, ampSynth.newMsg(1,
96 [\volumeAmp, volume.dbamp, \volumeLag, lag],
97 addAction: \addAfter));
101 "Volume only works on a running Server. Please boot".warn;
107 var nodeIDToFree = ampSynth.nodeID;
108 ampSynth.set(\volumeGate, 0.0);
109 { server.nodeAllocator.freePerm(nodeIDToFree) }.defer(1.0);
111 CmdPeriod.remove(cpFun);
115 numChans { ^numChans ? synthNumChans ? server.options.numOutputBusChannels }
117 if(isPlaying and: { num != synthNumChans }) {
118 "Change in number of channels will not take effect until volume is reset to 0dB.".warn;
127 this.playVolume(true)
133 (this.muteamp == 0.0).if({
142 ampSynth.set(\volumeAmp, 0);
143 this.changed(\mute, true);
148 ampSynth.set(\volumeAmp, muteamp.dbamp);
149 this.changed(\mute, false);
152 // sets volume back to 1 - removes the synth
157 // cleaner with MVC - in db
158 volume_ { arg aVolume;
161 (this.isPlaying and: {this.isMuted.not}).if({
165 server.serverRunning.if({
166 this.playVolume(isMuted);
169 volume = volume.clip(min, max);
170 if(isMuted) { muteamp = volume };
171 if(isPlaying && isMuted.not) { ampSynth.set(\volumeAmp, volume.dbamp) };
172 this.changed(\amp, volume);
175 playVolume { arg muted = false;
176 (this.isPlaying.not and: {
177 (volume != 0.0) or: {muted}
185 ampSynth.set(\volumeLag, lag);
188 setVolumeRange { arg argMin, argMax;
189 argMin !? { min = argMin };
190 argMax !? { max = argMax };
191 this.changed(\ampRange, min, max);
195 gui { arg window, bounds;
197 ^VolumeGui(this, window, bounds)
207 var window, spec, slider, box, simpleController;
209 *new{|model, win, bounds|
210 ^super.new.model_(model).init(win, bounds)
214 spec = [model.min, model.max, \db].asSpec;
215 bounds = bounds ?? {Rect(100, 100, 80, 330)};
216 window = win ?? {GUI.window.new("Volume", bounds).front};
217 box = GUI.numberBox.new(window, Rect(10, 10, 60, 30))
218 .value_(model.volume) ;
219 slider = GUI.slider.new(window, Rect(10, 40, 60, 280))
220 .value_(spec.unmap(model.volume)) ;
221 slider.action_({ arg item ;
222 model.volume_(spec.map(item.value));
224 box.action_({ arg item ;
225 model.volume_(item.value) ;
228 simpleController.remove;
230 simpleController = SimpleController(model)
231 .put(\amp, {|changer, what, volume|
233 box.value_(volume.round(0.01)) ;
234 slider.value_(spec.unmap(volume)) ;
236 .put(\ampRange, {|changer, what, min, max|
237 spec = [min, max, \db].asSpec.debug;
238 slider.value_(spec.unmap(model.volume)) ;