Submit
Browse
Anonymous
Login
RSS
SuperCollider Code
Fork Code: luce : standalone synth and custom slider GUI demo
name
code content
( /* luce module for SuperCollider, licensed under GNU GPL v3 (see end of file), Luce is a surname, which means 'Light'; (latin origin: "Lux", see Genesis 1:3 for more informations). This software was written by Simon Deplat (aka Dindoleon), but should be considered as a production of the whole SuperCollider community. This demonstrates how to : - Create a standalone module which opens inside a new window, - Create a custom graphical 2d slider. Be careful, it only responds to mouse action, not to keyboard instructions, - Write a simple SC code for beginners, as I tried to comment each step of the software. This covers creating variables, instanciating a SynthDef, creating a GUI, and creating functions which allows this GUI to interact with the playing synth, This is a part of a music station I'm currently working on. The idea is that you can integrate this little module inside your own GUI, by passing a view as display argument to the slider, instead of the window (see line 59 - 60). Also, you can easily create new modules by following those steps : - Change the SynthDef by another SynthDef, - Change the 'amount' mapping according to your needs, - Finally (optionnal), change the name of the window and the colors of the displays. See http://sccode.org/1-5aZ for an uncommented alternate version. Special thanks to Bruno Ruviaro for his GUI examples which inspired (and allowed) this piece of code. */ // Variables we're going to use : var synth, synth_amount_range, win, window_size, slider, margin, value, knob_size, knob_outline_size, stroke_size, frame_color, frame_border_color, gradient_color, diamond_color, diamond_outline_color; // Size of items window_size = [ 400, 300 ]; knob_size = 8; knob_outline_size = 15; stroke_size = 2; margin = 3; // Colors frame_color = Color.new( 0.7, 0.4, 0 ); frame_border_color = Color.new( 1, 0.4, 0 ); gradient_color = Color.new( 0.9, 0.5, 0.3 ); diamond_color = Color.new( 1, 0.75, 0.25 ); diamond_outline_color = Color.new( 0.8, 0.55, 0.05 ); // Mapping ( Y axis doesn't require further variable mapping as amplitude goes from 0 to 1 ) value = [ 0, 1 ]; synth_amount_range = [ 24, 16000 ]; // Synthdef; this a really simple sound inspired by the amazing Tour of UGen documentation file. synth = SynthDef(\luce, { |out = 0, freq = 440, amp = 0, amount = 24| var snd; snd = Resonz.ar( Saw.ar(freq), amount, 0.2 ); // Change this mul: variable if you want to increase the max amplitude of the synth, but go easy on it because you could easily harm your ears ! Out.ar(out, Pan2.ar(snd, 0, amp)); }).play; // GUI management: win = Window("luce", Rect(0, 0, window_size[0], window_size[1]), false); win.background_( frame_color ); // Change the 'win' argument for a View if you want to integrate it inside a custom GUI. You will also need to change the window_size variable according to the size you want the module to have. slider = UserView( win, Rect( margin, margin, window_size[0] - ( margin * 2 ), window_size[1] - ( margin * 2 ) )); // Here is the function used to draw the custom slider: slider.drawFunc = { Pen.width = stroke_size; // First, draw the background frame: Pen.addRect( Rect(0,0, slider.bounds.width,slider.bounds.height) ); Pen.fillAxialGradient( slider.bounds.leftBottom, slider.bounds.rightTop, Color.black, gradient_color ); // Draw the diamond itself: Pen.moveTo( ( slider.bounds.width * value[0] - knob_size ) @ ( slider.bounds.height * value[1] ) ); Pen.lineTo( ( slider.bounds.width * value[0] ) @ ( slider.bounds.height * value[1] - knob_size ) ); Pen.lineTo( ( slider.bounds.width * value[0] + knob_size ) @ (( slider.bounds.height * value[1] ) ) ); Pen.lineTo( ( slider.bounds.width * value[0] ) @ ( slider.bounds.height * value[1] + knob_size ) ); // Fourth line isn't needed as we fill the shape. Pen.fillColor_( diamond_color ); Pen.fill; // Draw the diamond outline: Pen.moveTo( 0 @ ( slider.bounds.height * value[1] ) ); Pen.lineTo( ( slider.bounds.width * value[0] - knob_outline_size ) @ ( slider.bounds.height * value[1] ) ); Pen.moveTo( ( slider.bounds.width * value[0] ) @ 0 ); Pen.lineTo( ( slider.bounds.width * value[0] ) @ ( slider.bounds.height * value[1] - knob_outline_size ) ); Pen.moveTo( ( slider.bounds.width * value[0] + knob_outline_size ) @ (( slider.bounds.height * value[1] ) ) ); Pen.lineTo( slider.bounds.width @ (( slider.bounds.height * value[1] ) ) ); Pen.moveTo( ( slider.bounds.width * value[0] ) @ (( slider.bounds.height * value[1] + knob_outline_size ) ) ); Pen.lineTo( ( slider.bounds.width * value[0] ) @ slider.bounds.height ); Pen.moveTo( ( slider.bounds.width * value[0] - knob_outline_size ) @ ( slider.bounds.height * value[1] ) ); Pen.lineTo( ( slider.bounds.width * value[0] ) @ ( slider.bounds.height * value[1] - knob_outline_size ) ); Pen.lineTo( ( slider.bounds.width * value[0] + knob_outline_size ) @ (( slider.bounds.height * value[1] ) ) ); Pen.lineTo( ( slider.bounds.width * value[0] ) @ (( slider.bounds.height * value[1] + knob_outline_size ) ) ); Pen.lineTo( ( slider.bounds.width * value[0] - knob_outline_size ) @ ( slider.bounds.height * value[1] ) ); Pen.strokeColor_( diamond_outline_color ); Pen.stroke; // Draw the frame border: Pen.addRect( Rect(0,0, slider.bounds.width,slider.bounds.height) ); Pen.strokeColor_( frame_border_color ); Pen.stroke; }; // Set the default action slider.action = { synth.set(\amp, 1 - value[1]); // Requires to invert the value, as the Y axis from GUI goes from top to bottom, and sliders usually goes from bottom to top. synth.set(\amount, linexp(value[0], 0, 1, synth_amount_range[0], synth_amount_range[1])); // Exponential mapping between the 0 -> 1 value and the amount range. Change this settings according to your needs. slider.refresh // Call the drawFunc of the slider to update graphics }; // Define mouse actions slider.mouseDownAction = { arg slider, x = 0.5, y = 0.5, m; ([256, 0].includes(m)).if{ // restrict to no modifier value[0] = (x).linlin(0,slider.bounds.width,0,1); // Linear mapping between the slider size and 0 -> 1 value[1] = (y).linlin(0,slider.bounds.height,0,1); slider.doAction}; }; slider.mouseMoveAction = slider.mouseDownAction; // Map the mouse action to its function win.front; // Start the software by giving life to the window /* LICENSE: This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ )
code description
luce is a standalone synth module driven by a custom 2D slider GUI. It is easy to integrate and to modify. It also serves the purpose of understanding the bases of developping modules with SuperCollider for beginners.
use markdown for formating
category tags
comma separated, i.g. "wild, siren" (do not enter default SC class names, please)
ancestor(s)
comma separated identificators, i.g. "1-C,1-1,1-4M,1-x"
Private?
the code will be accessible by direct url and not visible in public activity
signup to submit public code without captcha
comment of change