view src/sc_grammar.hpp @ 0:add35537fdbb tip

Initial import
author irh <ian.r.hobson@gmail.com>
date Thu, 25 Aug 2011 11:05:55 +0100
parents
children
line wrap: on
line source
//  Copyright 2011, Ian Hobson.
//
//  This file is part of gpsynth.
//
//  gpsynth 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.
//
//  gpsynth 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 gpsynth in the file COPYING. 
//  If not, see http://www.gnu.org/licenses/.

// SuperCollider grammar, resonsible for generating and altering SuperCollider
// synth graphs

#pragma once

#include "grammar.hpp"
#include "range.hpp"
#include "synth_graph.hpp"

#include <map>
#include <string>
#include <vector>

namespace sc {

struct Argument {
  
  enum ScalingMode {
    kScalingLinear,
    kScalingLog,
    kConstant
  };
  
  std::string name_;
  stdx::Range<double> range_;
  stdx::Range<double> range_control_;
  ScalingMode scaling_mode_;
  double constant_value_;
  bool fixed_range_;
  
  Argument(const std::string name = "")
  : name_(name),
    range_(0, 1),
    range_control_(0, 1),
    scaling_mode_(kScalingLinear),
    constant_value_(0),
    fixed_range_(false)
  {}
};

class Command {
public:
  enum CommandMode {
    kSource,
    kModifier,
    kSpecial,
    kNumberOfModes
  };
  
  enum SpecialCommands {
    kMixer,
    kMultiplier,
    kNumberOfSpecialCommands
  };
  
  enum OutputType {
    kAll,
    kAudio,
    kControl,
  };

private:
  std::string name_;
  std::vector<Argument> arguments_;
  CommandMode mode_;
  OutputType output_;
  
public:
  Command(const std::string& name,
          CommandMode mode,
          OutputType output = kAll,
          const std::vector<Argument>& arguments = std::vector<Argument>())
  : name_(name),
    mode_(mode),
    output_(output),
    arguments_(arguments)
  {}
  
  CommandMode Mode() const { return mode_; }
  OutputType Output() const { return output_; }
  const std::string& Name() const { return name_; }
  const std::vector<Argument>& Arguments() const { return arguments_;}
  const Argument& GetArgument(int argument) const {
    return arguments_[argument];
  }
  bool IsAudioSource() { return (mode_ == kSource) && (output_ != kControl); }
};

class Grammar : public GrammarInterface {
  // holds the commands available to the grammar
  std::vector<Command> commands_;
  typedef std::vector<Command>::size_type CommandID;
  int max_depth_;

public:
  // used when generating trees to indicate current tree state
  enum TreeMode {
    kTreeMode_Command,
    kTreeMode_Mod
  };
  
  Grammar(const std::string& json_data);
  
  void ParseJSON(const std::string& json_data);
  
  const std::vector<Command>& Commands() const { return commands_; }
  
  void SetMaximumDepth(int max_depth) { max_depth_ = max_depth; }
  
  void RandomGraph(sg::Graph& graph) const;
  void PickCrossoverNodes(const sg::Graph& parent_1, 
                          const sg::Graph& parent_2,
                          sg::Vertex* crossover_node_1,
                          sg::Vertex* crossover_node_2) const;
  bool MutationReplaceSubTree(sg::Graph& graph) const;
  bool MutationAddSubTree(sg::Graph& graph) const;
  bool MutationModifyInputs(sg::Graph& graph) const;
  bool MutationModifyConnections(sg::Graph& graph) const;
  bool MutationReplaceCommand(sg::Graph& graph) const;
  bool MutationInsertCommand(sg::Graph& graph) const;
  
private:
  int RandomCommand(sg::CommandRate rate,
                    int tree_depth,
                    bool must_be_modifier) const;
  int RandomParameter(sg::Graph& graph) const;
  
  sg::Vertex RandomTree(sg::Graph& graph,
                        sg::CommandRate rate,
                        TreeMode tree_mode,
                        int depth) const;
  
  sg::Vertex SpecialCommand(int command_id,
                            sg::Graph& graph,
                            sg::CommandRate output_mode,
                            TreeMode tree_mode,
                            int depth = 0,
                            int minimum_channels = 2) const;
  void AddTreeToSpecialCommand(sg::Vertex command,
                               sg::Graph& graph,
                               int input_id,
                               TreeMode tree_mode,
                               sg::CommandRate command_rate,
                               bool* constant_added,
                               std::set<int>* parameters,
                               int depth) const;
  sg::Vertex CreateCommand(sg::Graph &graph,
                           sg::CommandRate rate,
                           int depth,
                           bool must_be_modifier = false,
                           bool make_modifier_input = true) const;
  int GetCommandInputID(int command_id) const;
  const Argument& GetCommandArgument(int command_id, int argument_id) const;
  const std::vector<sc::Argument>& CommandArguments(int command) const;
};
  
} // sc namespace