ian@0: // Copyright 2011, Ian Hobson. ian@0: // ian@0: // This file is part of gpsynth. ian@0: // ian@0: // gpsynth is free software: you can redistribute it and/or modify ian@0: // it under the terms of the GNU General Public License as published by ian@0: // the Free Software Foundation, either version 3 of the License, or ian@0: // (at your option) any later version. ian@0: // ian@0: // gpsynth is distributed in the hope that it will be useful, ian@0: // but WITHOUT ANY WARRANTY; without even the implied warranty of ian@0: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ian@0: // GNU General Public License for more details. ian@0: // ian@0: // You should have received a copy of the GNU General Public License ian@0: // along with gpsynth in the file COPYING. ian@0: // If not, see http://www.gnu.org/licenses/. ian@0: ian@0: // SuperCollider grammar, resonsible for generating and altering SuperCollider ian@0: // synth graphs ian@0: ian@0: #pragma once ian@0: ian@0: #include "grammar.hpp" ian@0: #include "range.hpp" ian@0: #include "synth_graph.hpp" ian@0: ian@0: #include ian@0: #include ian@0: #include ian@0: ian@0: namespace sc { ian@0: ian@0: struct Argument { ian@0: ian@0: enum ScalingMode { ian@0: kScalingLinear, ian@0: kScalingLog, ian@0: kConstant ian@0: }; ian@0: ian@0: std::string name_; ian@0: stdx::Range range_; ian@0: stdx::Range range_control_; ian@0: ScalingMode scaling_mode_; ian@0: double constant_value_; ian@0: bool fixed_range_; ian@0: ian@0: Argument(const std::string name = "") ian@0: : name_(name), ian@0: range_(0, 1), ian@0: range_control_(0, 1), ian@0: scaling_mode_(kScalingLinear), ian@0: constant_value_(0), ian@0: fixed_range_(false) ian@0: {} ian@0: }; ian@0: ian@0: class Command { ian@0: public: ian@0: enum CommandMode { ian@0: kSource, ian@0: kModifier, ian@0: kSpecial, ian@0: kNumberOfModes ian@0: }; ian@0: ian@0: enum SpecialCommands { ian@0: kMixer, ian@0: kMultiplier, ian@0: kNumberOfSpecialCommands ian@0: }; ian@0: ian@0: enum OutputType { ian@0: kAll, ian@0: kAudio, ian@0: kControl, ian@0: }; ian@0: ian@0: private: ian@0: std::string name_; ian@0: std::vector arguments_; ian@0: CommandMode mode_; ian@0: OutputType output_; ian@0: ian@0: public: ian@0: Command(const std::string& name, ian@0: CommandMode mode, ian@0: OutputType output = kAll, ian@0: const std::vector& arguments = std::vector()) ian@0: : name_(name), ian@0: mode_(mode), ian@0: output_(output), ian@0: arguments_(arguments) ian@0: {} ian@0: ian@0: CommandMode Mode() const { return mode_; } ian@0: OutputType Output() const { return output_; } ian@0: const std::string& Name() const { return name_; } ian@0: const std::vector& Arguments() const { return arguments_;} ian@0: const Argument& GetArgument(int argument) const { ian@0: return arguments_[argument]; ian@0: } ian@0: bool IsAudioSource() { return (mode_ == kSource) && (output_ != kControl); } ian@0: }; ian@0: ian@0: class Grammar : public GrammarInterface { ian@0: // holds the commands available to the grammar ian@0: std::vector commands_; ian@0: typedef std::vector::size_type CommandID; ian@0: int max_depth_; ian@0: ian@0: public: ian@0: // used when generating trees to indicate current tree state ian@0: enum TreeMode { ian@0: kTreeMode_Command, ian@0: kTreeMode_Mod ian@0: }; ian@0: ian@0: Grammar(const std::string& json_data); ian@0: ian@0: void ParseJSON(const std::string& json_data); ian@0: ian@0: const std::vector& Commands() const { return commands_; } ian@0: ian@0: void SetMaximumDepth(int max_depth) { max_depth_ = max_depth; } ian@0: ian@0: void RandomGraph(sg::Graph& graph) const; ian@0: void PickCrossoverNodes(const sg::Graph& parent_1, ian@0: const sg::Graph& parent_2, ian@0: sg::Vertex* crossover_node_1, ian@0: sg::Vertex* crossover_node_2) const; ian@0: bool MutationReplaceSubTree(sg::Graph& graph) const; ian@0: bool MutationAddSubTree(sg::Graph& graph) const; ian@0: bool MutationModifyInputs(sg::Graph& graph) const; ian@0: bool MutationModifyConnections(sg::Graph& graph) const; ian@0: bool MutationReplaceCommand(sg::Graph& graph) const; ian@0: bool MutationInsertCommand(sg::Graph& graph) const; ian@0: ian@0: private: ian@0: int RandomCommand(sg::CommandRate rate, ian@0: int tree_depth, ian@0: bool must_be_modifier) const; ian@0: int RandomParameter(sg::Graph& graph) const; ian@0: ian@0: sg::Vertex RandomTree(sg::Graph& graph, ian@0: sg::CommandRate rate, ian@0: TreeMode tree_mode, ian@0: int depth) const; ian@0: ian@0: sg::Vertex SpecialCommand(int command_id, ian@0: sg::Graph& graph, ian@0: sg::CommandRate output_mode, ian@0: TreeMode tree_mode, ian@0: int depth = 0, ian@0: int minimum_channels = 2) const; ian@0: void AddTreeToSpecialCommand(sg::Vertex command, ian@0: sg::Graph& graph, ian@0: int input_id, ian@0: TreeMode tree_mode, ian@0: sg::CommandRate command_rate, ian@0: bool* constant_added, ian@0: std::set* parameters, ian@0: int depth) const; ian@0: sg::Vertex CreateCommand(sg::Graph &graph, ian@0: sg::CommandRate rate, ian@0: int depth, ian@0: bool must_be_modifier = false, ian@0: bool make_modifier_input = true) const; ian@0: int GetCommandInputID(int command_id) const; ian@0: const Argument& GetCommandArgument(int command_id, int argument_id) const; ian@0: const std::vector& CommandArguments(int command) const; ian@0: }; ian@0: ian@0: } // sc namespace