From 8c45cbc006d751df91eb637032190ff4a33fc78e Mon Sep 17 00:00:00 2001 From: David Runge Date: Sun, 3 Jul 2016 16:34:58 +0200 Subject: classes/*.sc: Moving all classes to the proper subfolder classes. --- classes/Bowelyzer.sc | 267 ++++++++++++++++++++++ classes/BowelyzerAnalyzer.sc | 209 +++++++++++++++++ classes/BowelyzerConfig.sc | 362 ++++++++++++++++++++++++++++++ classes/BowelyzerGUI.sc | 520 +++++++++++++++++++++++++++++++++++++++++++ classes/BowelyzerOSCHub.sc | 88 ++++++++ 5 files changed, 1446 insertions(+) create mode 100644 classes/Bowelyzer.sc create mode 100644 classes/BowelyzerAnalyzer.sc create mode 100644 classes/BowelyzerConfig.sc create mode 100644 classes/BowelyzerGUI.sc create mode 100644 classes/BowelyzerOSCHub.sc (limited to 'classes') diff --git a/classes/Bowelyzer.sc b/classes/Bowelyzer.sc new file mode 100644 index 0000000..cafaf00 --- /dev/null +++ b/classes/Bowelyzer.sc @@ -0,0 +1,267 @@ +Bowelyzer{ + + var Synth.new( + name, + [ + inputChannel: input, + sendReplyFreq: controls.at(\sendReplyFreq), + amplitudeAttackTime: controls.at(\amplitudeAttackTime), + amplitudeReleaseTime: controls.at(\amplitudeReleaseTime), + hfHainsworth: controls.at(\hfhainsworth), + hfFoote: controls.at(\hfFoote), + hfThreshold: controls.at(\hfThreshold), + hfWaitTime: controls.at(\hfWaitTime), + pitchInitFreq: controls.at(\pitchInitFreq), + pitchMinFreq: controls.at(\pitchMinFreq), + pitchMaxFreq: controls.at(\pitchMaxFreq), + pitchExecFreq: controls.at(\pitchExecFreq), + pitchMaxBinsPerOctave: controls.at(\pitchMaxBinsPerOctave), + pitchMedian: controls.at(\pitchMedian), + pitchAmpThreshold: controls.at(\pitchAmpThreshold), + pitchPeakThreshold: controls.at(\pitchPeakThreshold), + pitchDownSample: controls.at(\pitchDownSample) + ], + analyzerGroup + ).register; + ); + },{ + synths.add(name -> Synth.newPaused( + name, + [ + inputChannel: input, + sendReplyFreq: controls.at(\sendReplyFreq), + amplitudeAttackTime: controls.at(\amplitudeAttackTime), + amplitudeReleaseTime: controls.at(\amplitudeReleaseTime), + hfHainsworth: controls.at(\hfhainsworth), + hfFoote: controls.at(\hfFoote), + hfThreshold: controls.at(\hfThreshold), + hfWaitTime: controls.at(\hfWaitTime), + pitchInitFreq: controls.at(\pitchInitFreq), + pitchMinFreq: controls.at(\pitchMinFreq), + pitchMaxFreq: controls.at(\pitchMaxFreq), + pitchExecFreq: controls.at(\pitchExecFreq), + pitchMaxBinsPerOctave: controls.at(\pitchMaxBinsPerOctave), + pitchMedian: controls.at(\pitchMedian), + pitchAmpThreshold: controls.at(\pitchAmpThreshold), + pitchPeakThreshold: controls.at(\pitchPeakThreshold), + pitchDownSample: controls.at(\pitchDownSample) + ], + analyzerGroup + ).register; + ); + }); + } + + // set a synth control by provoding its name, its control name and control value + setSynthControl{ + arg name, controlName, controlValue; + synths.at(name).set(controlName, controlValue); + } + + // start a synth by name + startAnalysisSynth{ + arg name; + synths.at(name).run(true); + } + + // stop a synth by name + stopAnalysisSynth{ + arg name; + synths.at(name).run(false); + } + + // free a synth by name + freeAnalysisSynth{ + arg name; + synths.at(name).free; + } + + startAllAnalysisSynths{ + analyzerGroup.run(true); + } + + stopAllAnalysisSynths{ + analyzerGroup.run(false); + } +} diff --git a/classes/BowelyzerConfig.sc b/classes/BowelyzerConfig.sc new file mode 100644 index 0000000..287aad4 --- /dev/null +++ b/classes/BowelyzerConfig.sc @@ -0,0 +1,362 @@ +BowelyzerConfig{ + + const true, + \amplitudeAttackTime -> 0.01, + \amplitudeReleaseTime -> 0.1, + \hfHainsworth -> 1.0, + \hfFoote -> 0.0, + \hfThreshold -> 0.3, + \hfWaitTime -> 0.04, + \pitchInitFreq -> 440, + \pitchMinFreq -> 60, + \pitchMaxFreq -> 4000, + \pitchExecFreq -> 100, + \pitchMaxBinsPerOctave -> 16, + \pitchMedian -> 1, + \pitchAmpThreshold -> 0.01, + \pitchPeakThreshold -> 0.5, + \pitchDownSample -> 1, + \sendReplyFreq ->20 + ]); + defaultConfig = Dictionary.with(*[ + \inputs -> Dictionary.with(*[ + \left -> 0, + \right -> 1 + ]), + //names -> [left, right], + \synthServerAddress -> "127.0.0.1", + \synthServerPort -> 57110, + \hubAddress -> "127.0.0.1", + \hubPort -> 57120, + \forwardAddress -> "127.0.0.1", + \forwardPort -> 57120, + \controls -> Dictionary.with(*[ + \left -> defaultControls, + \right -> defaultControls + ]) + ]); + } + +// read configuration from file + readConfigurationFile{ + arg configFile; + var configFromFile, reader, path; + path = PathName.new(configFile.asString); + if(path.isFile,{ + postln("Reading configuration file: "++configFile); + try{ + configFromFile = (configFile.asString).parseYAMLFile; + configFromFile.keysValuesDo({|key, value| + switch(key.asSymbol, + \controls,{ + // adding names dictionary + config.put(key.asSymbol, Dictionary.new(value.size)); + // going through the names and their associated dictionaries + value.keysValuesDo({|name, dictionary| + if(dictionary.isKindOf(Dictionary),{ + config.at(key.asSymbol).put(name.asSymbol, Dictionary.new(dictionary.size)); + // going through each control dictionary with controls and their values + dictionary.keysValuesDo({|control, controlValue| + if(defaultControls.includesKey(control.asSymbol),{ + config.at(key.asSymbol).at(name.asSymbol).put(control.asSymbol, this.getControlValue(control.asSymbol, controlValue)); + }); + }); + },{ + error("This element should be of type Dictionary: "++dictionary); + }); + }); + }, + \inputs,{ + config.put(key.asSymbol, Dictionary.new()); + value.keysValuesDo({|name, channel| + config.at(\inputs).put(name.asSymbol, channel.asInteger); + }); + }, + { + if(defaultConfig.includesKey(key.asSymbol),{ + config.put(key.asSymbol, this.getSettingValue(key.asSymbol, value)); + },{ + error("Key is not included in known configuration: "++key); + }); + } + ); + }); + postln("Reading of configuration complete. Now validating..."); + if(this.validateConfig,{ + postln("Validation complete."); + ^true; + },{ + postln("Validation failed."); + ^false; + }); + }{ + ("Failed parsing the file: "++configFile).error; + ("Make sure its JSON syntax is valid!").error; + ^false; + }; + }, { + error("File not readable:"++configFile.asString); + ^false; + }); + } + + //TODO: add writeConfigurationFile + + // return a control value as correct type and within its defined ControlSpec range + getControlValue{ + arg control, value; + if(defaultControls.includesKey(control.asSymbol),{ + if(hasToBeFloat.includes(control.asSymbol),{ + ^control.asSymbol.asSpec.constrain(value.asFloat).asFloat; + }); + if(hasToBeInteger.includes(control.asSymbol),{ + ^control.asSymbol.asSpec.constrain(value.asInteger).asInteger; + }); + if(hasToBeBool.includes(control.asSymbol),{ + switch(value, + 0,{^false}, + 1,{^true}, + "true",{^true}, + "false",{^false} + ); + }); + },{ + ^nil; + }); + } + + //get a setting value as correct type + getSettingValue{ + arg setting, value; + if(defaultConfig.includesKey(setting.asSymbol),{ + if(hasToBeString.includes(setting.asSymbol),{ + ^value.asString; + }); + if(hasToBeInteger.includes(setting.asSymbol),{ + ^value.asInteger; + }); + },{ + ^nil; + }); + } + + // validate/extend/fix the config and return true if it's useable + validateConfig{ + var broken = false; + //fail if there are no inputs defined + if(config.includesKey(\inputs).not,{ + ^false; + }); + // if there are no controls defined at all, add at least a Dictionary for them + if(config.includesKey(\controls).not,{ + config.put(\controls, Dictionary.new(config.at(\inputs).size)); + }); + // go through the defaultConfig/defaultControl collection and compare it to the provided config + defaultConfig.keysValuesDo({|key, value| + if(key != \controls && key != \inputs,{ + // if a standard setting is not in the configuration, add it from the default + if(config.includesKey(key).not,{ + config.put(key, value); + }); + }); + }); + // go through the inputs and add controls, if there are none setup for them + config.at(\inputs).keysValuesDo({|name, channel| + // if there are no controls defined for the input, add them from default + if(config.at(\controls).includesKey(name).not,{ + config.at(\controls).put(name, defaultControls); + }); + }); + // go through each control dictionary + config.at(\controls).keysValuesDo({|name, controlDictionary| + if(config.at(\inputs).includesKey(name),{ + // go through the defaultControl Dictionary and add missing controls to controls from config + defaultControls.keysValuesDo({|defaultControl, defaultControlValue| + if(controlDictionary.includesKey(defaultControl).not,{ + config.at(\controls).at(name).put(defaultControl, defaultControlValue); + }); + }); + },{ + // remove controls for non-existing inputs + config.at(\controls).removeAt(name); + }); + }); + ^true; + } + + //print the current config + showConfig{ + postln("Configuration is: "); + config.keysValuesDo{|key, value| + switch(key, + \controls, { + postln(key++" ("++key.class++") -> ("++value.class++")"); + value.keysValuesDo({|subKey, subValue| + postln(" "++subKey++" ("++subKey.class++") -> ("++subValue.class++")"); + subValue.keysValuesDo({|subSubKey, subSubValue| + postln(" "++subSubKey++" ("++subSubKey.class++") -> "++subSubValue++" ("++subSubValue.class++")"); + }); + }); + }, + \inputs, { + postln(key++" ("++key.class++") -> ("++value.class++")"); + value.keysValuesDo({|subKey, subValue| + postln(" "++subKey++" ("++subKey.class++") -> "++subValue++" ("++subValue.class++")"); + }); + }, + {postln(key++" ("++key.class++") -> "++value++" ("++value.class++")");} + ); + }; + } + + getSynthControl{ + arg name, control; + if(config.at(\controls).includesKey(name) && config.at(\controls).at(name).includes(control),{ + ^config.at(\controls).at(name).at(control); + },{ + ^false; + }); + } + + // sets a control to a value for a synth + setSynthControl{ + arg name, control; + if(config.at(\controls).includesKey(name) && config.at(\controls).at(name).includes(control[0]),{ + config.at(\controls).at(name).put(control[0], control[1]); + ^true; + },{ + ^false; + }); + } + +} diff --git a/classes/BowelyzerGUI.sc b/classes/BowelyzerGUI.sc new file mode 100644 index 0000000..e26798e --- /dev/null +++ b/classes/BowelyzerGUI.sc @@ -0,0 +1,520 @@ +BowelyzerGUI{ + + var mainView,