Package de.maramuse.soundcomp.parser

Source Code of de.maramuse.soundcomp.parser.Bpm

/*
* Copyright 2010 Jan Schmidt-Reinisch
*
* SoundComp - a sound processing library
*
* This library 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; in version 2.1
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**
* This parser symbol represents a tempo change annotation
*/
package de.maramuse.soundcomp.parser;

import de.maramuse.soundcomp.events.AbruptTempoChangeEvent;
import de.maramuse.soundcomp.events.ExponentialTempoChangeEvent;
import de.maramuse.soundcomp.events.HarmonicTempoChangeEvent;
import de.maramuse.soundcomp.events.InverseTempoChangeEvent;
import de.maramuse.soundcomp.events.LinearTempoChangeEvent;
import de.maramuse.soundcomp.events.ReturnToGlobalTiming;
import de.maramuse.soundcomp.events.SeamlessTempoChangeEvent;
import de.maramuse.soundcomp.events.TempoChangeEvent;

public class Bpm extends TimingEvent {
  public static final int ACCELMODE_EXPONENTIAL=0;
  public static final int ACCELMODE_HARMONIC=1;
  public static final int ACCELMODE_INVERSE=2;
  public static final int ACCELMODE_SEAMLESS=3;
  public static final int ACCELMODE_ABRUPT=4;
  public static final int ACCELMODE_RETURN=5;
  public static final int ACCELMODE_LINEAR=6;

  double startSpeed=Double.NaN, endSpeed=Double.NaN;
  boolean voicelocal=false;
  boolean sweep=true;
  double duration=Double.NaN;
  double delay=Double.NaN;
  private int accelMode=ACCELMODE_ABRUPT;

  public Bpm(String s) {
  super(SCParser.BPM, s);
  }
 
  public Bpm assignParams(SCParser.ParserVal list){
  if(list.inner.size()==0)
    throw new IllegalArgumentException("missing parameters for tempo change in "+getLocationText());
  for(SCParser.ParserVal val: list.inner){
    assignParam(val);
  }
  // now check for useful combinations
  if(accelMode==Bpm.ACCELMODE_ABRUPT){
    if(!Double.isNaN(startSpeed)&&!Double.isNaN(endSpeed)&&startSpeed!=endSpeed){
    throw new IllegalArgumentException("start and end tempo cannot be different on abrupt tempo change in "+getLocationText());
    }
    if(Double.isNaN(startSpeed))startSpeed=endSpeed;
    if(Double.isNaN(endSpeed))endSpeed=startSpeed;
  }
  // we need an end tempo, unless we have a "return to global tempo" command
  if(Double.isNaN(endSpeed)&&(accelMode!=Bpm.ACCELMODE_ABRUPT||!voicelocal))
    throw new IllegalArgumentException("end tempo must be given for tempo change on "+getLocationText());
  // later on we need a valid delay - if it is not given, take the default zero.
  if(Double.isNaN(delay))
    delay=0D;
  return this;
  }

  private void assignParam(SCParser.ParserVal val){
  SCParser.ParserVal dval=null;
  if(val.inner.size()>0)dval=val.get(0);
  switch(val.getType()){
    case SCParser.STARTBPM:
    if(dval==null)
      throw new IllegalArgumentException("start tempo is not set in "+getLocationText());
    if(!dval.isConstant())
      throw new IllegalArgumentException("start tempo is not constant in "+dval.getLocationText());
    if(!Double.isNaN(startSpeed))
      throw new IllegalArgumentException("duplicate start tempo given in "+dval.getLocationText());
    setStartSpeed(dval.asDouble());
    return;
    case SCParser.END:
    if(dval==null)
      throw new IllegalArgumentException("end tempo is not set in "+getLocationText());
    if(!dval.isConstant())
      throw new IllegalArgumentException("end tempo is not constant in "+dval.getLocationText());
    if(!Double.isNaN(endSpeed))
      throw new IllegalArgumentException("duplicate end tempo given in "+dval.getLocationText());
    setEndSpeed(dval.asDouble());
    return;
    case SCParser.DURATION:
    if(dval==null)
      throw new IllegalArgumentException("tempo change duration is not set in "+getLocationText());
    if(!dval.isConstant())
      throw new IllegalArgumentException("tempo change duration is not constant in "+dval.getLocationText());
    if(!Double.isNaN(duration))
      throw new IllegalArgumentException("duplicate tempo change duration given in "+dval.getLocationText());
    setDuration(dval.asDouble());
    return;
    case SCParser.VOICE:
    setVoicelocal(true);
    return;
    case SCParser.DELAY:
    if(dval==null)
      throw new IllegalArgumentException("delay is not set in "+getLocationText());
    if(!dval.isConstant())
      throw new IllegalArgumentException("delay is not constant in "+dval.getLocationText());
    if(!Double.isNaN(delay))
      throw new IllegalArgumentException("duplicate delay given in "+dval.getLocationText());
    delay=dval.asDouble();
    return;
    case SCParser.MEXP:
    case SCParser.HARMONIC:
    case SCParser.INVERSE:
    case SCParser.SEAMLESS:
    case SCParser.LINEAR:
    if(accelMode!=Bpm.ACCELMODE_ABRUPT)
      throw new IllegalArgumentException("duplicate tempo change mode given for tempo change on "+getLocationText());
    setAccelMode(((AccelMode)val).getAccelMode());
    return;
  }
  }
  /**
   * set the new startSpeed
   *
   * @param startSpeed
   *          the new startSpeed
   * @return this
   */
  public Bpm setStartSpeed(double startSpeed) {
  this.startSpeed=startSpeed;
  return this;
  }

