diff options
author | David Runge <dave@sleepmap.de> | 2016-05-29 13:38:07 +0200 |
---|---|---|
committer | David Runge <dave@sleepmap.de> | 2016-05-29 13:38:07 +0200 |
commit | 74bb3e3290d8f4ea82b2caf79f4b96bb7991faad (patch) | |
tree | 2da93c9e1923893ec752108733397204821e273d /BowelyzerConfig.sc | |
parent | 33d8b5bff1feb3c35fc049e29fcaca985d50520b (diff) | |
download | bowelyzer-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.sc | 229 |
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++")"); + }); + }; + } + +} |