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};
45 SynthDef(sdname = (\volumeAmpControl ++ synthNumChans).asSymbol,
46 { arg volumeAmp = 1, volumeLag = 0.1, volumeGate=1;
48 Linen.kr(volumeGate, releaseTime: 0.05, doneAction:2),
49 In.ar(startBus, synthNumChans) * Lag.kr(volumeAmp, volumeLag) );
53 play {arg mute = false;
56 (isPlaying || isPrepping).not.if({
57 server.serverRunning.if({
60 synthNumChans = server.options.numOutputBusChannels;
62 synthNumChans = numChans;
70 CmdPeriod.add(cpFun = {
73 nodeIDToFree = ampSynth.nodeID;
74 { server.nodeAllocator
75 .freePerm(nodeIDToFree);
86 // we have permanent node IDs so we should use them
87 nodeID = server.nodeAllocator.allocPerm(1);
88 ampSynth = Synth.basicNew(sdname, server, nodeID);
89 server.sendBundle(nil, ampSynth.newMsg(1,
90 [\volumeAmp, volume.dbamp, \volumeLag, lag],
91 addAction: \addAfter));
95 "Volume only works on a running Server. Please boot".warn;
101 var nodeIDToFree = ampSynth.nodeID;
102 ampSynth.set(\volumeGate, 0.0);
103 { server.nodeAllocator.freePerm(nodeIDToFree) }.defer(1.0);
105 CmdPeriod.remove(cpFun);
109 numChans { ^numChans ? synthNumChans ? server.options.numOutputBusChannels }
111 if(isPlaying and: { num != synthNumChans }) {
112 "Change in number of channels will not take effect until volume is reset to 0dB.".warn;
121 this.playVolume(true)
127 (this.muteamp == 0.0).if({
136 ampSynth.set(\volumeAmp, 0);
137 this.changed(\mute, true);
142 ampSynth.set(\volumeAmp, muteamp.dbamp);
143 this.changed(\mute, false);
146 // sets volume back to 1 - removes the synth
151 // cleaner with MVC - in db
152 volume_ { arg aVolume;
155 (this.isPlaying and: {this.isMuted.not}).if({
159 server.serverRunning.if({
160 this.playVolume(isMuted);
163 volume = volume.clip(min, max);
164 if(isMuted) { muteamp = volume };
165 if(isPlaying && isMuted.not) { ampSynth.set(\volumeAmp, volume.dbamp) };
166 this.changed(\amp, volume);
169 playVolume { arg muted = false;
170 (this.isPlaying.not and: {
171 (volume != 0.0) or: {muted}
179 ampSynth.set(\volumeLag, lag);
182 setVolumeRange { arg argMin, argMax;
183 argMin !? { min = argMin };
184 argMax !? { max = argMax };
185 this.changed(\ampRange, min, max);
189 gui { arg window, bounds;
191 ^VolumeGui(this, window, bounds)
201 var window, spec, slider, box, simpleController;
203 *new{|model, win, bounds|
204 ^super.new.model_(model).init(win, bounds)
208 spec = [model.min, model.max, \db].asSpec;
209 bounds = bounds ?? {Rect(100, 100, 80, 330)};
210 window = win ?? {GUI.window.new("Volume", bounds).front};
211 box = GUI.numberBox.new(window, Rect(10, 10, 60, 30))
212 .value_(model.volume) ;
213 slider = GUI.slider.new(window, Rect(10, 40, 60, 280))
214 .value_(spec.unmap(model.volume)) ;
215 slider.action_({ arg item ;
216 model.volume_(spec.map(item.value));
218 box.action_({ arg item ;
219 model.volume_(item.value) ;
222 simpleController.remove;
224 simpleController = SimpleController(model)
225 .put(\amp, {|changer, what, volume|
227 box.value_(volume.round(0.01)) ;
228 slider.value_(spec.unmap(volume)) ;
230 .put(\ampRange, {|changer, what, min, max|
231 spec = [min, max, \db].asSpec.debug;
232 slider.value_(spec.unmap(model.volume)) ;