  /**
   * Returns the set startSpeed
   *
   * @return the set startSpeed
   */
  public double getStartSpeed() {
  return startSpeed;
  }

  /**
   * set the new startSpeed
   *
   * @param startSpeed
   *          the new startSpeed
   * @return this
   */
  public Bpm setEndSpeed(double endSpeed) {
  this.endSpeed=endSpeed;
  return this;
  }

  /**
   * Returns the set startSpeed
   *
   * @return the set startSpeed
   */
  public double getEndSpeed() {
  return endSpeed;
  }

  /**
   * set the voicelocal flag, indicating that the tempo change is valid for the containing voice only (otherwise global
   * for all voices that don't have a local tempo set)
   *
   * @param voicelocal
   *          the new voicelocal flag
   * @return this
   */
  Bpm setVoicelocal(boolean voicelocal) {
  this.voicelocal=voicelocal;
  return this;
  }

  /**
   * Returns the voicelocal flag, indicating that the tempo change is valid for the containing voice only (@see
   * Bpm.setVoicelocal(boolean voicelocal))
   *
   * @return the voicelocal flag
   */
  @Override
  public boolean isVoicelocal() {
  return voicelocal;
  }

  /**
   * Returns the sweep flag, =true if this change is not abrupt
   *
   * @return the sweep flag, =true if this change is not abrupt
   */
  public boolean isSweep() {
  return sweep;
  }

  /**
   * Returns the duration of the tempo change, in whole beats
   *
   * @return the duration of the tempo change, in whole beats
   */
  public double getDuration() {
  return duration;
  }
 
  /**
   * Returns the delay of the tempo change, in whole beats
   *
   * @return the delay of the tempo change, in whole beats
   */
  public double getDelay() {
  return delay;
  }
 
 

  /**
   * Sets the duration of the tempo change, in whole beats
   *
   * @param duration
   *          the duration of the tempo change, in whole beats
   */
  public Bpm setDuration(double duration) {
  this.duration=duration;
  sweep=(duration>0&&!Double.isNaN(duration));
  return this;
  }

  public Bpm setAccelMode(int accelMode){
  switch(accelMode){
    case ACCELMODE_ABRUPT:
    case ACCELMODE_LINEAR:
    case ACCELMODE_EXPONENTIAL:
    case ACCELMODE_HARMONIC:
    case ACCELMODE_INVERSE:
    case ACCELMODE_SEAMLESS:
    case ACCELMODE_RETURN:
    this.accelMode=accelMode;
    return this;
    default: throw new IllegalArgumentException("Unknown tempo acceleration mode "+accelMode);
  }
  }
 
  @Override
  public de.maramuse.soundcomp.events.TempoChangeEvent toTempoEvent() {
  TempoChangeEvent tce=null;
  switch(accelMode){
    case ACCELMODE_ABRUPT:
    tce=new AbruptTempoChangeEvent(tempTimestamp);
    break;
    case ACCELMODE_EXPONENTIAL:
    tce=new ExponentialTempoChangeEvent(tempTimestamp);
    break;
    case ACCELMODE_HARMONIC:
    tce=new HarmonicTempoChangeEvent(tempTimestamp);
    break;
    case ACCELMODE_INVERSE:
    tce=new InverseTempoChangeEvent(tempTimestamp);
    break;
    case ACCELMODE_SEAMLESS:
    tce=new SeamlessTempoChangeEvent(tempTimestamp);
    break;
    case ACCELMODE_RETURN:
    tce=new ReturnToGlobalTiming(tempTimestamp);
    break;
    case ACCELMODE_LINEAR:
    tce=new LinearTempoChangeEvent(tempTimestamp);
    break;
    default:
    return null;
  }
  tce.setEndBpm(endSpeed);
  tce.setStartBpm(startSpeed);
  tce.setBeats(duration);
  tce.setVoicelocal(voicelocal);
  tce.init();
  // tce.setBeat(beat); since this potentially is to be used in another voice,
  // there might be a beat offset necessary. We do not have the necessary info here.
  // if necessary, calculate it in the relevant voice where the previous tempo change,
  // timestamp and beat is known.
  tce.setBeat(Double.NaN);
  return tce;
  }
}
TOP

Related Classes of de.maramuse.soundcomp.parser.Bpm

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.