aboutsummaryrefslogtreecommitdiffstats
path: root/BowelyzerConfig.sc
diff options
context:
space:
mode:
authorDavid Runge <dave@sleepmap.de>2016-05-29 13:38:07 +0200
committerDavid Runge <dave@sleepmap.de>2016-05-29 13:38:07 +0200
commit74bb3e3290d8f4ea82b2caf79f4b96bb7991faad (patch)
tree2da93c9e1923893ec752108733397204821e273d /BowelyzerConfig.sc
parent33d8b5bff1feb3c35fc049e29fcaca985d50520b (diff)
downloadbowelyzer-74bb3e3290d8f4ea82b2caf79f4b96bb7991faad.tar.gz
bowelyzer-74bb3e3290d8f4ea82b2caf79f4b96bb7991faad.tar.bz2
bowelyzer-74bb3e3290d8f4ea82b2caf79f4b96bb7991faad.tar.xz
bowelyzer-74bb3e3290d8f4ea82b2caf79f4b96bb7991faad.zip
First commit of bowelyzer code. Includes Bowelyzer.sc, Bowelyzer{Analyzer,Config,OSCHub}.sc, bowelyzer.scd (for help) and darmstadt.json for a standard configuration in JSON.
Diffstat (limited to 'BowelyzerConfig.sc')
-rw-r--r--BowelyzerConfig.sc229
1 files changed, 229 insertions, 0 deletions
diff --git a/BowelyzerConfig.sc b/BowelyzerConfig.sc
new file mode 100644
index 0000000..9686c17
--- /dev/null
+++ b/BowelyzerConfig.sc
@@ -0,0 +1,229 @@
+BowelyzerConfig{
+
+ var <config,
+ <defaultConfig,
+ <defaultControls,
+ <changed = false,
+ <hasToBeString,
+ <hasToBeInteger,
+ <hasToBeArray,
+ <hasToBeDictionary,
+ <hasToBeFloat;
+
+
+ *new{
+ arg config;
+ ^super.new.init(config);
+ }
+
+ init{
+ arg configFile;
+ hasToBeString = [
+ \forwardAddress,
+ \hubAddress,
+ \synthServerAddress
+ ];
+ hasToBeInteger = [
+ \forwardPort,
+ \hubPort,
+ \synthServerPort,
+ \pitchMedian,
+ \pitchDownSample
+ ];
+ hasToBeArray = [
+ \names,
+ \channelOffset
+ ];
+ hasToBeDictionary = [
+ \controls,
+ \left,
+ \right
+ ];
+ hasToBeFloat = [
+ \amplitudeAttackTime,
+ \amplitudeReleaseTime,
+ \hfHainsworth,
+ \hfFoote,
+ \hfThreshold,
+ \hfWaitTime,
+ \pitchInitFreq,
+ \pitchMinFreq,
+ \pitchMaxFreq,
+ \pitchExecFreq,
+ \pitchMaxBinsPerOctave,
+ \pitchAmpThreshold,
+ \pitchPeakThreshold,
+ \sendReplyFreq
+ ];
+ config = this.createDefaultConfig;
+ if(configFile.notNil,{
+ this.readConfigurationFile(configFile)
+ },{
+ ("No configuration file provided. Using default.").postln;
+ });
+ this.showConfig;
+ }
+
+// create the default configuration
+ createDefaultConfig{
+ defaultControls = Dictionary.with(*[
+ "amplitudeAttackTime" -> 0.01,
+ "amplitudejReleaseTime" -> 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(*[
+ "channelOffset" -> [0, 0],
+ "names" -> ["left", "right"],
+ "synthServerAddress" -> "127.0.0.1",
+ "synthServerPort"->57110,
+ "hubAddress" -> "127.0.0.1",
+ "hubPort" -> 57120,
+ "forwardAddress" -> "127.0.0.1",
+ "forwardPort" -> 9999,
+ "controls" -> Dictionary.with(*[
+ "left" -> defaultControls,
+ "right" -> defaultControls
+ ])
+ ]);
+ ^defaultConfig;
+ }
+
+// 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|
+ if(config.includesKey(key),{
+ config.put(key,value);
+ });
+ });
+ this.validateConfig;
+ }{
+ ("Failed parsing the file: "++configFile).error;
+ ("Make sure its JSON syntax is valid!").error;
+ };
+ }, {
+ error("File not readable:"++configFile.asString);
+ });
+ this.validateConfig;
+ }
+
+ //check common mistakes in configuration and try fixing them
+ validateConfig{
+ var broken = false;
+ //check for correct types
+ config.keysValuesDo({|key, value|
+ if(key.isKindOf(String).not,{
+ error("Key is no string: "++key);
+ broken = true;
+ });
+ // check if the strings are associated with the correct keys
+ if(hasToBeString.includes(key.asSymbol) && value.isKindOf(String).not, {
+ config.put(key, value.asString);
+ });
+ // check if the integers are associated with the correct keys
+ if(hasToBeInteger.includes(key.asSymbol) && value.isKindOf(Integer).not, {
+ config.put(key, value.asInteger);
+ });
+ // check if the floats are associated with the correct keys
+ if(hasToBeFloat.includes(key.asSymbol) && value.isKindOf(Float).not, {
+ config.put(key, value.asFloat);
+ });
+ // check if the dictionaries are associated with the correct keys
+ if(hasToBeDictionary.includes(key.asSymbol) && value.isKindOf(Dictionary).not, {
+ error("Value ("++value++") of key ("++key++") should be of type Dictionary.");
+ broken = true;
+ });
+ //check if arrays are associated with the correct keys
+ if(hasToBeArray.includes(key.asSymbol),{
+ if(value.isArray.not,{
+ error("Value ("++value++") of key ("++key++") should be Array.");
+ broken = true;
+ },{
+ //setting correct types in Arrays
+ if((key == "channelOffset") && (value.size >= 1) && value[0].isKindOf(Integer).not,{
+ for(0, value.size-1, {|i|
+ config.at(key)[i] = value[i].asInteger;
+ });
+ });
+ if((key == "names") && (value.size >= 1) && value[0].isKindOf(String).not,{
+ for(0, value.size-1, {|i|
+ config.at(key)[i] = value[i].asString;
+ });
+ });
+ });
+ });
+ // check if controls dictionaries are setup correctly
+ if(key == "controls",{
+ value.keysValuesDo({|name, controls|
+ if(hasToBeDictionary.includes(name.asSymbol) && controls.isKindOf(Dictionary).not, {
+ error("Value ("++controls++") of key ("++name++") should be of type Dictionary.");
+ broken = true;
+ },{
+ config.at("controls").at(name).keysValuesDo({|controlKey, controlValue|
+ // check if the integers are associated with the correct keys
+ if(hasToBeInteger.includes(controlKey.asSymbol) && controlValue.isKindOf(Integer).not, {
+ config.at(key).at(name).put(controlKey, controlValue.asInteger);
+ });
+ // check if the floats are associated with the correct keys
+ if(hasToBeFloat.includes(controlKey.asSymbol) && controlValue.isKindOf(Float).not, {
+ config.at(key).at(name).put(controlKey, controlValue.asFloat);
+ });
+ });
+ });
+ });
+ });
+ });
+ // if not completely broken, fix stuff
+ if(broken,{
+ error("There were errors. Reverting to default config.");
+ config = this.createDefaultConfig;
+ },{
+ postln("Fixing stuff");
+ // zero-pad channel offsets
+ if(config.at("names").size > config.at("channelOffset").size,{
+ var difference = config.at("names").size - config.at("channelOffset").size;
+ config.at("channelOffset").asArray = config.at("channelOffset")++Array.fill(difference, {arg i; i*0});
+ });
+ //TODO: add defaultControls for channels that have none
+ //TODO: fill non-existing keys with default values (in case config file is incomplete)
+ });
+ }
+
+ //print the current config
+ showConfig{
+ postln("Configuration is:");
+ config.keysValuesDo{|key, value|
+ if(key == "controls",{
+ postln(key++" ("++key.class++") ->");
+ value.keysValuesDo{|key, value|
+ postln( key++" ("++key.class++"):");
+ value.keysValuesDo{|key, value|
+ postln(" "++key++" ("++key.class++") -> "++value++" ("++value.class++")");
+ }
+ }
+ },{
+ postln(key++" ("++key.class++") -> "++value++" ("++value.class++")");
+ });
+ };
+ }
+
+}