Logo Search packages:      
Sourcecode: csound version File versions

VoiceleadingNode.cpp

/*
 * C S O U N D
 *
 * 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 "VoiceleadingNode.hpp"
#include "Conversions.hpp"
#include "Voicelead.hpp"
#include "System.hpp"

#include <cmath>
#include <cfloat>
#include <sstream>

namespace csound
{
  extern void printChord(std::ostream &stream, std::string label, const std::vector<double> &chord);

  extern void printChord(std::string label, const std::vector<double> &chord);

  VoiceleadingOperation::VoiceleadingOperation() :
    beginTime(0.0),
    rescaledBeginTime(0.0),
    endTime(0.0),
    rescaledEndTime(0.0),
#ifdef MSVC
    P(DBL_MAX),
    T(DBL_MAX),
    C(DBL_MAX),
    V(DBL_MAX),
#else
    P(double(0.0) / double(0.0)),
    T(double(0.0) / double(0.0)),
    C(double(0.0) / double(0.0)),
    V(double(0.0) / double(0.0)),
#endif
    L(false),
    begin(0),
    end(0),
    avoidParallels(false)
  {
  }

  VoiceleadingOperation::~VoiceleadingOperation()
  {
  }

  VoiceleadingNode::VoiceleadingNode() :
    base(36.0),
    range(60.0),
    rescaleTimes(true),
    avoidParallels(true),
    divisionsPerOctave(12)
  {
  }

  VoiceleadingNode::~VoiceleadingNode()
  {
  }

  std::ostream &operator << (std::ostream &stream, const VoiceleadingOperation &operation)
  {
    stream << "  beginTime:         " << operation.beginTime << std::endl;
    stream << "  endTime:           " << operation.endTime << std::endl;
    stream << "  rescaledBeginTime: " << operation.rescaledBeginTime << std::endl;
    stream << "  rescaledEndTime:   " << operation.rescaledEndTime << std::endl;
    stream << "  begin:             " << operation.begin << std::endl;
    stream << "  end:               " << operation.end << std::endl;
#ifdef MSVC
    if (!(operation.P == DBL_MAX)) {
      stream << "  P:                 " << operation.P << std::endl;
    }
    if (!(operation.T == DBL_MAX)) {
      stream << "  T:                 " << operation.T << std::endl;
    }
    if (!(operation.C == DBL_MAX)) {
      stream << "  C:                 " << operation.C << std::endl;
    }
    if (!(operation.V == DBL_MAX)) {
      stream << "  V:                 " << operation.V << std::endl;
    }
#else
    if (!std::isnan(operation.P)) {
      stream << "  P:                 " << operation.P << std::endl;
    }
    if (!std::isnan(operation.T)) {
      stream << "  T:                 " << operation.T << std::endl;
    }
    if (!std::isnan(operation.C)) {
      stream << "  C:                 " << operation.C << std::endl;
    }
    if (!std::isnan(operation.V)) {
      stream << "  V:                 " << operation.V << std::endl;
    }
#endif
    if (operation.L) {
      stream << "  L:                 " << int(operation.L) << std::endl;
    }
    return stream;
  }

00116   void VoiceleadingNode::apply(Score &score, const VoiceleadingOperation &priorOperation, const VoiceleadingOperation &operation)
  {
    if ( (System::getMessageLevel() & System::INFORMATION_LEVEL) == System::INFORMATION_LEVEL) {
      std::stringstream stream;
      stream << "BEGAN VoiceleadingNode::apply:..." << std::endl;
      stream << "Events in score:     " << score.size() << std::endl;
      stream << "Score duration:      " << score.getDuration() << std::endl;
      stream << "Events in operation: " << (operation.end - operation.begin) << std::endl;
      stream << "priorOperation:      " << std::endl << priorOperation;
      stream << "currrentOperation:   " << std::endl << operation;
      stream << std::endl;
      System::inform(stream.str().c_str());
    }
    if (operation.begin == operation.end) {
      return;
    }
#ifdef MSVC
    if (!(operation.P == DBL_MAX) && !(operation.T == DBL_MAX)) {
      if (!(operation.V == DBL_MAX)) {
#else
    if (!std::isnan(operation.P) && !std::isnan(operation.T)) {
      if (!std::isnan(operation.V)) {
#endif
        score.setPTV(operation.begin,
                     operation.end,
                     operation.P,
                     operation.T,
                     operation.V,
                     base,
                     range);
      } else if (operation.L) {
        score.setPT(operation.begin,
                    operation.end,
                    operation.P,
                    operation.T,
                    base,
                    range,
                    divisionsPerOctave);
        score.voicelead(priorOperation.begin,
                        priorOperation.end,
                        operation.begin,
                        operation.end,
                        base,
                        range,
                        avoidParallels,
                        divisionsPerOctave);
      } else {
        score.setPT(operation.begin,
                    operation.end,
                    operation.P,
                    operation.T,
                    base,
                    range,
                    divisionsPerOctave);
      }
#ifdef MSVC
    } else if (!(operation.C == DBL_MAX)) {
      if (!(operation.V == DBL_MAX)) {
#else
    } else if (!std::isnan(operation.C)) {
      if (!std::isnan(operation.V)) {
#endif
        std::vector<double> pcs = Voicelead::mToPitchClassSet(Voicelead::cToM(operation.C, divisionsPerOctave), divisionsPerOctave);
        printChord("CV", pcs);
        std::vector<double> pt = Voicelead::pitchClassSetToPandT(pcs, divisionsPerOctave);
        double prime = pt[0];
        double transposition = pt[1];
        System::inform("prime: %f transposition %f: divisionsPerOctave %d\n", prime, transposition, divisionsPerOctave);
        score.setPTV(operation.begin,
                     operation.end,
                     prime,
                     transposition,
                     operation.V,
                     base,
                     range);
      } else if (operation.L) {
        std::vector<double> pcs = Voicelead::mToPitchClassSet(Voicelead::cToM(operation.C, divisionsPerOctave), divisionsPerOctave);
        printChord("CL", pcs);
        score.voicelead(priorOperation.begin,
                        priorOperation.end,
                        operation.begin,
                        operation.end,
                        pcs,
                        base,
                        range,
                        avoidParallels,
                        divisionsPerOctave);
      } else {
        std::vector<double> pcs = Voicelead::mToPitchClassSet(Voicelead::cToM(operation.C, divisionsPerOctave), divisionsPerOctave);
        score.setPitchClassSet(operation.begin,
                               operation.end,
                               pcs,
                               divisionsPerOctave);
      }
    } else {
#ifdef MSVC
        if (!(operation.V == DBL_MAX)) {
#else
      if (!std::isnan(operation.V)) {
#endif
        std::vector<double> ptv = score.getPTV(operation.begin,
                                               operation.end,
                                               base,
                                               range,
                                               divisionsPerOctave);
        score.setPTV(operation.begin,
                     operation.end,
                     ptv[0],
                     ptv[1],
                     operation.V,
                     base,
                     range,
                     divisionsPerOctave);
      } else if (operation.L) {
        score.voicelead(priorOperation.begin,
                        priorOperation.end,
                        operation.begin,
                        operation.end,
                        base,
                        range,
                        avoidParallels,
                        divisionsPerOctave);
      }
    }
    System::message("ENDED VoiceleadingNode::apply.\n");
  }

  void VoiceleadingNode::PT(double time, double P, double T)
  {
    operations[time].beginTime = time;
    operations[time].P = P;
    operations[time].T = T;
  }

  void VoiceleadingNode::PTV(double time, double P, double T, double V)
  {
    operations[time].beginTime = time;
    operations[time].P = P;
    operations[time].T = T;
    operations[time].V = V;
  }

  void VoiceleadingNode::PTL(double time, double P, double T, bool avoidParallels)
  {
    operations[time].beginTime = time;
    operations[time].P = P;
    operations[time].T = T;
    operations[time].L = true;
    operations[time].avoidParallels = avoidParallels;
  }

  void VoiceleadingNode::C(double time, double C_)
  {
    operations[time].beginTime = time;
    operations[time].C = C_;
  }

  void VoiceleadingNode::C(double time, std::string C_)
  {
    C(time, Voicelead::nameToC(C_, divisionsPerOctave));
  }

  void VoiceleadingNode::CV(double time, double C, double V)
  {
    operations[time].beginTime = time;
    operations[time].C = C;
    operations[time].V = V;
  }

  void VoiceleadingNode::CV(double time, std::string C, double V)
  {
    CV(time, Voicelead::nameToC(C, divisionsPerOctave), V);
  }

  void VoiceleadingNode::CL(double time, double C, bool avoidParallels)
  {
    operations[time].beginTime = time;
    operations[time].C = C;
    operations[time].L = true;
    operations[time].avoidParallels = avoidParallels;
  }

  void VoiceleadingNode::CL(double time, std::string C, bool avoidParallels)
  {
    CL(time, Voicelead::nameToC(C, divisionsPerOctave), avoidParallels);
  }

  void VoiceleadingNode::V(double time, double V_)
  {
    operations[time].beginTime = time;
    operations[time].V = V_;
  }

  void VoiceleadingNode::L(double time, bool avoidParallels)
  {
    operations[time].beginTime = time;
    operations[time].L = true;
    operations[time].avoidParallels = avoidParallels;
  }

00316   void VoiceleadingNode::produceOrTransform(Score &score, size_t beginAt, size_t endAt, const ublas::matrix<double> &coordinates)
  {
    transform(score, rescaleTimes);
  }

00321   void VoiceleadingNode::transform(Score &score, bool rescaleTimes_)
  {
    if (operations.empty()) {
      return;
    }
    // Find the time rescale factor.
    score.sort();
    score.findScale();
    double origin = score.scaleActualMinima.getTime();
    double duration = score.getDuration();
    double scoreMaxTime = origin + duration;
    double operationMaxTime = 0.0;
    double timeScale = 1.0;
    std::vector<VoiceleadingOperation *> ops;
    for (std::map<double, VoiceleadingOperation>::iterator it = operations.begin(); it != operations.end(); ++it) {
      if (it->second.beginTime > operationMaxTime) {
        operationMaxTime = it->second.beginTime;
      }
      ops.push_back(&it->second);
    }
    if (rescaleTimes_) {
      if (operationMaxTime > 0.0) {
        timeScale = duration / operationMaxTime;
      }
    }
    System::inform("BEGAN VoiceleadingNode::produceOrTransform  operationMaxTime: %f  origin: %f  duration: %f  scoreMaxTime: %f  timeScale: %f...\n",
                   operationMaxTime,
                   origin,
                   duration,
                   scoreMaxTime,
                   timeScale);
    VoiceleadingOperation *priorOperation = 0;
    VoiceleadingOperation *currentOperation = 0;
    VoiceleadingOperation *nextOperation = 0;
    for (int priorIndex = -1, currentIndex = 0, nextIndex = 1, firstIndex = 0, endIndex = ops.size(), backIndex = ops.size() - 1;
         currentIndex < endIndex;
         priorIndex++, currentIndex++, nextIndex++) {
      if (currentIndex <= firstIndex) {
        priorOperation = ops[currentIndex];
        currentOperation = ops[currentIndex];
      } else {
        priorOperation = ops[priorIndex];
        currentOperation = ops[currentIndex];
      }
      currentOperation->rescaledBeginTime = ((currentOperation->beginTime - origin) * timeScale) + origin;
      currentOperation->begin = score.indexAtTime(currentOperation->rescaledBeginTime);
      if (currentIndex >= backIndex) {
        currentOperation->endTime = std::max(currentOperation->rescaledBeginTime, scoreMaxTime);
        currentOperation->rescaledEndTime = currentOperation->endTime;
        currentOperation->end = score.size();
      } else {
        nextOperation = ops[nextIndex];
        currentOperation->endTime = nextOperation->beginTime;
        currentOperation->rescaledEndTime = currentOperation->endTime * timeScale;
        currentOperation->end = score.indexAfterTime(currentOperation->rescaledEndTime);
      }
      apply(score, *priorOperation, *currentOperation);
    }
    System::inform("ENDED VoiceleadingNode::produceOrTransform.\n");
  }

}

Generated by  Doxygen 1.6.0   Back to index