[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [sc-users] wslib update



Actually I did something similar. I post it here in case it's usefull for someone. It uses synth arguments instead of a control bus.

The usage is BEQgui(group,out,mono,setting) where group is a group to which tail it will create the synth, out is the audio bus to use, mono is either true or false for mono or stereo operation and setting is the parameters of the eq (= frdb).

example:
(
{ WhiteNoise.ar(0.5).dup }.play;
~setting = [[100, 6, 1], [400,3,1], [4500,-2,1], [1500,-5, 1], [6000, -6, 1]];
~eq = BEQgui(s,0,false,~setting);
~eq.makegui
)

LFSaw escreveu:
Hello,

I wasnÄt sure if I wanted to post this, but the other day I spend a lot of time refactoring your Code, Wouter to add the possibility of several of these GUIs. If I have time, I will release it as a quark, but for now, just a sneak preview; hope thats ok for you and others. The interface is completely based on your post some months ago, but you will have to add a custom synth by yourself. A convenience PseudoUGen is also added that will also add the proper naming of controls for you. perhaps someone wants to add some additional features to it, or even wouter wants to add it to his lib (with modifications).
I am completely open for thoughts.

kind regards
    Till



On 06.05.2009, at 09:03, Wouter Snoei wrote:

Hi Andrzej,

thanks for the feedback and suggestions! I updated wslib to add OneShotController (I just forgot to copy it to the right place) and changed ServerRecordWindow and the main help (rev 931).

It's great! thank you verrry much! Did you consider adding possibility of changing group/bus to custom ones (so eg. that could be used with MixerChannel)?

Yes I will look at that.

cheers,
Wouter


Op 6 mei 2009, om 01:18 heeft Andrzej Kopeć het volgende geschreven:


Wiadomość napisana w dniu 2009-05-05, o godz. 17:46, przez Wouter Snoei:

Hi all,

just to inform you; I have just updated the wslib quark to reflect some of the new features in SC3.3. It is not compatible anymore with pre 3.3 versions. New features include:

MasterEQ : a graphical interface for BEQSuite (as posted earlier on the list, now in a Class)
It's great! thank you verrry much! Did you consider adding possibility of changing group/bus to custom ones (so eg. that could be used with MixerChannel)?

OneShotController : enables Synth actions (upon start, free, pause and unpause)
in current quarks svn rev. (930) there is no such class... :(


improvements on RoundButton : gradient support, SCImage support, new bevel drawing using gradient improvements on SmoothSlider : gradient support, border, baseWidth and more (now documented)
appleScript : running AppleScript commands straight from SC
asciiCorrect : convert Strings to display *all* ascii characters correctly

and lots of changes "under the hood"


Enjoy! (comments very welcome of course)

w = ServerRecordWindow( s );

gives me:

ERROR: Primitive '_SCView_New' failed.
Failed.
RECEIVER:
Instance of SNBox {    (16209070, gc=98, fmt=00, flg=00, set=06)
instance variables [33]
  dataptr : nil
(...)

there is a problem with SNBox, so I modified gui to the newest style ;) (attached)

Also not every link on wslib help page works in Help Browser.

<ServerRecordWindow2.sc>

thanks,
ak




_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.beast.bham.ac.uk/research/sc_mailing_lists.shtml
archive: https://listarc.bham.ac.uk/marchives/sc-users/
search: https://listarc.bham.ac.uk/lists/sc-users/search/



--
Miguel Negrão // ZLB
http://www.friendlyvirus.org/artists/zlb/
BEQgui {

var synth,<>frdb,<>fwin;

*new { |group ,out=0,mono=true,preset| ^super.new.init(group,out,mono,preset) }

init { |group,out,mono,setting| 
	synth = Synth.tail(group,if(mono){\eqMono}{\eqStereo},[\out,out]);
	frdb = setting ?? { [[100, 6, 1], [500,6,1], [4500,-6,1], [1500,-10, 1], [6000, -6, 1]]};
	this.send_current; 

}

setting {
	^frdb
} 

send_current { 
	synth.setn(\a1,frdb.collect({ |item,i|
			[ item[0].cpsmidi - 1000.cpsmidi, item[1], item[2].log10 ] }).flat);
			
	}

free { synth.free; fwin.close; }

gui {
	if(fwin.isNil) {this.makegui} {fwin.front}
}

makegui {

var uvw, font, frpresets, tvw, tvw_refresh, pumenu, pu_buttons, pumenu_create_items, pumenu_check,
 selected, tvw_views, pu_filebuttons;

fwin = GUI.window.new( "EQ", Rect(300, 100, 346, 270), false ).front; 

fwin.view.decorator = FlowLayout( fwin.view.bounds, 10@10, 4@10 );

fwin.onClose_{ fwin = nil};

uvw = GUI.userView.new( fwin, fwin.view.bounds.insetBy(10,10).height_(180) ).resize_(5);

font = GUI.font.new( GUI.font.defaultMonoFace, 9 );

uvw.relativeOrigin = false;

uvw.focusColor = Color.clear;

//frdb = frdb ?? { [[100, 6, 1], [500,6,1], [4500,-6,1], [1500,-10, 1], [6000, -6, 1]]};

frpresets = [ // x_ = cannot delete or modify
	\x_default, [[100, -6, 1], [250,-7.5,1], [1000, 0, 1],  [3500,0,1], [6000, 7.5, 1]],
	\x_flat, [[100,0,1], [250,0,1], [1000,0,1], [3500,0,1], [6000,0,1]]
	];
	

	
//frdb = frpresets[1].deepCopy;

selected = -1;

tvw = TabbedView( fwin, fwin.view.bounds.insetBy(10,10).height_(35).top_(200),
	[ "low shelf", "peak 1", "peak 2", "peak 3", "high shelf" ],
	{ |i| Color.hsv( i.linlin(0,5,0,1), 0.75, 0.5).alpha_( 0.25 ); }!5 )
		.font_( font )
		.resize_( 7 );
		
tvw.focusActions = { |i| { selected = i; uvw.refresh;  }; }!5;

tvw_views = [];

tvw.views.do({ |view,i| 
	var vw_array = [];
	
	view.decorator = FlowLayout( view.bounds.moveTo(0,0) ); 
	
	GUI.staticText.new( view, 35@14 ).font_( font ).align_( \right ).string_( "freq:" );
	vw_array = vw_array.add( 
		SNBox( view, 40@14 ).font_( font ).value_( frdb[i][0] )
			.clipLo_(20).clipHi_(22000)
			.action_({ |vw|
				frdb[i][0] = vw.value;
				this.send_current;
				uvw.refresh;
				pumenu_check.value;
				})  );
	
	GUI.staticText.new( view, 25@14 ).font_( font ).align_( \right ).string_( "db:" );
	vw_array = vw_array.add( 
		SNBox( view, 40@14 ).font_( font ).value_( frdb[i][1] )
			.clipLo_( -24 ).clipHi_( 24 )
			.action_({ |vw|
				frdb[i][1] = vw.value;
				this.send_current;
				uvw.refresh;
				pumenu_check.value;
				})  );
	
	GUI.staticText.new( view, 25@14 ).font_( font ).align_( \right )
		.string_( (0: "rs:", 4:"rs")[i] ? "rq"  );
	vw_array = vw_array.add( 
		SNBox( view, 40@14 ).font_( font ).value_( frdb[i][2] )
			.step_(0.1).clipLo_( if( [0,4].includes(i) ) { 0.6 } {0.01}).clipHi_(10)
			.action_({ |vw|
				frdb[i][2] = vw.value;
				this.send_current;
				uvw.refresh;
				pumenu_check.value;
				}) 
				);
	
	tvw_views = tvw_views.add( vw_array );
	
	});
	

tvw_refresh = { 
	frdb.do({ |item,i| 
		item.do({ |subitem, ii| 
			tvw_views[ i ][ ii ].value = subitem;
			})
		});
	};
	
pumenu = GUI.popUpMenu.new( fwin, 150@15 )
	.font_( font ).canFocus_(false);
	
//pumenu_check.value;
pu_buttons = [
	RoundButton.new( fwin, 15@15 )
		.radius_( 2 ).border_(1)
		.states_( [[ '+' ]] ),
	RoundButton.new( fwin,  15@15 )
		.radius_( 2 ).border_(1)
		.states_( [[ '-' ]] ),	
	];
	
GUI.staticText.new( fwin, 25@15  );
pu_filebuttons = [
	RoundButton.new( fwin, 50@15 )
		.extrude_( false ).font_( font )
		.states_( [[ "save", Color.black, Color.red(0.75).alpha_(0.25) ]] ),
	RoundButton.new( fwin,  50@15 )
		.extrude_( false ).font_( font )
		.states_( [[ "revert", Color.black, Color.green(0.75).alpha_(0.25) ]] )
	];

pu_filebuttons[0].action_({
		File.use("eq-prefs.txt", "w",
	{ |f| f.write(
		(  current: frdb,
		   presets: frpresets ).asCompileString
		); })
	});

pu_filebuttons[1].action_({
	var contents;
		File.use("eq-prefs.txt", "r", { |f| 
			contents = f.readAllString.interpret;
			//contents.postln;
			frdb = contents[ \current ];
			frpresets = contents[ \presets ];
			this.send_current;
			pumenu_create_items.value;
			pumenu_check.value;
			uvw.refresh;
			tvw_refresh.value;
				 	})
	});	


	
pumenu_create_items = {
	var items;
	items = [];
	frpresets.pairsDo({ |key, value|
		if( key.asString[..1] == "x_" )
			{ items = items.add( key.asString[2..] ); }
			{ items = items.add( key.asString ); };
		
		});
	items = items ++ [ "-", "(custom" /*)*/ ];
	pumenu.items = items;
	};
	
pumenu_create_items.value;

pumenu.action = { |pu|
	frdb = frpresets[ (pu.value * 2) + 1 ].deepCopy;
	//frdb.postln;
	this.send_current;
	uvw.refresh;
	tvw_refresh.value;
	if( frpresets[ pu.value * 2 ].asString[..1] == "x_" )
		  	{  pu_buttons[0].enabled_(false); 
		  	    pu_buttons[1].enabled_(false);   }
		  	{   pu_buttons[0].enabled_(false);
		  	     pu_buttons[1].enabled_(true);    };
	};
	

	
pu_buttons[0].action = { |bt|
	var testPreset, addPreset, replacePreset;
	
	testPreset = { |name = "user"|
		var index, xnames, clpresets;
		name = name.asSymbol;
		index = frpresets.clump(2).detectIndex({ |item| item[0] == name.asSymbol });
		xnames = frpresets.clump(2)
			.select({ |item| item[0].asString[..1] == "x_" })
			.collect({ |item| item[0].asString[2..].asSymbol });
		if( index.isNil )
			{
			if( xnames.includes( name ).not )
				{ addPreset.value( name ); }
				{ SCAlert( "EQ preset '%' cannot be overwritten.\nPlease choose a different name"
						.format( name ), ["ok"] ); };
			} {
			 SCAlert( "EQ preset '%' already exists.\nDo you want to overwrite it?"
						.format( name ), ["cancel","ok"], 
						[{}, { replacePreset.value( name, index ) }] ); 
			};
		};
		
	addPreset = { |name = "user"|
		frpresets = frpresets ++ [ name.asSymbol, frdb.deepCopy ];
		pumenu_create_items.value;
		pumenu_check.value;
		};
		
	replacePreset = { |name = "x_default", index = 0|
		frpresets[ index * 2 ] = name.asSymbol;
		frpresets[ (index * 2)+1 ] = frdb.deepCopy;
		pumenu_create_items.value;
		pumenu_check.value;
		};
	
	SCRequestString(  "user", "Enter a short name for the new preset",
		{ |str| testPreset.value(str); });
		
	};

pu_buttons[1].action = { |bt|
	 SCAlert( "Are you sure you want to\ndelete preset '%'"
				.format( pumenu.items[ pumenu.value ] ), ["cancel","ok"], 
				[{}, {
				frpresets.removeAt(  pumenu.value * 2 );
				frpresets.removeAt(  pumenu.value * 2 );
				pumenu_create_items.value;
				pumenu_check.value;
			}] ); 
			
	};

pumenu_check	= {
	var index;
	index = frpresets.clump(2).detectIndex({ |item| item[1] == frdb });
	if( index.notNil )
		{ pumenu.value = index;
		  pu_buttons[0].enabled_(false);
		  if( frpresets[ index * 2 ].asString[..1] == "x_" )
		  	{  pu_buttons[1].enabled_(false);  }
		  	{   pu_buttons[1].enabled_(true);  };
			}
		{ pumenu.value = (frpresets.size/2) + 1; 
		    pu_buttons[1].enabled_(false);  
		     pu_buttons[0].enabled_(true);
			};
	};

pumenu_check.value;

this.send_current;


uvw.mouseDownAction = { |vw,x,y,mod|
	var bounds;
	var pt;
	var min = 20, max = 22050, range = 24;
	
	bounds = vw.bounds;
	pt = (x@y) - (bounds.leftTop);
	
	selected =  frdb.detectIndex({ |array|
		(( array[ 0 ].explin( min, max, 0, bounds.width ) )@
		( array[ 1 ].linlin( range.neg, range, bounds.height, 0, \none ) ))
			.dist( pt ) <= 5;
		}) ? -1;
		
	if( selected != -1 ) { tvw.focus( selected ) };
	vw.refresh;
	};
	
uvw.mouseMoveAction = { |vw,x,y,mod|
	var bounds;
	var pt;
	var min = 20, max = 22050, range = 24;
	
	bounds = vw.bounds;
	pt = (x@y) - (bounds.leftTop);
	
	if( selected != -1 )
		{
		case { ModKey( mod ).alt }
			{ 
			if(  ModKey( mod ).shift )
				{
			frdb[selected] = frdb[selected][[0,1]] 
				++ [ y.linexp( bounds.height, 0, 0.1, 10, \none ).nearestInList(
					if( [0,4].includes(selected) ) 
						{[0.6,1,2.5,5,10]} 
						{[0.1,0.25,0.5,1,2.5,5,10]}
						
					) ];
				}
				{
			frdb[selected] = frdb[selected][[0,1]] 
				++ [ y.linexp( bounds.height, 0, 0.1, 10, \none ).clip(
						 if( [0,4].includes(selected) ) { 0.6 } {0.1},10).round(0.01) ];
				};
			tvw_views[selected][2].value = frdb[selected][2];
				 }
			{ ModKey( mod ).shift }
			{
		frdb[selected] = [
			pt.x.linexp(0, bounds.width, min, max )
				.nearestInList( [25,50,75,100,250,500,750,1000,2500,5000,7500,10000] ),
			pt.y.linlin( 0, bounds.height, range, range.neg, \none )
				.clip2( range ).round(6),
			frdb[selected][2] 
			];
		tvw_views[selected][0].value = frdb[selected][0];
		tvw_views[selected][1].value = frdb[selected][1];	
			}
			{ true }
			{
		frdb[selected] = [
			pt.x.linexp(0, bounds.width, min, max ).clip(20,20000).round(1),
			pt.y.linlin( 0, bounds.height, range, range.neg, \none ).clip2( range )
				.round(0.25),
			frdb[selected][2] 
			];	
		tvw_views[selected][0].value = frdb[selected][0];
		tvw_views[selected][1].value = frdb[selected][1];		};
	this.send_current;
	vw.refresh;
	pumenu_check.value;
		};

	};

uvw.drawFunc = { |vw|
	var freqs, svals, values, bounds, zeroline;
	var freq = 1200, rq = 0.5, db = 12;
	var min = 20, max = 22050, range = 24;
	var vlines = [100,1000,10000];
	var dimvlines = [25,50,75, 250,500,750, 2500,5000,7500];
	var hlines = [-18,-12,-6,6,12,18];
	var pt;
	
	bounds = vw.bounds;
	
	#freq,db,rq = frdb[0] ? [ freq, db, rq ];
	
	freqs = ({|i| i } ! (bounds.width+1));
	freqs = freqs.linexp(0, bounds.width, min, max );
	
	values = [
		B2LowShelf.magResponse( freqs, 44100, frdb[0][0], frdb[0][2], frdb[0][1]),
		B2PeakEQ.magResponse( freqs, 44100, frdb[1][0], frdb[1][2], frdb[1][1]),
		B2PeakEQ.magResponse( freqs, 44100, frdb[2][0], frdb[2][2], frdb[2][1]),
		B2PeakEQ.magResponse( freqs, 44100, frdb[3][0], frdb[3][2], frdb[3][1]),
		B2HiShelf.magResponse( freqs, 44100, frdb[4][0], frdb[4][2], frdb[4][1])
			].ampdb.max(-200).min(200);
	
	zeroline = 0.linlin(range.neg,range, bounds.height, 0, \none);
	
	svals = values.sum.linlin(range.neg,range, bounds.height, 0, \none);
	values = values.linlin(range.neg,range, bounds.height, 0, \none);
	
	vlines = vlines.explin( min, max, 0, bounds.width );
	dimvlines = dimvlines.explin( min, max, 0, bounds.width );
	
	pt = 
		frdb.collect({ |array|
			
		(array[0].explin( min, max, 0, bounds.width ))
		@
		(array[1].linlin(range.neg,range,bounds.height,0,\none));
		});
	
	GUI.pen.use({
		GUI.pen.translate( bounds.left, bounds.top );
		
		GUI.pen.color = Color.gray(0.2).alpha_(0.5);
		GUI.pen.addRect( bounds.moveTo(0,0).insetBy(-1,-1) ).stroke;
		
		GUI.pen.addRect( bounds.moveTo(0,0) ).clip;
		
		GUI.pen.color = Color.gray(0.2).alpha_(0.125);
		
		hlines.do({ |hline,i|
			hline = hline.linlin( range.neg,range, bounds.height, 0, \none );
			GUI.pen.line( 0@hline, bounds.width@hline )
			});
		dimvlines.do({ |vline,i|
			GUI.pen.line( vline@0, vline@xxxxxxxxxxxxx );
			});
		GUI.pen.stroke;
	
		GUI.pen.color = Color.gray(0.2).alpha_(0.5);
		vlines.do({ |vline,i|
			GUI.pen.line( vline@0, vline@xxxxxxxxxxxxx );
			});
		GUI.pen.line( 0@zeroline, bounds.width@zeroline ).stroke;
		
		/*
		GUI.pen.color = Color.white.alpha_(0.5);
		GUI.pen.fillRect( Rect( 33, 0, 206, 14 ) );
		*/
		
		GUI.pen.font = font;
		
		GUI.pen.color = Color.gray(0.2).alpha_(0.5);
		hlines.do({ |hline|
			GUI.pen.stringAtPoint( hline.asString ++ "dB", 
				1@(hline.linlin( range.neg,range, bounds.height, 0, \none ) -10) );
			});
		vlines.do({ |vline,i|
			GUI.pen.stringAtPoint( ["100Hz", "1KHz", "10KHz"][i], 
				(vline+2)@(bounds.height - 10) );
			});
		
		/*
		if( selected != -1 )
			{ GUI.pen.stringAtPoint(
				[ "low shelf: %hz, %dB, rs=%",
				  "peak 1: %hz, %dB, rq=%",
				  "peak 2: %hz, %dB, rq=%",
				  "peak 3: %hz, %dB, rq=%",
				  "hi shelf: %hz, %dB, rs=%"
				][ selected ].format(
					frdb[selected][0],
					frdb[selected][1],
					frdb[selected][2]
					),
				35@1 );
			 }
			 { GUI.pen.stringAtPoint( "shift: snap, alt: rq", 35@1 ); };
		*/
				
		values.do({ |svals,i|
			var color;
			color = Color.hsv(
				i.linlin(0,values.size,0,1), 
				0.75, 0.5).alpha_(if( selected == i ) { 0.75 } { 0.25 });
			GUI.pen.color = color;
			GUI.pen.moveTo( 0@(svals[0]) );
			svals[1..].do({ |val, i|
				GUI.pen.lineTo( (i+1)@val );
				});
			GUI.pen.lineTo( bounds.width@(bounds.height/2) );
			GUI.pen.lineTo( 0@(bounds.height/2) );
			GUI.pen.lineTo( 0@(svals[0]) );
			GUI.pen.fill;
			
			GUI.pen.addArc( pt[i], 5, 0, 2pi );
			
			GUI.pen.color = color.alpha_(0.75);
			GUI.pen.stroke;

			});
		
		GUI.pen.color = Color.blue(0.5);
		GUI.pen.moveTo( 0@(svals[0]) );
		svals[1..].do({ |val, i|
			GUI.pen.lineTo( (i+1)@val );
			});
		GUI.pen.stroke;
		
		});
	
	}; fwin.refresh;

}

*loadSDef {
	SynthDef(\eqMono, { arg out = 0, gate=1, 
	a1,a2,a3,b1,b2,b3,c1,c2,c3,d1,d2,d3,e1,e2,e3; 
	
	var env, frdb, in;
	env = Linen.kr(gate, 0.05, 1, 0.1, 2);
	
	frdb = [a1,a2,a3,b1,b2,b3,c1,c2,c3,d1,d2,d3,e1,e2,e3].clump(3)
		.collect({ |item|
			[ (item[0] + 1000.cpsmidi).midicps, item[1], 10**item[2]]
			});
	frdb[0].postln;		
	frdb[0][[0,2,1]].lag(0.1).postln;		
	in = In.ar(out, 1);		
	in = BLowShelf.ar( in, *frdb[0][[0,2,1]].lag(0.1) );
	in = BPeakEQ.ar( in, *frdb[1][[0,2,1]].lag(0.1));
	in = BPeakEQ.ar( in, *frdb[2][[0,2,1]].lag(0.1));
	in = BPeakEQ.ar( in, *frdb[3][[0,2,1]].lag(0.1));
	in = BHiShelf.ar( in, *frdb[4][[0,2,1]].lag(0.1));

	XOut.ar(out,env,in)
	}).store;
	
	SynthDef(\eqStereo, { arg out = 0, gate=1, 
	a1,a2,a3,b1,b2,b3,c1,c2,c3,d1,d2,d3,e1,e2,e3; 
	
	var env, frdb, in;
	env = Linen.kr(gate, 0.05, 1, 0.1, 2);
	
	frdb = [a1,a2,a3,b1,b2,b3,c1,c2,c3,d1,d2,d3,e1,e2,e3].clump(3)
		.collect({ |item|
			[ (item[0] + 1000.cpsmidi).midicps, item[1], 10**item[2]]
			});
	frdb[0].postln;		
	frdb[0][[0,2,1]].lag(0.1).postln;		
	in = In.ar(out, 1);		
	in = BLowShelf.ar( in, *frdb[0][[0,2,1]].lag(0.1) );
	in = BPeakEQ.ar( in, *frdb[1][[0,2,1]].lag(0.1));
	in = BPeakEQ.ar( in, *frdb[2][[0,2,1]].lag(0.1));
	in = BPeakEQ.ar( in, *frdb[3][[0,2,1]].lag(0.1));
	in = BHiShelf.ar( in, *frdb[4][[0,2,1]].lag(0.1));

	XOut.ar(out,env,in)
	}).store;

	}
}