/* Copyright (C) 2000 Jeff Tranter tranter@pobox.com (C) 1999 Stefan Westerfeld stefan@space.twc.de This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "artsmodulessynth.h" #include "stdsynthmodule.h" using namespace Arts; class Synth_PITCH_SHIFT_impl : virtual public Synth_PITCH_SHIFT_skel, virtual public StdSynthModule { protected: float _speed, _frequency; enum { MAXDELAY = 44100 }; float *dbuffer; float lfopos, b1pos, b2pos, b1inc, b2inc; bool b1reset, b2reset, initialized; int dbpos; public: Synth_PITCH_SHIFT_impl() : _speed(1.0), _frequency(5.0) { } float speed() { return _speed; } void speed(float newSpeed) { _speed = newSpeed; } float frequency() { return _frequency; } void frequency(float newFrequency) { _frequency = newFrequency; } void streamInit() { dbuffer = new float[MAXDELAY]; for (dbpos=0; dbpos 1.0 (uppitching) * * start with a sample from long ago and slowly decrease delay */ if (!b1reset && lfopos > 0.25) { if (_speed <= 1.0) { b1pos = 0; b1inc = 1 - _speed; } else { b1inc = 1 - _speed; b1pos = 10 + ((-b1inc) * (1 / lfoposinc)); /* 10+ are not strictly necessary */ } b1reset = true; } if (!b2reset && lfopos > 0.75) { if (_speed <= 1.0) { b2pos = 0; b2inc = 1 - _speed; } else{ b2inc = 1 - _speed; b2pos = 10 + ((-b2inc) * (1/lfoposinc)); /* 10+ are not strictly necessary */ } b2reset = true; } b1pos += b1inc; b2pos += b2inc; int position, position1; double error,int_pos; /* * Interpolate value from buffer position 1 */ error = modf(b1pos, &int_pos); position = dbpos - (int)int_pos; if (position < 0) position += MAXDELAY; position1 = position - 1; if (position1 < 0) position1 += MAXDELAY; b1value = dbuffer[position] * (1 - error) + dbuffer[position1] * error; /* * Interpolate value from buffer position 2 */ error = modf(b2pos,&int_pos); position = dbpos - (int)int_pos; if (position < 0) position += MAXDELAY; position1 = position-1; if ( position1 < 0) position1 += MAXDELAY; b2value = dbuffer[position]*(1-error) + dbuffer[position1]*error; /* * Calculate output signal from these two buffers */ lfo = (sin(pi2 * lfopos) + 1) / 2; /* position sin lfo variable *------------------------------------------------------------------ * lfo value: 0.25 1 1 => buffer 2 is used * 0.75 -1 0 => buffer 1 is used */ *outvalue++ = b1value * (1.0 - lfo) + b2value * lfo; /* * increment delay buffer position */ dbpos++; if (dbpos == MAXDELAY) dbpos = 0; } } }; REGISTER_IMPLEMENTATION(Synth_PITCH_SHIFT_impl);