Logo Search packages:      
Sourcecode: csound version File versions  Download package

Lindenmayer.cpp

/**
 * C S O U N D   V S T
 *
 * A VST plugin version of Csound, with Python scripting.
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "CppSound.hpp"
#include "Lindenmayer.hpp"
#include <iostream>
#include <iomanip>
#include <boost/format.hpp>
#include <sstream>
#if defined(HAVE_IO_H)
#include <io.h>
#endif
#include <stdio.h>
using boost::format;
using boost::io::group;

namespace csound
{
  Lindenmayer::Lindenmayer() : angle(1.0)
  {
  }

  Lindenmayer::~Lindenmayer()
  {
  }

  std::string Lindenmayer::getReplacement(std::string word)
  {
    if(rules.find(word) == rules.end())
      {
      return word;
      }
    else
      {
      return rules[word];
      }
  }

  void Lindenmayer::generate()
  {
    std::string word;
    std::string replacement;
    std::ifstream inputStream;
    std::ofstream outputStream;
    std::string inputFilename = "a.lindenmayer";
    std::string outputFilename = "b.lindenmayer";
    std::string tempFilename;
    outputStream.open(outputFilename.c_str());
    outputStream << axiom.c_str() << std::endl;
    outputStream.close();
    for(int i = 0; i < iterationCount; i++)
      {
      std::ifstream inputStream;
      std::ofstream outputStream;
      tempFilename = inputFilename;
      inputFilename = outputFilename;
      outputFilename = tempFilename;
      unlink(outputFilename.c_str());
      inputStream.open(inputFilename.c_str());
      inputStream.seekg(0, std::ios_base::beg);
      outputStream.open(outputFilename.c_str());
      while(!inputStream.eof())
        {
          inputStream >> word;
          inputStream >> std::ws;
          replacement = getReplacement(word);
          outputStream << replacement << std::endl;
        }
      inputStream.close();
      outputStream.close();
      }
    score.scaleActualMinima = turtle;
    score.scaleActualRanges = turtle;
    initialize();
    inputStream.open(inputFilename.c_str());
    while(!inputStream.eof())
      {
      inputStream >> word;
      interpret(word, false);
      }
    initialize();
    inputStream.close();
    std::ifstream finalInputStream(inputFilename.c_str());
    while(!finalInputStream.eof())
      {
      finalInputStream >> word;
      //std::cerr << word << std::endl;
      interpret(word, true);
      }
    finalInputStream.close();
    for(std::vector<Event>::iterator i = score.begin(); i != score.end(); ++i)
      {
      Event &event = *i;
      event.setStatus(MidiFile::CHANNEL_NOTE_ON);
      }
  }

  void Lindenmayer::initialize()
  {
    turtle = csound::Event();
    turtleStep = csound::Event();
    for(size_t i = 0; i < Event::HOMOGENEITY; i++)
      {
      turtleStep[i] = 1.0;
      }
    turtleOrientation = csound::Event();
    turtleOrientation[Event::TIME] = 1.0;
  }

  void Lindenmayer::interpret(std::string action, bool render)
  {
    try
      {
      action = Conversions::trim(action); 
        char command = action[0];
        switch(command)
          {
          case 'N':
            {
            // N
            // 0
            if(render)
              {
                Event event = turtle;
                //score.rescale(event);
                score.push_back(event);
              }
            else
              {
                updateActual(turtle);
              }
            }
            break;
          case 'M':
            {
            // Mn
            // 01
            double a = 1.0;
            if(action.length () > 1)
              {
                a = Conversions::stringToDouble(action.substr(1));
              }
            double step;
            for (int i = 0; i < Event::HOMOGENEITY; i++)
              {
                step = turtle[i] + (turtleStep[i] * a * turtleOrientation[i]);
                turtle[i] = step;
              }
            }
            break;
          case 'R':
            {
            // Rddn
            // 0123
            size_t d1 = getDimension(action[1]);
            size_t d2 = getDimension(action[2]);
            double n = 1.0;
            if(action.length() > 3)
              {
                n = Conversions::stringToDouble(action.substr(3));
              }
            double a = angle * n;
            ublas::matrix<double> rotation = createRotation (d1, d2, a);
            std::cerr << "Orientation before rotation: " << std::endl;
            for (int i = 0; i < turtleOrientation.size(); i++)
              {
                std::cerr << format("%9.3f ") % turtleOrientation(i);
              }
            std::cerr << std::endl;
            std::cerr << "Rotation for angle " << a << ":" << std::endl;
            for (int i = 0; i < rotation.size1(); i++)
              {
                for (int j = 0; j < rotation.size2(); j++ )
                  {
                  std::cerr << format("%9.3f ") % rotation(i, j);
                  }
                std::cerr << std::endl;
              }
            turtleOrientation = ublas::prod(rotation, turtleOrientation);
            std::cerr << "Orientation after rotation: " << std::endl;
            for (int i = 0; i < turtleOrientation.size(); i++)
              {
                std::cerr << format("%9.3f ") % turtleOrientation(i);
              }
            std::cerr << std::endl;
            std::cerr << std::endl;
            }
            break;
          case 'T':
            {
            // Tdon
            // 0123
            size_t dimension = getDimension(action[1]);
            char operation = action[2];
            double n = 1.0;
            if(action.length() > 3)
              {
                n = Conversions::stringToDouble(action.substr(3));
              }
            switch(operation)
              {
              case '=':
                turtle[dimension] =  (turtleStep[dimension] * n);
                break;
              case '*':
                turtle[dimension] = (turtle[dimension] * (turtleStep[dimension] * n));
                break;
              case '/':
                turtle[dimension] = (turtle[dimension] / (turtleStep[dimension] * n));
                break;
              case '+':
                turtle[dimension] = (turtle[dimension] + (turtleStep[dimension] * n));
                break;
              case '-':
                turtle[dimension] = (turtle[dimension] - (turtleStep[dimension] * n));
                break;
              }
            if(dimension == Event::PITCHES)
              {
                turtle[dimension] = Conversions::modulus(turtle[dimension], 4096.0);
                  }
            }
            break;
          case 'S':
            {
            // Sdon
            // 0123
            size_t dimension = getDimension(action[1]);
            char operation = action[2];
            double n = 1.0;
            if(action.length() > 3)
              {
                n = Conversions::stringToDouble(action.substr(3));
              }
            switch(operation)
              {
              case '=':
                turtleStep[dimension] = n;
                break;
              case '*':
                turtleStep[dimension] = (turtleStep[dimension] * n);
                break;
              case '/':
                turtleStep[dimension] = (turtleStep[dimension] / n);
                break;
              case '+':
                turtleStep[dimension] = (turtleStep[dimension] + n);
                break;
              case '-':
                turtleStep[dimension] = (turtleStep[dimension] - n);
                break;
              }
            //std::cerr << "step for " << dimension << " = " << turtleStep[dimension] << std::endl;
            if(dimension == Event::PITCHES)
              {
                turtle[dimension] = Conversions::modulus(turtle[dimension], 4096.0);
              }
            }
            break;
          case '[':
            {
            Event a = turtle;
            turtleStack.push(a);
            Event b = turtleStep;
            turtleStepStack.push(b);
            Event c = turtleOrientation;
            turtleOrientationStack.push(c);
            }
            break;
          case ']':
            {
            turtle = turtleStack.top();
            turtleStack.pop();
            turtleStep = turtleStepStack.top();
            turtleStepStack.pop();
            turtleOrientation = turtleOrientationStack.top();
            turtleOrientationStack.pop();
            }
            break;
          }
      }
    catch(void *x)
      {
      std::cout << x << std::endl;
      }
  }

  int Lindenmayer::getDimension (char dimension) const
  {
    switch(dimension)
      {
      case 'i': return Event::INSTRUMENT;
      case 't': return Event::TIME;
      case 'd': return Event::DURATION;
      case 'k': return Event::KEY;
      case 'v': return Event::VELOCITY;
      case 'p': return Event::PHASE;
      case 'x': return Event::PAN;
      case 'y': return Event::HEIGHT;
      case 'z': return Event::DEPTH;
      case 's': return Event::PITCHES;
      }
    return -1;
  }

  ublas::matrix<double> Lindenmayer::createRotation (int dimension1, int dimension2, double angle) const
  {
    ublas::matrix<double> rotation_ = ublas::identity_matrix<double>(Event::ELEMENT_COUNT);
    rotation_(dimension1,dimension1) =  std::cos(angle);
    rotation_(dimension1,dimension2) = -std::sin(angle);
    rotation_(dimension2,dimension1) =  std::sin(angle);
    rotation_(dimension2,dimension2) =  std::cos(angle);
    return rotation_;
  }

  void Lindenmayer::updateActual(Event &event)
  {
    for(int i = 0, n = event.size(); i < n; i++)
      {
      if(score.scaleActualMinima[i] < event[i])
        {
          score.scaleActualMinima[i] = event[i];
        }
      if(score.scaleActualRanges[i] >= (score.scaleActualMinima[i] + event[i]))
        {
          score.scaleActualRanges[i] = (score.scaleActualMinima[i] + event[i]);
        }
      }
  }

  void Lindenmayer::rewrite()
  {
    System::inform("BEGAN Lindenmayer::rewrite()...");
    std::stringstream production(axiom);
    std::stringstream priorProduction;
    std::string symbol;
    std::string replacement;
    for (int i = 0; i < iterationCount; i++)
      {
      priorProduction.clear();
      priorProduction << production.str();
      production.clear();
      while (!priorProduction.eof())
        {
          priorProduction >> symbol;
          if(rules.find(symbol) == rules.end())
            {
            replacement = symbol;
            }
          else
            {
            replacement = rules[symbol];
            }
          production << replacement;
        }
      }
    System::inform("ENDED Lindenmayer::rewrite().");
  }

  double Lindenmayer::getAngle() const
  {
    return angle;
  }

  void Lindenmayer::setAngle(double angle)
  {
    this->angle = angle;
  }

  std::string Lindenmayer::getAxiom() const
  {
    return axiom;
  }

  void Lindenmayer::setAxiom(std::string axiom)
  {
    this->axiom = axiom;
  }

  void Lindenmayer::addRule(std::string command, std::string replacement)
  {
    rules[command] = replacement;
  }

  int Lindenmayer::getIterationCount() const
  {
    return iterationCount;
  }

  void Lindenmayer::setIterationCount(int count)
  {
    iterationCount = count;
  }

  void Lindenmayer::clear()
  {
    initialize();
    rules.clear();
    while(!turtleStack.empty())
      {
      turtleStack.pop();
      }
    while(!turtleStepStack.empty())
      {
      turtleStepStack.pop();
      }
    while(!turtleOrientationStack.empty())
      {
      turtleOrientationStack.pop();
      }
  }
}


Generated by  Doxygen 1.6.0   Back to index