Version 4.4.3

This commit is contained in:
Gary Scavone
2013-09-29 23:21:29 +02:00
committed by Stephen Sinclair
parent baca57040b
commit 0aec39260a
223 changed files with 26190 additions and 11130 deletions

View File

@@ -2,12 +2,14 @@
/*! \class ADSR
\brief STK ADSR envelope class.
This class implements a traditional ADSR (Attack, Decay, Sustain,
This class implements a traditional ADSR (Attack, Decay, Sustain,
Release) envelope. It responds to simple keyOn and keyOff
messages, keeping track of its state. The \e state = ADSR::DONE
after the envelope value reaches 0.0 in the ADSR::RELEASE state.
messages, keeping track of its state. The \e state = ADSR::IDLE
before being triggered and after the envelope value reaches 0.0 in
the ADSR::RELEASE state. All rate, target and level settings must
be non-negative. All time settings must be positive.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -22,8 +24,9 @@ ADSR :: ADSR( void )
attackRate_ = 0.001;
decayRate_ = 0.001;
releaseRate_ = 0.005;
releaseTime_ = -1.0;
sustainLevel_ = 0.5;
state_ = ATTACK;
state_ = IDLE;
Stk::addSampleRateAlert( this );
}
@@ -42,7 +45,7 @@ void ADSR :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
void ADSR :: keyOn()
{
target_ = 1.0;
if ( target_ <= 0.0 ) target_ = 1.0;
state_ = ATTACK;
}
@@ -50,76 +53,97 @@ void ADSR :: keyOff()
{
target_ = 0.0;
state_ = RELEASE;
// FIXED October 2010 - Nick Donaldson
// Need to make release rate relative to current value!!
// Only update if we have set a TIME rather than a RATE,
// in which case releaseTime_ will be -1
if ( releaseTime_ > 0.0 )
releaseRate_ = value_ / ( releaseTime_ * Stk::sampleRate() );
}
void ADSR :: setAttackRate( StkFloat rate )
{
if ( rate < 0.0 ) {
errorString_ << "ADSR::setAttackRate: negative rates not allowed ... correcting!";
handleError( StkError::WARNING );
attackRate_ = -rate;
oStream_ << "ADSR::setAttackRate: argument must be >= 0.0!";
handleError( StkError::WARNING ); return;
}
else attackRate_ = rate;
attackRate_ = rate;
}
void ADSR :: setAttackTarget( StkFloat target )
{
if ( target < 0.0 ) {
oStream_ << "ADSR::setAttackTarget: negative target not allowed!";
handleError( StkError::WARNING ); return;
}
target_ = target;
}
void ADSR :: setDecayRate( StkFloat rate )
{
if ( rate < 0.0 ) {
errorString_ << "ADSR::setDecayRate: negative rates not allowed ... correcting!";
handleError( StkError::WARNING );
decayRate_ = -rate;
oStream_ << "ADSR::setDecayRate: negative rates not allowed!";
handleError( StkError::WARNING ); return;
}
else decayRate_ = rate;
decayRate_ = rate;
}
void ADSR :: setSustainLevel( StkFloat level )
{
if ( level < 0.0 ) {
errorString_ << "ADSR::setSustainLevel: level out of range ... correcting!";
handleError( StkError::WARNING );
sustainLevel_ = 0.0;
oStream_ << "ADSR::setSustainLevel: negative level not allowed!";
handleError( StkError::WARNING ); return;
}
else sustainLevel_ = level;
sustainLevel_ = level;
}
void ADSR :: setReleaseRate( StkFloat rate )
{
if ( rate < 0.0 ) {
errorString_ << "ADSR::setReleaseRate: negative rates not allowed ... correcting!";
handleError( StkError::WARNING );
releaseRate_ = -rate;
oStream_ << "ADSR::setReleaseRate: negative rates not allowed!";
handleError( StkError::WARNING ); return;
}
else releaseRate_ = rate;
releaseRate_ = rate;
// Set to negative value so we don't update the release rate on keyOff()
releaseTime_ = -1.0;
}
void ADSR :: setAttackTime( StkFloat time )
{
if ( time < 0.0 ) {
errorString_ << "ADSR::setAttackTime: negative times not allowed ... correcting!";
handleError( StkError::WARNING );
attackRate_ = 1.0 / ( -time * Stk::sampleRate() );
if ( time <= 0.0 ) {
oStream_ << "ADSR::setAttackTime: negative or zero times not allowed!";
handleError( StkError::WARNING ); return;
}
else attackRate_ = 1.0 / ( time * Stk::sampleRate() );
attackRate_ = 1.0 / ( time * Stk::sampleRate() );
}
void ADSR :: setDecayTime( StkFloat time )
{
if ( time < 0.0 ) {
errorString_ << "ADSR::setDecayTime: negative times not allowed ... correcting!";
handleError( StkError::WARNING );
decayRate_ = 1.0 / ( -time * Stk::sampleRate() );
if ( time <= 0.0 ) {
oStream_ << "ADSR::setDecayTime: negative or zero times not allowed!";
handleError( StkError::WARNING ); return;
}
else decayRate_ = 1.0 / ( time * Stk::sampleRate() );
decayRate_ = (1.0 - sustainLevel_) / ( time * Stk::sampleRate() );
}
void ADSR :: setReleaseTime( StkFloat time )
{
if ( time < 0.0 ) {
errorString_ << "ADSR::setReleaseTime: negative times not allowed ... correcting!";
handleError( StkError::WARNING );
releaseRate_ = sustainLevel_ / ( -time * Stk::sampleRate() );
if ( time <= 0.0 ) {
oStream_ << "ADSR::setReleaseTime: negative or zero times not allowed!";
handleError( StkError::WARNING ); return;
}
else releaseRate_ = sustainLevel_ / ( time * Stk::sampleRate() );
releaseRate_ = sustainLevel_ / ( time * Stk::sampleRate() );
releaseTime_ = time;
}
void ADSR :: setAllTimes( StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime )
@@ -132,15 +156,16 @@ void ADSR :: setAllTimes( StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFl
void ADSR :: setTarget( StkFloat target )
{
if ( target < 0.0 ) {
oStream_ << "ADSR::setTarget: negative target not allowed!";
handleError( StkError::WARNING ); return;
}
target_ = target;
if ( value_ < target_ ) {
state_ = ATTACK;
this->setSustainLevel( target_ );
}
if ( value_ > target_ ) {
this->setSustainLevel( target_ );
state_ = DECAY;
}
this->setSustainLevel( target_ );
if ( value_ < target_ ) state_ = ATTACK;
if ( value_ > target_ ) state_ = DECAY;
}
void ADSR :: setValue( StkFloat value )

View File

@@ -19,7 +19,7 @@
to \e keyOn and \e keyOff messages by ramping to
1.0 on keyOn and to 0.0 on keyOff.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -63,9 +63,8 @@ void Asymp :: keyOff( void )
void Asymp :: setTau( StkFloat tau )
{
if ( tau <= 0.0 ) {
errorString_ << "Asymp::setTau: negative or zero tau not allowed ... ignoring!";
handleError( StkError::WARNING );
return;
oStream_ << "Asymp::setTau: negative or zero tau not allowed!";
handleError( StkError::WARNING ); return;
}
factor_ = std::exp( -1.0 / ( tau * Stk::sampleRate() ) );
@@ -75,9 +74,8 @@ void Asymp :: setTau( StkFloat tau )
void Asymp :: setTime( StkFloat time )
{
if ( time <= 0.0 ) {
errorString_ << "Asymp::setTime: negative or zero times not allowed ... ignoring!";
handleError( StkError::WARNING );
return;
oStream_ << "Asymp::setTime: negative or zero times not allowed!";
handleError( StkError::WARNING ); return;
}
StkFloat tau = -time / std::log( TARGET_THRESHOLD );
@@ -85,6 +83,16 @@ void Asymp :: setTime( StkFloat time )
constant_ = ( 1.0 - factor_ ) * target_;
}
void Asymp :: setT60( StkFloat t60 )
{
if ( t60 <= 0.0 ) {
oStream_ << "Asymp::setT60: negative or zero t60 not allowed!";
handleError( StkError::WARNING ); return;
}
setTau( t60 / 6.91 );
}
void Asymp :: setTarget( StkFloat target )
{
target_ = target;

View File

@@ -40,13 +40,13 @@ BandedWG :: BandedWG( void )
doPluck_ = true;
bowTable_.setSlope( 3.0 );
adsr_.setAllTimes( 0.02, 0.005, 0.9, 0.01);
adsr_.setAllTimes( 0.02, 0.005, 0.9, 0.01 );
frequency_ = 220.0;
this->setPreset(0);
bowPosition_ = 0;
baseGain_ = (StkFloat) 0.999;
baseGain_ = 0.999;
integrationConstant_ = 0.0;
trackVelocity_ = false;
@@ -171,16 +171,17 @@ void BandedWG :: setPreset( int preset )
void BandedWG :: setFrequency( StkFloat frequency )
{
frequency_ = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "BandedWG::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
frequency_ = 220.0;
oStream_ << "BandedWG::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
if (frequency_ > 1568.0) frequency_ = 1568.0;
#endif
if (frequency > 1568.0) frequency = 1568.0;
StkFloat radius;
StkFloat base = Stk::sampleRate() / frequency_;
StkFloat base = Stk::sampleRate() / frequency;
StkFloat length;
for (int i=0; i<presetModes_; i++) {
// Calculate the delay line lengths for each mode.
@@ -200,7 +201,7 @@ void BandedWG :: setFrequency( StkFloat frequency )
// Set the bandpass filter resonances
radius = 1.0 - PI * 32 / Stk::sampleRate(); //frequency_ * modes_[i] / Stk::sampleRate()/32;
if ( radius < 0.0 ) radius = 0.0;
bandpass_[i].setResonance(frequency_ * modes_[i], radius, true);
bandpass_[i].setResonance(frequency * modes_[i], radius, true);
delay_[i].clear();
bandpass_[i].clear();
@@ -241,28 +242,18 @@ void BandedWG :: pluck( StkFloat amplitude )
void BandedWG :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency(frequency);
this->setFrequency( frequency );
if ( doPluck_ )
this->pluck(amplitude);
this->pluck( amplitude );
else
this->startBowing(amplitude, amplitude * 0.001);
#if defined(_STK_DEBUG_)
errorString_ << "BandedWG::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
this->startBowing( amplitude, amplitude * 0.001 );
}
void BandedWG :: noteOff( StkFloat amplitude )
{
if ( !doPluck_ )
this->stopBowing((1.0 - amplitude) * 0.005);
#if defined(_STK_DEBUG_)
errorString_ << "BandedWG::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
this->stopBowing( (1.0 - amplitude) * 0.005 );
}
StkFloat BandedWG :: tick( unsigned int )
@@ -311,51 +302,47 @@ StkFloat BandedWG :: tick( unsigned int )
void BandedWG :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "BandedWG::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "BandedWG::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
#if defined(_STK_DEBUG_)
if ( value < 0 || ( number != 101 && value > 128.0 ) ) {
oStream_ << "BandedWG::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_BowPressure_) { // 2
if ( norm == 0.0 )
if ( normalizedValue == 0.0 )
doPluck_ = true;
else {
doPluck_ = false;
bowTable_.setSlope( 10.0 - (9.0 * norm));
bowTable_.setSlope( 10.0 - (9.0 * normalizedValue));
}
}
else if (number == 4) { // 4
if ( !trackVelocity_ ) trackVelocity_ = true;
bowTarget_ += 0.005 * (norm - bowPosition_);
bowPosition_ = norm;
bowTarget_ += 0.005 * (normalizedValue - bowPosition_);
bowPosition_ = normalizedValue;
//adsr_.setTarget(bowPosition_);
}
else if (number == 8) // 8
this->setStrikePosition( norm );
this->setStrikePosition( normalizedValue );
else if (number == __SK_AfterTouch_Cont_) { // 128
//bowTarget_ += 0.02 * (norm - bowPosition_);
//bowPosition_ = norm;
//bowTarget_ += 0.02 * (normalizedValue - bowPosition_);
//bowPosition_ = normalizedValue;
if ( trackVelocity_ ) trackVelocity_ = false;
maxVelocity_ = 0.13 * norm;
adsr_.setTarget(norm);
maxVelocity_ = 0.13 * normalizedValue;
adsr_.setTarget(normalizedValue);
}
else if (number == __SK_ModWheel_) { // 1
// baseGain_ = 0.9989999999 + (0.001 * norm );
baseGain_ = 0.8999999999999999 + (0.1 * norm);
// baseGain_ = 0.9989999999 + (0.001 * normalizedValue );
baseGain_ = 0.8999999999999999 + (0.1 * normalizedValue);
// std::cerr << "Yuck!" << std::endl;
for (int i=0; i<nModes_; i++)
gains_[i]=(StkFloat) basegains_[i]*baseGain_;
// gains_[i]=(StkFloat) pow(baseGain_, (int)((StkFloat)delay_[i].getDelay()+i));
}
else if (number == __SK_ModFrequency_) // 11
integrationConstant_ = norm;
integrationConstant_ = normalizedValue;
else if (number == __SK_Sustain_) { // 64
if (value < 65) doPluck_ = true;
else doPluck_ = false;
@@ -365,15 +352,12 @@ void BandedWG :: controlChange( int number, StkFloat value )
else trackVelocity_ = true;
}
else if (number == __SK_ProphesyRibbon_) // 16
this->setPreset((int) value);
this->setPreset((int) value);
#if defined(_STK_DEBUG_)
else {
errorString_ << "BandedWG::controlChange: undefined control number (" << number << ")!";
oStream_ << "BandedWG::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "BandedWG::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -28,7 +28,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -74,11 +74,6 @@ void BeeThree :: noteOn( StkFloat frequency, StkFloat amplitude )
gains_[3] = amplitude * fmGains_[95];
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
errorString_ << "BeeThree::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace

View File

@@ -6,7 +6,7 @@
Methods are provided for creating a resonance or notch in the
frequency response while maintaining a constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -46,13 +46,24 @@ void BiQuad :: setCoefficients( StkFloat b0, StkFloat b1, StkFloat b2, StkFloat
void BiQuad :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
{
if ( !ignoreSampleRateChange_ ) {
errorString_ << "BiQuad::sampleRateChanged: you may need to recompute filter coefficients!";
oStream_ << "BiQuad::sampleRateChanged: you may need to recompute filter coefficients!";
handleError( StkError::WARNING );
}
}
void BiQuad :: setResonance(StkFloat frequency, StkFloat radius, bool normalize)
void BiQuad :: setResonance( StkFloat frequency, StkFloat radius, bool normalize )
{
#if defined(_STK_DEBUG_)
if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) {
oStream_ << "BiQuad::setResonance: frequency argument (" << frequency << ") is out of range!";
handleError( StkError::WARNING ); return;
}
if ( radius < 0.0 || radius >= 1.0 ) {
oStream_ << "BiQuad::setResonance: radius argument (" << radius << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
a_[2] = radius * radius;
a_[1] = -2.0 * radius * cos( TWO_PI * frequency / Stk::sampleRate() );
@@ -64,14 +75,25 @@ void BiQuad :: setResonance(StkFloat frequency, StkFloat radius, bool normalize)
}
}
void BiQuad :: setNotch(StkFloat frequency, StkFloat radius)
void BiQuad :: setNotch( StkFloat frequency, StkFloat radius )
{
#if defined(_STK_DEBUG_)
if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) {
oStream_ << "BiQuad::setNotch: frequency argument (" << frequency << ") is out of range!";
handleError( StkError::WARNING ); return;
}
if ( radius < 0.0 ) {
oStream_ << "BiQuad::setNotch: radius argument (" << radius << ") is negative!";
handleError( StkError::WARNING ); return;
}
#endif
// This method does not attempt to normalize the filter gain.
b_[2] = radius * radius;
b_[1] = (StkFloat) -2.0 * radius * cos( TWO_PI * (double) frequency / Stk::sampleRate() );
}
void BiQuad :: setEqualGainZeroes()
void BiQuad :: setEqualGainZeroes( void )
{
b_[0] = 1.0;
b_[1] = 0.0;

View File

@@ -27,6 +27,11 @@ namespace stk {
Blit:: Blit( StkFloat frequency )
{
if ( frequency <= 0.0 ) {
oStream_ << "Blit::Blit: argument (" << frequency << ") must be positive!";
handleError( StkError::FUNCTION_ARGUMENT );
}
nHarmonics_ = 0;
this->setFrequency( frequency );
this->reset();
@@ -44,10 +49,10 @@ void Blit :: reset()
void Blit :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
errorString_ << "Blit::setFrequency: frequency = " << frequency << '.';
handleError( StkError::DEBUG_WARNING );
#endif
if ( frequency <= 0.0 ) {
oStream_ << "Blit::setFrequency: argument (" << frequency << ") must be positive!";
handleError( StkError::WARNING ); return;
}
p_ = Stk::sampleRate() / frequency;
rate_ = PI / p_;
@@ -68,11 +73,6 @@ void Blit :: updateHarmonics( void )
}
else
m_ = 2 * nHarmonics_ + 1;
#if defined(_STK_DEBUG_)
errorString_ << "Blit::updateHarmonics: nHarmonics_ = " << nHarmonics_ << ", m_ = " << m_ << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace

View File

@@ -25,6 +25,11 @@ namespace stk {
BlitSaw:: BlitSaw( StkFloat frequency )
{
if ( frequency <= 0.0 ) {
oStream_ << "BlitSaw::BlitSaw: argument (" << frequency << ") must be positive!";
handleError( StkError::FUNCTION_ARGUMENT );
}
nHarmonics_ = 0;
this->reset();
this->setFrequency( frequency );
@@ -43,10 +48,10 @@ void BlitSaw :: reset()
void BlitSaw :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
errorString_ << "BlitSaw::setFrequency: frequency = " << frequency << '.';
handleError( StkError::DEBUG_WARNING );
#endif
if ( frequency <= 0.0 ) {
oStream_ << "BlitSaw::setFrequency: argument (" << frequency << ") must be positive!";
handleError( StkError::WARNING ); return;
}
p_ = Stk::sampleRate() / frequency;
C2_ = 1 / p_;
@@ -81,11 +86,6 @@ void BlitSaw :: updateHarmonics( void )
m_ = 2 * nHarmonics_ + 1;
a_ = m_ / p_;
#if defined(_STK_DEBUG_)
errorString_ << "BlitSaw::updateHarmonics: nHarmonics_ = " << nHarmonics_ << ", m_ = " << m_ << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace

View File

@@ -36,6 +36,11 @@ namespace stk {
BlitSquare:: BlitSquare( StkFloat frequency )
{
if ( frequency <= 0.0 ) {
oStream_ << "BlitSquare::BlitSquare: argument (" << frequency << ") must be positive!";
handleError( StkError::FUNCTION_ARGUMENT );
}
nHarmonics_ = 0;
this->setFrequency( frequency );
this->reset();
@@ -55,10 +60,10 @@ void BlitSquare :: reset()
void BlitSquare :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
errorString_ << "BlitSquare::setFrequency: frequency = " << frequency << '.';
handleError( StkError::DEBUG_WARNING );
#endif
if ( frequency <= 0.0 ) {
oStream_ << "BlitSquare::setFrequency: argument (" << frequency << ") must be positive!";
handleError( StkError::WARNING ); return;
}
// By using an even value of the parameter M, we get a bipolar blit
// waveform at half the blit frequency. Thus, we need to scale the
@@ -85,11 +90,6 @@ void BlitSquare :: updateHarmonics( void )
m_ = 2 * (nHarmonics_ + 1);
a_ = m_ / p_;
#if defined(_STK_DEBUG_)
errorString_ << "BlitSquare::updateHarmonics: nHarmonics_ = " << nHarmonics_ << ", m_ = " << m_ << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace

View File

@@ -12,7 +12,7 @@
- Vibrato Gain = 1
- Volume = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -30,11 +30,11 @@ BlowBotl :: BlowBotl( void )
vibrato_.setFrequency( 5.925 );
vibratoGain_ = 0.0;
resonator_.setResonance(500.0, __BOTTLE_RADIUS_, true);
adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010);
resonator_.setResonance( 500.0, __BOTTLE_RADIUS_, true );
adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010 );
noiseGain_ = 20.0;
maxPressure_ = (StkFloat) 0.0;
maxPressure_ = 0.0;
}
BlowBotl :: ~BlowBotl( void )
@@ -48,81 +48,74 @@ void BlowBotl :: clear( void )
void BlowBotl :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "BlowBotl::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
oStream_ << "BlowBotl::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
resonator_.setResonance( freakency, __BOTTLE_RADIUS_, true );
resonator_.setResonance( frequency, __BOTTLE_RADIUS_, true );
}
void BlowBotl :: startBlowing( StkFloat amplitude, StkFloat rate )
{
adsr_.setAttackRate(rate);
if ( amplitude <= 0.0 || rate <= 0.0 ) {
oStream_ << "BlowBotl::startBowing: one or more arguments is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
adsr_.setAttackRate( rate );
maxPressure_ = amplitude;
adsr_.keyOn();
}
void BlowBotl :: stopBlowing( StkFloat rate )
{
adsr_.setReleaseRate(rate);
if ( rate <= 0.0 ) {
oStream_ << "BlowBotl::stopBowing: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
adsr_.setReleaseRate( rate );
adsr_.keyOff();
}
void BlowBotl :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency(frequency);
this->setFrequency( frequency );
startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02);
outputGain_ = amplitude + 0.001;
#if defined(_STK_DEBUG_)
errorString_ << "BlowBotl::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void BlowBotl :: noteOff( StkFloat amplitude )
{
this->stopBlowing(amplitude * 0.02);
#if defined(_STK_DEBUG_)
errorString_ << "BlowBotl::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
this->stopBlowing( amplitude * 0.02 );
}
void BlowBotl :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "BlowBotl::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "BlowBotl::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_NoiseLevel_) // 4
noiseGain_ = norm * 30.0;
else if (number == __SK_ModFrequency_) // 11
vibrato_.setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = norm * 0.4;
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( norm );
else {
errorString_ << "BlowBotl::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "BlowBotl::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
if ( value < 0 || ( number != 101 && value > 128.0 ) ) {
oStream_ << "BlowBotl::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_NoiseLevel_) // 4
noiseGain_ = normalizedValue * 30.0;
else if (number == __SK_ModFrequency_) // 11
vibrato_.setFrequency( normalizedValue * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = normalizedValue * 0.4;
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( normalizedValue );
#if defined(_STK_DEBUG_)
else {
oStream_ << "BlowBotl::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -29,7 +29,7 @@
- Register State = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -41,12 +41,17 @@ namespace stk {
BlowHole :: BlowHole( StkFloat lowestFrequency )
{
length_ = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
if ( lowestFrequency <= 0.0 ) {
oStream_ << "BlowHole::BlowHole: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned long nDelays = (unsigned long) ( 0.5 * Stk::sampleRate() / lowestFrequency );
// delays[0] is the delay line between the reed and the register vent.
delays_[0].setDelay( 5.0 * Stk::sampleRate() / 22050.0 );
// delays[1] is the delay line between the register vent and the tonehole.
delays_[1].setMaximumDelay( length_ );
delays_[1].setDelay( length_ >> 1 );
delays_[1].setMaximumDelay( nDelays + 1 );
// delays[2] is the delay line between the tonehole and the end of the bore.
delays_[2].setDelay( 4.0 * Stk::sampleRate() / 22050.0 );
@@ -61,9 +66,9 @@ BlowHole :: BlowHole( StkFloat lowestFrequency )
// Calculate tonehole coefficients and set for initially open.
StkFloat te = 1.4 * rth; // effective length of the open hole
thCoeff_ = (te*2*Stk::sampleRate() - 347.23) / (te*2*Stk::sampleRate() + 347.23);
tonehole_.setA1(-thCoeff_);
tonehole_.setB0(thCoeff_);
tonehole_.setB1(-1.0);
tonehole_.setA1( -thCoeff_ );
tonehole_.setB0( thCoeff_ );
tonehole_.setB1( -1.0 );
// Calculate register hole filter coefficients
double r_rh = 0.0015; // register vent radius
@@ -74,15 +79,18 @@ BlowHole :: BlowHole( StkFloat lowestFrequency )
StkFloat rhCoeff = (zeta - 2 * Stk::sampleRate() * psi) / (zeta + 2 * Stk::sampleRate() * psi);
rhGain_ = -347.23 / (zeta + 2 * Stk::sampleRate() * psi);
vent_.setA1( rhCoeff );
vent_.setB0(1.0);
vent_.setB1(1.0);
vent_.setB0( 1.0 );
vent_.setB1( 1.0 );
// Start with register vent closed
vent_.setGain(0.0);
vent_.setGain( 0.0 );
vibrato_.setFrequency((StkFloat) 5.735);
outputGain_ = 1.0;
noiseGain_ = 0.2;
vibratoGain_ = 0.01;
this->setFrequency( 220.0 );
this->clear();
}
BlowHole :: ~BlowHole( void )
@@ -101,19 +109,18 @@ void BlowHole :: clear( void )
void BlowHole :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
std::cerr << "BlowHole: setFrequency parameter is less than or equal to zero!" << std::endl;
freakency = 220.0;
oStream_ << "BlowHole::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
// Delay = length - approximate filter delay.
StkFloat delay = (Stk::sampleRate() / freakency) * 0.5 - 3.5;
// Account for approximate filter delays and one sample "lastOut" delay.
StkFloat delay = ( Stk::sampleRate() / frequency ) * 0.5 - 3.5;
delay -= delays_[0].getDelay() + delays_[2].getDelay();
if (delay <= 0.0) delay = 0.3;
else if (delay > length_) delay = length_;
delays_[1].setDelay(delay);
delays_[1].setDelay( delay );
}
void BlowHole :: setVent( StkFloat newValue )
@@ -124,9 +131,9 @@ void BlowHole :: setVent( StkFloat newValue )
StkFloat gain;
if (newValue <= 0.0)
if ( newValue <= 0.0 )
gain = 0.0;
else if (newValue >= 1.0)
else if ( newValue >= 1.0 )
gain = rhGain_;
else
gain = newValue * rhGain_;
@@ -146,7 +153,7 @@ void BlowHole :: setTonehole( StkFloat newValue )
else if ( newValue >= 1.0 )
new_coeff = thCoeff_;
else
new_coeff = (newValue * (thCoeff_ - 0.9995)) + 0.9995;
new_coeff = ( newValue * (thCoeff_ - 0.9995) ) + 0.9995;
tonehole_.setA1( -new_coeff );
tonehole_.setB0( new_coeff );
@@ -154,12 +161,22 @@ void BlowHole :: setTonehole( StkFloat newValue )
void BlowHole :: startBlowing( StkFloat amplitude, StkFloat rate )
{
if ( amplitude <= 0.0 || rate <= 0.0 ) {
oStream_ << "BlowHole::startBlowing: one or more arguments is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
envelope_.setRate( rate );
envelope_.setTarget( amplitude );
}
void BlowHole :: stopBlowing( StkFloat rate )
{
if ( rate <= 0.0 ) {
oStream_ << "BlowHole::stopBlowing: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
envelope_.setRate( rate );
envelope_.setTarget( 0.0 );
}
@@ -169,55 +186,38 @@ void BlowHole :: noteOn( StkFloat frequency, StkFloat amplitude )
this->setFrequency( frequency );
this->startBlowing( 0.55 + (amplitude * 0.30), amplitude * 0.005 );
outputGain_ = amplitude + 0.001;
#if defined(_STK_DEBUG_)
errorString_ << "BlowHole::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void BlowHole :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.01 );
#if defined(_STK_DEBUG_)
errorString_ << "BlowHole::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void BlowHole :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "BlowHole::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "BlowHole::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_ReedStiffness_) // 2
reedTable_.setSlope( -0.44 + (0.26 * norm) );
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = ( norm * 0.4);
else if (number == __SK_ModFrequency_) // 11
this->setTonehole( norm );
else if (number == __SK_ModWheel_) // 1
this->setVent( norm );
else if (number == __SK_AfterTouch_Cont_) // 128
envelope_.setValue( norm );
else {
errorString_ << "BlowHole::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "BlowHole::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "BlowHole::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_ReedStiffness_) // 2
reedTable_.setSlope( -0.44 + (0.26 * normalizedValue) );
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = ( normalizedValue * 0.4);
else if (number == __SK_ModFrequency_) // 11
this->setTonehole( normalizedValue );
else if (number == __SK_ModWheel_) // 1
this->setVent( normalizedValue );
else if (number == __SK_AfterTouch_Cont_) // 128
envelope_.setValue( normalizedValue );
#if defined(_STK_DEBUG_)
else {
oStream_ << "BlowHole::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -15,9 +15,12 @@
- Bow Position = 4
- Vibrato Frequency = 11
- Vibrato Gain = 1
- Bow Velocity = 100
- Frequency = 101
- Volume = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
Contributions by Esteban Maestre, 2011.
*/
/***************************************************/
@@ -28,25 +31,41 @@ namespace stk {
Bowed :: Bowed( StkFloat lowestFrequency )
{
unsigned long length;
length = (long) ( Stk::sampleRate() / lowestFrequency + 1 );
neckDelay_.setMaximumDelay( length );
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Bowed::Bowed: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned long nDelays = (unsigned long) ( Stk::sampleRate() / lowestFrequency );
neckDelay_.setMaximumDelay( nDelays + 1 );
neckDelay_.setDelay( 100.0 );
length >>= 1;
bridgeDelay_.setMaximumDelay( length );
bridgeDelay_.setMaximumDelay( nDelays + 1 );
bridgeDelay_.setDelay( 29.0 );
bowTable_.setSlope(3.0 );
bowTable_.setSlope( 3.0 );
bowTable_.setOffset( 0.001);
bowDown_ = false;
maxVelocity_ = 0.25;
vibrato_.setFrequency( 6.12723 );
vibratoGain_ = 0.0;
stringFilter_.setPole( 0.6 - (0.1 * 22050.0 / Stk::sampleRate()) );
stringFilter_.setPole( 0.75 - (0.2 * 22050.0 / Stk::sampleRate()) );
stringFilter_.setGain( 0.95 );
bodyFilter_.setResonance( 500.0, 0.85, true );
bodyFilter_.setGain( 0.2 );
// Old single body filter
//bodyFilter_.setResonance( 500.0, 0.85, true );
//bodyFilter_.setGain( 0.2 );
// New body filter provided by Esteban Maestre (cascade of second-order sections)
bodyFilters_[0].setCoefficients( 1.0, 1.5667, 0.3133, -0.5509, -0.3925 );
bodyFilters_[1].setCoefficients( 1.0, -1.9537, 0.9542, -1.6357, 0.8697 );
bodyFilters_[2].setCoefficients( 1.0, -1.6683, 0.8852, -1.7674, 0.8735 );
bodyFilters_[3].setCoefficients( 1.0, -1.8585, 0.9653, -1.8498, 0.9516 );
bodyFilters_[4].setCoefficients( 1.0, -1.9299, 0.9621, -1.9354, 0.9590 );
bodyFilters_[5].setCoefficients( 1.0, -1.9800, 0.9888, -1.9867, 0.9923 );
adsr_.setAllTimes( 0.02, 0.005, 0.9, 0.01 );
@@ -54,6 +73,7 @@ Bowed :: Bowed( StkFloat lowestFrequency )
// Necessary to initialize internal variables.
this->setFrequency( 220.0 );
this->clear();
}
Bowed :: ~Bowed( void )
@@ -64,19 +84,21 @@ void Bowed :: clear( void )
{
neckDelay_.clear();
bridgeDelay_.clear();
stringFilter_.clear();
for ( int i=0; i<6; i++ ) bodyFilters_[i].clear();
}
void Bowed :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "Bowed::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
oStream_ << "Bowed::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
// Delay = length - approximate filter delay.
baseDelay_ = Stk::sampleRate() / freakency - 4.0;
baseDelay_ = Stk::sampleRate() / frequency - 4.0;
if ( baseDelay_ <= 0.0 ) baseDelay_ = 0.3;
bridgeDelay_.setDelay( baseDelay_ * betaRatio_ ); // bow to bridge length
neckDelay_.setDelay( baseDelay_ * (1.0 - betaRatio_) ); // bow to nut (finger) length
@@ -84,13 +106,24 @@ void Bowed :: setFrequency( StkFloat frequency )
void Bowed :: startBowing( StkFloat amplitude, StkFloat rate )
{
if ( amplitude <= 0.0 || rate <= 0.0 ) {
oStream_ << "Bowed::startBowing: one or more arguments is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
adsr_.setAttackRate( rate );
adsr_.keyOn();
maxVelocity_ = 0.03 + ( 0.2 * amplitude );
maxVelocity_ = 0.03 + ( 0.2 * amplitude );
bowDown_ = true;
}
void Bowed :: stopBowing( StkFloat rate )
{
if ( rate <= 0.0 ) {
oStream_ << "Bowed::stopBowing: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
adsr_.setReleaseRate( rate );
adsr_.keyOff();
}
@@ -99,63 +132,48 @@ void Bowed :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->startBowing( amplitude, amplitude * 0.001 );
this->setFrequency( frequency );
#if defined(_STK_DEBUG_)
errorString_ << "Bowed::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Bowed :: noteOff( StkFloat amplitude )
{
this->stopBowing( (1.0 - amplitude) * 0.005 );
#if defined(_STK_DEBUG_)
errorString_ << "Bowed::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Bowed :: setVibrato( StkFloat gain )
{
vibratoGain_ = gain;
}
void Bowed :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Bowed::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Bowed::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
#if defined(_STK_DEBUG_)
if ( value < 0 || ( number != 101 && value > 128.0 ) ) {
oStream_ << "Bowed::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
if (number == __SK_BowPressure_) // 2
bowTable_.setSlope( 5.0 - (4.0 * norm) );
else if (number == __SK_BowPosition_) { // 4
betaRatio_ = 0.027236 + (0.2 * norm);
StkFloat normalizedValue = value * ONE_OVER_128;
if ( number == __SK_BowPressure_ ) { // 2
if ( normalizedValue > 0.0 ) bowDown_ = true;
else bowDown_ = false;
bowTable_.setSlope( 5.0 - (4.0 * normalizedValue) );
}
else if ( number == __SK_BowPosition_ ) { // 4
betaRatio_ = normalizedValue;
bridgeDelay_.setDelay( baseDelay_ * betaRatio_ );
neckDelay_.setDelay( baseDelay_ * (1.0 - betaRatio_) );
}
else if (number == __SK_ModFrequency_) // 11
vibrato_.setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = ( norm * 0.4 );
else if ( number == __SK_ModFrequency_ ) // 11
vibrato_.setFrequency( normalizedValue * 12.0 );
else if ( number == __SK_ModWheel_ ) // 1
vibratoGain_ = ( normalizedValue * 0.4 );
else if ( number == 100 ) // 100: set instantaneous bow velocity
adsr_.setTarget( normalizedValue );
else if ( number == 101 ) // 101: set instantaneous value of frequency
this->setFrequency( value );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget(norm);
adsr_.setTarget( normalizedValue );
#if defined(_STK_DEBUG_)
else {
errorString_ << "Bowed::controlChange: undefined control number (" << number << ")!";
oStream_ << "Bowed::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Bowed::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -16,7 +16,7 @@
- Vibrato Gain = 1
- Volume = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -28,22 +28,25 @@ namespace stk {
Brass :: Brass( StkFloat lowestFrequency )
{
length_ = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( 0.5 * length_ );
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Brass::Brass: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned long nDelays = (unsigned long) ( Stk::sampleRate() / lowestFrequency );
delayLine_.setMaximumDelay( nDelays + 1 );
lipFilter_.setGain( 0.03 );
dcBlock_.setBlockZero();
adsr_.setAllTimes( 0.005, 0.001, 1.0, 0.010 );
vibrato_.setFrequency( 6.137 );
vibratoGain_ = 0.0;
this->clear();
maxPressure_ = 0.0;
lipTarget_ = 0.0;
this->clear();
// This is necessary to initialize variables.
this->setFrequency( 220.0 );
}
@@ -61,35 +64,40 @@ void Brass :: clear( void )
void Brass :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "Brass::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
oStream_ << "Brass::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
// Fudge correction for filter delays.
slideTarget_ = (Stk::sampleRate() / freakency * 2.0) + 3.0;
slideTarget_ = ( Stk::sampleRate() / frequency * 2.0 ) + 3.0;
delayLine_.setDelay( slideTarget_ ); // play a harmonic
lipTarget_ = freakency;
lipFilter_.setResonance( freakency, 0.997 );
lipTarget_ = frequency;
lipFilter_.setResonance( frequency, 0.997 );
}
void Brass :: setLip( StkFloat frequency )
{
StkFloat freakency = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "Brass::setLip: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
oStream_ << "Brass::setLip: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
lipFilter_.setResonance( freakency, 0.997 );
lipFilter_.setResonance( frequency, 0.997 );
}
void Brass :: startBlowing( StkFloat amplitude, StkFloat rate )
{
if ( amplitude <= 0.0 || rate <= 0.0 ) {
oStream_ << "Brass::startBlowing: one or more arguments is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
adsr_.setAttackRate( rate );
maxPressure_ = amplitude;
adsr_.keyOn();
@@ -97,6 +105,11 @@ void Brass :: startBlowing( StkFloat amplitude, StkFloat rate )
void Brass :: stopBlowing( StkFloat rate )
{
if ( rate <= 0.0 ) {
oStream_ << "Brass::stopBlowing: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
adsr_.setReleaseRate( rate );
adsr_.keyOff();
}
@@ -105,57 +118,40 @@ void Brass :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
this->startBlowing( amplitude, amplitude * 0.001 );
#if defined(_STK_DEBUG_)
errorString_ << "Brass::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Brass :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.005 );
#if defined(_STK_DEBUG_)
errorString_ << "Brass::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Brass :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Brass::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Brass::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
#if defined(_STK_DEBUG_)
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Brass::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_LipTension_) { // 2
StkFloat temp = lipTarget_ * pow( 4.0, (2.0 * norm) - 1.0 );
this->setLip(temp);
StkFloat temp = lipTarget_ * pow( 4.0, (2.0 * normalizedValue) - 1.0 );
this->setLip( temp );
}
else if (number == __SK_SlideLength_) // 4
delayLine_.setDelay( slideTarget_ * (0.5 + norm) );
delayLine_.setDelay( slideTarget_ * (0.5 + normalizedValue) );
else if (number == __SK_ModFrequency_) // 11
vibrato_.setFrequency( norm * 12.0 );
vibrato_.setFrequency( normalizedValue * 12.0 );
else if (number == __SK_ModWheel_ ) // 1
vibratoGain_ = norm * 0.4;
vibratoGain_ = normalizedValue * 0.4;
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( norm );
adsr_.setTarget( normalizedValue );
#if defined(_STK_DEBUG_)
else {
errorString_ << "Brass::controlChange: undefined control number (" << number << ")!";
oStream_ << "Brass::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Brass::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -5,7 +5,7 @@
This class implements a chorus effect. It takes a monophonic
input signal and produces a stereo output signal.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -37,6 +37,16 @@ void Chorus :: clear( void )
lastFrame_[1] = 0.0;
}
void Chorus :: setModDepth( StkFloat depth )
{
if ( depth < 0.0 || depth > 1.0 ) {
oStream_ << "Chorus::setModDepth(): depth argument must be between 0.0 - 1.0!";
handleError( StkError::WARNING ); return;
}
modDepth_ = depth;
};
void Chorus :: setModFrequency( StkFloat frequency )
{
mods_[0].setFrequency( frequency );

View File

@@ -18,7 +18,7 @@
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -29,16 +29,24 @@ namespace stk {
Clarinet :: Clarinet( StkFloat lowestFrequency )
{
length_ = (long) (Stk::sampleRate() / lowestFrequency + 1);
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( length_ / 2.0 );
reedTable_.setOffset((StkFloat) 0.7);
reedTable_.setSlope((StkFloat) -0.3);
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Clarinet::Clarinet: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
vibrato_.setFrequency((StkFloat) 5.735);
outputGain_ = (StkFloat) 1.0;
noiseGain_ = (StkFloat) 0.2;
vibratoGain_ = (StkFloat) 0.1;
unsigned long nDelays = (unsigned long) ( 0.5 * Stk::sampleRate() / lowestFrequency );
delayLine_.setMaximumDelay( nDelays + 1 );
reedTable_.setOffset( 0.7 );
reedTable_.setSlope( -0.3 );
vibrato_.setFrequency( 5.735 );
outputGain_ = 1.0;
noiseGain_ = 0.2;
vibratoGain_ = 0.1;
this->setFrequency( 220.0 );
this->clear();
}
Clarinet :: ~Clarinet( void )
@@ -53,86 +61,77 @@ void Clarinet :: clear( void )
void Clarinet :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "Clarinet::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
oStream_ << "Clarinet::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
// Delay = length - approximate filter delay.
StkFloat delay = (Stk::sampleRate() / freakency) * 0.5 - 1.5;
if (delay <= 0.0) delay = 0.3;
else if (delay > length_) delay = length_;
delayLine_.setDelay(delay);
// Account for filter delay and one sample "lastOut" delay.
StkFloat delay = ( Stk::sampleRate() / frequency ) * 0.5 - filter_.phaseDelay( frequency ) - 1.0;
delayLine_.setDelay( delay );
}
void Clarinet :: startBlowing( StkFloat amplitude, StkFloat rate )
{
envelope_.setRate(rate);
envelope_.setTarget(amplitude);
if ( amplitude <= 0.0 || rate <= 0.0 ) {
oStream_ << "Clarinet::startBlowing: one or more arguments is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
envelope_.setRate( rate );
envelope_.setTarget( amplitude );
}
void Clarinet :: stopBlowing( StkFloat rate )
{
envelope_.setRate(rate);
envelope_.setTarget((StkFloat) 0.0);
if ( rate <= 0.0 ) {
oStream_ << "Clarinet::stopBlowing: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
envelope_.setRate( rate );
envelope_.setTarget( 0.0 );
}
void Clarinet :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency(frequency);
this->startBlowing((StkFloat) 0.55 + (amplitude * (StkFloat) 0.30), amplitude * (StkFloat) 0.005);
outputGain_ = amplitude + (StkFloat) 0.001;
#if defined(_STK_DEBUG_)
errorString_ << "Clarinet::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
this->setFrequency( frequency );
this->startBlowing( 0.55 + (amplitude * 0.30), amplitude * 0.005 );
outputGain_ = amplitude + 0.001;
}
void Clarinet :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.01 );
#if defined(_STK_DEBUG_)
errorString_ << "Clarinet::NoteOff: amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Clarinet :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Clarinet::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Clarinet::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_ReedStiffness_) // 2
reedTable_.setSlope((StkFloat) -0.44 + ( (StkFloat) 0.26 * norm ));
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = (norm * (StkFloat) 0.4);
else if (number == __SK_ModFrequency_) // 11
vibrato_.setFrequency((norm * (StkFloat) 12.0));
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = (norm * (StkFloat) 0.5);
else if (number == __SK_AfterTouch_Cont_) // 128
envelope_.setValue(norm);
else {
errorString_ << "Clarinet::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Clarinet::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Clarinet::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if ( number == __SK_ReedStiffness_ ) // 2
reedTable_.setSlope( -0.44 + ( 0.26 * normalizedValue ) );
else if ( number == __SK_NoiseLevel_ ) // 4
noiseGain_ = ( normalizedValue * 0.4 );
else if ( number == __SK_ModFrequency_ ) // 11
vibrato_.setFrequency( normalizedValue * 12.0 );
else if ( number == __SK_ModWheel_ ) // 1
vibratoGain_ = ( normalizedValue * 0.5 );
else if ( number == __SK_AfterTouch_Cont_ ) // 128
envelope_.setValue( normalizedValue );
#if defined(_STK_DEBUG_)
else {
oStream_ << "Clarinet::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -10,7 +10,7 @@
A non-interpolating delay line is typically used in fixed
delay-length applications, such as for reverberation.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -23,13 +23,8 @@ Delay :: Delay( unsigned long delay, unsigned long maxDelay )
// Writing before reading allows delays from 0 to length-1.
// If we want to allow a delay of maxDelay, we need a
// delay-line of length = maxDelay+1.
if ( maxDelay < 1 ) {
errorString_ << "Delay::Delay: maxDelay must be > 0!\n";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( delay > maxDelay ) {
errorString_ << "Delay::Delay: maxDelay must be > than delay argument!\n";
oStream_ << "Delay::Delay: maxDelay must be > than delay argument!\n";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -47,44 +42,25 @@ Delay :: ~Delay()
void Delay :: setMaximumDelay( unsigned long delay )
{
if ( delay < inputs_.size() ) return;
if ( delay < 0 ) {
errorString_ << "Delay::setMaximumDelay: argument (" << delay << ") less than zero!\n";
handleError( StkError::WARNING );
return;
}
else if ( delay < delay_ ) {
errorString_ << "Delay::setMaximumDelay: argument (" << delay << ") less than current delay setting (" << delay_ << ")!\n";
handleError( StkError::WARNING );
return;
}
inputs_.resize( delay + 1 );
}
void Delay :: setDelay( unsigned long delay )
{
if ( delay > inputs_.size() - 1 ) { // The value is too big.
errorString_ << "Delay::setDelay: argument (" << delay << ") too big ... setting to maximum!\n";
handleError( StkError::WARNING );
oStream_ << "Delay::setDelay: argument (" << delay << ") greater than maximum!\n";
handleError( StkError::WARNING ); return;
}
// Force delay to maximum length.
outPoint_ = inPoint_ + 1;
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
delay_ = inputs_.size() - 1;
if ( delay < 0 ) {
oStream_ << "Delay::setDelay: argument (" << delay << ") less than zero!\n";
handleError( StkError::WARNING ); return;
}
else if ( delay < 0 ) {
errorString_ << "Delay::setDelay: argument (" << delay << ") less than zero ... setting to zero!\n";
handleError( StkError::WARNING );
outPoint_ = inPoint_;
delay_ = 0;
}
else { // read chases write
if ( inPoint_ >= delay ) outPoint_ = inPoint_ - delay;
else outPoint_ = inputs_.size() + inPoint_ - delay;
delay_ = delay;
}
// read chases write
if ( inPoint_ >= delay ) outPoint_ = inPoint_ - delay;
else outPoint_ = inputs_.size() + inPoint_ - delay;
delay_ = delay;
}
StkFloat Delay :: energy( void ) const
@@ -109,7 +85,7 @@ StkFloat Delay :: energy( void ) const
return e;
}
StkFloat Delay :: contentsAt( unsigned long tapDelay )
StkFloat Delay :: tapOut( unsigned long tapDelay )
{
long tap = inPoint_ - tapDelay - 1;
while ( tap < 0 ) // Check for wraparound.
@@ -118,7 +94,16 @@ StkFloat Delay :: contentsAt( unsigned long tapDelay )
return inputs_[tap];
}
StkFloat Delay :: addTo( unsigned long tapDelay, StkFloat value )
void Delay :: tapIn( StkFloat value, unsigned long tapDelay )
{
long tap = inPoint_ - tapDelay - 1;
while ( tap < 0 ) // Check for wraparound.
tap += inputs_.size();
inputs_[tap] = value;
}
StkFloat Delay :: addTo( StkFloat value, unsigned long tapDelay )
{
long tap = inPoint_ - tapDelay - 1;
while ( tap < 0 ) // Check for wraparound.

View File

@@ -14,7 +14,7 @@
minimum delay possible in this implementation is limited to a
value of 0.5.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -24,13 +24,13 @@ namespace stk {
DelayA :: DelayA( StkFloat delay, unsigned long maxDelay )
{
if ( delay < 0.5 || maxDelay < 1 ) {
errorString_ << "DelayA::DelayA: delay must be >= 0.5, maxDelay must be > 0!";
if ( delay < 0.5 ) {
oStream_ << "DelayA::DelayA: delay must be >= 0.5!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( delay > (StkFloat) maxDelay ) {
errorString_ << "DelayA::DelayA: maxDelay must be > than delay argument!";
oStream_ << "DelayA::DelayA: maxDelay must be > than delay argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -59,45 +59,24 @@ void DelayA :: clear()
void DelayA :: setMaximumDelay( unsigned long delay )
{
if ( delay < inputs_.size() ) return;
if ( delay < 0 ) {
errorString_ << "DelayA::setMaximumDelay: argument (" << delay << ") less than zero!\n";
handleError( StkError::WARNING );
return;
}
else if ( delay < delay_ ) {
errorString_ << "DelayA::setMaximumDelay: argument (" << delay << ") less than current delay setting (" << delay_ << ")!\n";
handleError( StkError::WARNING );
return;
}
inputs_.resize( delay + 1 );
}
void DelayA :: setDelay( StkFloat delay )
{
StkFloat outPointer;
unsigned long length = inputs_.size();
if ( delay + 1 > length ) { // The value is too big.
errorString_ << "DelayA::setDelay: argument (" << delay << ") too big ... setting to maximum!";
handleError( StkError::WARNING );
oStream_ << "DelayA::setDelay: argument (" << delay << ") greater than maximum!";
handleError( StkError::WARNING ); return;
}
// Force delay to maxLength
outPointer = inPoint_ + 1.0;
delay_ = length - 1;
}
else if ( delay < 0.5 ) {
errorString_ << "DelayA::setDelay: argument (" << delay << ") less than 0.5 not possible!";
if ( delay < 0.5 ) {
oStream_ << "DelayA::setDelay: argument (" << delay << ") less than 0.5 not possible!";
handleError( StkError::WARNING );
}
outPointer = inPoint_ + 0.4999999999;
delay_ = 0.5;
}
else {
outPointer = inPoint_ - delay + 1.0; // outPoint chases inpoint
delay_ = delay;
}
StkFloat outPointer = inPoint_ - delay + 1.0; // outPoint chases inpoint
delay_ = delay;
while ( outPointer < 0 )
outPointer += length; // modulo maximum length
@@ -110,15 +89,14 @@ void DelayA :: setDelay( StkFloat delay )
// The optimal range for alpha is about 0.5 - 1.5 in order to
// achieve the flattest phase delay response.
outPoint_ += 1;
if (outPoint_ >= length) outPoint_ -= length;
if ( outPoint_ >= length ) outPoint_ -= length;
alpha_ += (StkFloat) 1.0;
}
coeff_ = ((StkFloat) 1.0 - alpha_) /
((StkFloat) 1.0 + alpha_); // coefficient for all pass
coeff_ = (1.0 - alpha_) / (1.0 + alpha_); // coefficient for allpass
}
StkFloat DelayA :: contentsAt( unsigned long tapDelay )
StkFloat DelayA :: tapOut( unsigned long tapDelay )
{
long tap = inPoint_ - tapDelay - 1;
while ( tap < 0 ) // Check for wraparound.
@@ -127,4 +105,13 @@ StkFloat DelayA :: contentsAt( unsigned long tapDelay )
return inputs_[tap];
}
void DelayA :: tapIn( StkFloat value, unsigned long tapDelay )
{
long tap = inPoint_ - tapDelay - 1;
while ( tap < 0 ) // Check for wraparound.
tap += inputs_.size();
inputs_[tap] = value;
}
} // stk namespace

View File

@@ -13,7 +13,7 @@
delay setting. The use of higher order Lagrange interpolators can
typically improve (minimize) this attenuation characteristic.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -23,13 +23,13 @@ namespace stk {
DelayL :: DelayL( StkFloat delay, unsigned long maxDelay )
{
if ( delay < 0.0 || maxDelay < 1 ) {
errorString_ << "DelayL::DelayL: delay must be >= 0.0, maxDelay must be > 0!";
if ( delay < 0.0 ) {
oStream_ << "DelayL::DelayL: delay must be >= 0.0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( delay > (StkFloat) maxDelay ) {
errorString_ << "DelayL::DelayL: maxDelay must be > than delay argument!";
oStream_ << "DelayL::DelayL: maxDelay must be > than delay argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -49,46 +49,25 @@ DelayL :: ~DelayL()
void DelayL :: setMaximumDelay( unsigned long delay )
{
if ( delay < inputs_.size() ) return;
if ( delay < 0 ) {
errorString_ << "DelayL::setMaximumDelay: argument (" << delay << ") less than zero!\n";
handleError( StkError::WARNING );
return;
}
else if ( delay < delay_ ) {
errorString_ << "DelayL::setMaximumDelay: argument (" << delay << ") less than current delay setting (" << delay_ << ")!\n";
handleError( StkError::WARNING );
return;
}
inputs_.resize( delay + 1 );
}
void DelayL :: setDelay( StkFloat delay )
{
StkFloat outPointer;
if ( delay + 1 > inputs_.size() ) { // The value is too big.
errorString_ << "DelayL::setDelay: argument (" << delay << ") too big ... setting to maximum!";
handleError( StkError::WARNING );
// Force delay to maxLength
outPointer = inPoint_ + 1.0;
delay_ = inputs_.size() - 1;
}
else if (delay < 0 ) {
errorString_ << "DelayL::setDelay: argument (" << delay << ") less than zero ... setting to zero!";
handleError( StkError::WARNING );
outPointer = inPoint_;
delay_ = 0;
}
else {
outPointer = inPoint_ - delay; // read chases write
delay_ = delay;
oStream_ << "DelayL::setDelay: argument (" << delay << ") greater than maximum!";
handleError( StkError::WARNING ); return;
}
while (outPointer < 0)
if (delay < 0 ) {
oStream_ << "DelayL::setDelay: argument (" << delay << ") less than zero!";
handleError( StkError::WARNING ); return;
}
StkFloat outPointer = inPoint_ - delay; // read chases write
delay_ = delay;
while ( outPointer < 0 )
outPointer += inputs_.size(); // modulo maximum length
outPoint_ = (long) outPointer; // integer part
@@ -97,7 +76,7 @@ void DelayL :: setDelay( StkFloat delay )
omAlpha_ = (StkFloat) 1.0 - alpha_;
}
StkFloat DelayL :: contentsAt( unsigned long tapDelay )
StkFloat DelayL :: tapOut( unsigned long tapDelay )
{
long tap = inPoint_ - tapDelay - 1;
while ( tap < 0 ) // Check for wraparound.
@@ -106,4 +85,13 @@ StkFloat DelayL :: contentsAt( unsigned long tapDelay )
return inputs_[tap];
}
void DelayL :: tapIn( StkFloat value, unsigned long tapDelay )
{
long tap = inPoint_ - tapDelay - 1;
while ( tap < 0 ) // Check for wraparound.
tap += inputs_.size();
inputs_[tap] = value;
}
} // stk namespace

View File

@@ -11,7 +11,7 @@
of simultaneous voices) via a #define in the
Drummer.h.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -69,21 +69,9 @@ Drummer :: ~Drummer( void )
void Drummer :: noteOn( StkFloat instrument, StkFloat amplitude )
{
#if defined(_STK_DEBUG_)
errorString_ << "Drummer::NoteOn: instrument = " << instrument << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
StkFloat gain = amplitude;
if ( amplitude > 1.0 ) {
errorString_ << "Drummer::noteOn: amplitude parameter is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
}
else if ( amplitude < 0.0 ) {
errorString_ << "Drummer::noteOn: amplitude parameter is less than 0.0 ... doing nothing!";
handleError( StkError::WARNING );
return;
if ( amplitude < 0.0 || amplitude > 1.0 ) {
oStream_ << "Drummer::noteOn: amplitude parameter is out of bounds!";
handleError( StkError::WARNING ); return;
}
// Yes, this is tres kludgey.
@@ -100,8 +88,8 @@ void Drummer :: noteOn( StkFloat instrument, StkFloat amplitude )
nSounding_++;
}
waves_[iWave].reset();
filters_[iWave].setPole( 0.999 - (gain * 0.6) );
filters_[iWave].setGain( gain );
filters_[iWave].setPole( 0.999 - (amplitude * 0.6) );
filters_[iWave].setGain( amplitude );
break;
}
}
@@ -123,22 +111,24 @@ void Drummer :: noteOn( StkFloat instrument, StkFloat amplitude )
}
soundOrder_[iWave] = nSounding_ - 1;
soundNumber_[iWave] = noteNumber;
std::cout << "iWave = " << iWave << ", nSounding = " << nSounding_ << ", soundOrder[] = " << soundOrder_[iWave] << std::endl;
//std::cout << "iWave = " << iWave << ", nSounding = " << nSounding_ << ", soundOrder[] = " << soundOrder_[iWave] << std::endl;
// Concatenate the STK rawwave path to the rawwave file
waves_[iWave].openFile( (Stk::rawwavePath() + waveNames[ genMIDIMap[ noteNumber ] ]).c_str(), true );
if ( Stk::sampleRate() != 22050.0 )
waves_[iWave].setRate( 22050.0 / Stk::sampleRate() );
filters_[iWave].setPole( 0.999 - (gain * 0.6) );
filters_[iWave].setGain( gain );
filters_[iWave].setPole( 0.999 - (amplitude * 0.6) );
filters_[iWave].setGain( amplitude );
}
/*
#if defined(_STK_DEBUG_)
errorString_ << "Drummer::noteOn: number sounding = " << nSounding_ << ", notes: ";
for ( int i=0; i<nSounding_; i++ ) errorString_ << soundNumber_[i] << " ";
errorString_ << '\n';
handleError( StkError::DEBUG_WARNING );
oStream_ << "Drummer::noteOn: number sounding = " << nSounding_ << ", notes: ";
for ( int i=0; i<nSounding_; i++ ) oStream_ << soundNumber_[i] << " ";
oStream_ << '\n';
handleError( StkError::WARNING );
#endif
*/
}
void Drummer :: noteOff( StkFloat amplitude )

View File

@@ -4,7 +4,7 @@
This class implements an echo effect.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -29,26 +29,22 @@ void Echo :: clear( void )
void Echo :: setMaximumDelay( unsigned long delay )
{
length_ = delay;
if ( delay == 0 ) {
errorString_ << "Echo::setMaximumDelay: parameter cannot be zero ... setting to 10!";
handleError( StkError::WARNING );
length_ = 10;
oStream_ << "Echo::setMaximumDelay: parameter cannot be zero!";
handleError( StkError::WARNING ); return;
}
delayLine_.setMaximumDelay( length_ );
delayLine_.setMaximumDelay( delay );
}
void Echo :: setDelay( unsigned long delay )
{
unsigned long size = delay;
if ( delay > length_ ) {
errorString_ << "Echo::setDelay: parameter is greater than maximum delay length ... setting to max!";
handleError( StkError::WARNING );
size = length_;
oStream_ << "Echo::setDelay: parameter is greater than maximum delay length!";
handleError( StkError::WARNING ); return;
}
delayLine_.setDelay( size );
delayLine_.setDelay( delay );
}
} // stk namespace

View File

@@ -7,7 +7,7 @@
specified \e rate. It also responds to simple \e keyOn and \e
keyOff messages, ramping to 1.0 on keyOn and to 0.0 on keyOff.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -47,4 +47,38 @@ void Envelope :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
rate_ = oldRate * rate_ / newRate;
}
void Envelope :: setRate( StkFloat rate )
{
if ( rate < 0.0 ) {
oStream_ << "Envelope::setRate: argument must be >= 0.0!";
handleError( StkError::WARNING ); return;
}
rate_ = rate;
}
void Envelope :: setTime( StkFloat time )
{
if ( time <= 0.0 ) {
oStream_ << "Envelope::setTime: argument must be > 0.0!";
handleError( StkError::WARNING ); return;
}
rate_ = 1.0 / ( time * Stk::sampleRate() );
}
void Envelope :: setTarget( StkFloat target )
{
target_ = target;
if ( value_ != target_ ) state_ = 1;
}
void Envelope :: setValue( StkFloat value )
{
state_ = 0;
target_ = value;
value_ = value;
lastFrame_[0] = value_;
}
} // stk namespace

View File

@@ -19,7 +19,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -32,7 +32,7 @@ FM :: FM( unsigned int operators )
: nOperators_(operators)
{
if ( nOperators_ == 0 ) {
errorString_ << "FM: Invalid number of operators (" << operators << ") argument to constructor!";
oStream_ << "FM::FM: Number of operators must be greater than zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -91,8 +91,14 @@ void FM :: loadWaves( const char **filenames )
void FM :: setFrequency( StkFloat frequency )
{
baseFrequency_ = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "FM::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
baseFrequency_ = frequency;
for ( unsigned int i=0; i<nOperators_; i++ )
waves_[i]->setFrequency( baseFrequency_ * ratios_[i] );
}
@@ -100,14 +106,12 @@ void FM :: setFrequency( StkFloat frequency )
void FM :: setRatio( unsigned int waveIndex, StkFloat ratio )
{
if ( waveIndex < 0 ) {
errorString_ << "FM::setRatio: waveIndex parameter is less than zero!";
handleError( StkError::WARNING );
return;
oStream_ << "FM::setRatio: waveIndex parameter is less than zero!";
handleError( StkError::WARNING ); return;
}
else if ( waveIndex >= nOperators_ ) {
errorString_ << "FM:setRatio: waveIndex parameter is greater than the number of operators!";
handleError( StkError::WARNING );
return;
oStream_ << "FM:setRatio: waveIndex parameter is greater than the number of operators!";
handleError( StkError::WARNING ); return;
}
ratios_[waveIndex] = ratio;
@@ -120,14 +124,12 @@ void FM :: setRatio( unsigned int waveIndex, StkFloat ratio )
void FM :: setGain( unsigned int waveIndex, StkFloat gain )
{
if ( waveIndex < 0 ) {
errorString_ << "FM::setGain: waveIndex parameter is less than zero!";
handleError( StkError::WARNING );
return;
oStream_ << "FM::setGain: waveIndex parameter is less than zero!";
handleError( StkError::WARNING ); return;
}
else if ( waveIndex >= nOperators_ ) {
errorString_ << "FM::setGain: waveIndex parameter is greater than the number of operators!";
handleError( StkError::WARNING );
return;
oStream_ << "FM::setGain: waveIndex parameter is greater than the number of operators!";
handleError( StkError::WARNING ); return;
}
gains_[waveIndex] = gain;
@@ -148,49 +150,37 @@ void FM :: keyOff( void )
void FM :: noteOff( StkFloat amplitude )
{
this->keyOff();
#if defined(_STK_DEBUG_)
errorString_ << "FM::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void FM :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "FM::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "FM::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_Breath_) // 2
this->setControl1( norm );
else if (number == __SK_FootControl_) // 4
this->setControl2( norm );
else if (number == __SK_ModFrequency_) // 11
this->setModulationSpeed( norm * 12.0);
else if (number == __SK_ModWheel_) // 1
this->setModulationDepth( norm );
else if (number == __SK_AfterTouch_Cont_) { // 128
//adsr_[0]->setTarget( norm );
adsr_[1]->setTarget( norm );
//adsr_[2]->setTarget( norm );
adsr_[3]->setTarget( norm );
}
else {
errorString_ << "FM::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "FM::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "FM::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_Breath_) // 2
this->setControl1( normalizedValue );
else if (number == __SK_FootControl_) // 4
this->setControl2( normalizedValue );
else if (number == __SK_ModFrequency_) // 11
this->setModulationSpeed( normalizedValue * 12.0);
else if (number == __SK_ModWheel_) // 1
this->setModulationDepth( normalizedValue );
else if (number == __SK_AfterTouch_Cont_) { // 128
//adsr_[0]->setTarget( normalizedValue );
adsr_[1]->setTarget( normalizedValue );
//adsr_[2]->setTarget( normalizedValue );
adsr_[3]->setTarget( normalizedValue );
}
#if defined(_STK_DEBUG_)
else {
oStream_ << "FM::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -75,6 +75,13 @@ FMVoices :: ~FMVoices( void )
void FMVoices :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "FMVoices::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat temp, temp2 = 0.0;
int tempi = 0;
unsigned int i = 0;
@@ -118,51 +125,38 @@ void FMVoices :: noteOn( StkFloat frequency, StkFloat amplitude )
tilt_[1] = amplitude * amplitude;
tilt_[2] = tilt_[1] * amplitude;
this->keyOn();
#if defined(_STK_DEBUG_)
errorString_ << "FMVoices::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void FMVoices :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "FMVoices::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "FMVoices::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
#if defined(_STK_DEBUG_)
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "FMVoices::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_Breath_) // 2
gains_[3] = fmGains_[(int) ( norm * 99.9 )];
gains_[3] = fmGains_[(int) ( normalizedValue * 99.9 )];
else if (number == __SK_FootControl_) { // 4
currentVowel_ = (int) (norm * 128.0);
currentVowel_ = (int) (normalizedValue * 128.0);
this->setFrequency(baseFrequency_);
}
else if (number == __SK_ModFrequency_) // 11
this->setModulationSpeed( norm * 12.0);
this->setModulationSpeed( normalizedValue * 12.0);
else if (number == __SK_ModWheel_) // 1
this->setModulationDepth( norm );
this->setModulationDepth( normalizedValue );
else if (number == __SK_AfterTouch_Cont_) { // 128
tilt_[0] = norm;
tilt_[1] = norm * norm;
tilt_[2] = tilt_[1] * norm;
tilt_[0] = normalizedValue;
tilt_[1] = normalizedValue * normalizedValue;
tilt_[2] = tilt_[1] * normalizedValue;
}
#if defined(_STK_DEBUG_)
else {
errorString_ << "FMVoices::controlChange: undefined control number (" << number << ")!";
oStream_ << "FMVoices::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "FMVoices::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -12,7 +12,7 @@
the overloaded one that takes an StkFrames object for
multi-channel and/or multi-frame data.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -127,7 +127,7 @@ StkFloat FileLoop :: tick( unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= data_.channels() ) {
errorString_ << "FileLoop::tick(): channel argument and soundfile data are incompatible!";
oStream_ << "FileLoop::tick(): channel argument and soundfile data are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -197,7 +197,7 @@ StkFrames& FileLoop :: tick( StkFrames& frames )
{
if ( !file_.isOpen() ) {
#if defined(_STK_DEBUG_)
errorString_ << "FileLoop::tick(): no file data is loaded!";
oStream_ << "FileLoop::tick(): no file data is loaded!";
handleError( StkError::WARNING );
#endif
return frames;
@@ -206,7 +206,7 @@ StkFrames& FileLoop :: tick( StkFrames& frames )
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( nChannels != frames.channels() ) {
errorString_ << "FileLoop::tick(): StkFrames argument is incompatible with file data!";
oStream_ << "FileLoop::tick(): StkFrames argument is incompatible with file data!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif

View File

@@ -13,17 +13,19 @@
FileRead currently supports uncompressed WAV,
AIFF/AIFC, SND (AU), MAT-file (Matlab), and
STK RAW file formats. Signed integer (8-,
16-, and 32-bit) and floating-point (32- and
16-, 24- and 32-bit) and floating-point (32- and
64-bit) data types are supported. Compressed
data types are not supported.
STK RAW files have no header and are assumed
to contain a monophonic stream of 16-bit
signed integers in big-endian byte order at a
sample rate of 22050 Hz. MAT-file data should
be saved in an array with each data channel
filling a matrix row. The sample rate for
MAT-files is assumed to be 44100 Hz.
STK RAW files have no header and are assumed to
contain a monophonic stream of 16-bit signed
integers in big-endian byte order at a sample
rate of 22050 Hz. MAT-file data should be saved
in an array with each data channel filling a
matrix row. The sample rate for MAT-files should
be specified in a variable named "fs". If no
such variable is found, the sample rate is
assumed to be 44100 Hz.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
@@ -39,7 +41,7 @@
namespace stk {
FileRead :: FileRead()
: fd_(0)
: fd_(0), fileSize_(0), channels_(0), dataType_(0), fileRate_(0.0)
{
}
@@ -61,6 +63,10 @@ void FileRead :: close( void )
if ( fd_ ) fclose( fd_ );
fd_ = 0;
wavFile_ = false;
fileSize_ = 0;
channels_ = 0;
dataType_ = 0;
fileRate_ = 0.0;
}
bool FileRead :: isOpen( void )
@@ -78,7 +84,7 @@ void FileRead :: open( std::string fileName, bool typeRaw, unsigned int nChannel
// Try to open the file.
fd_ = fopen( fileName.c_str(), "rb" );
if ( !fd_ ) {
errorString_ << "FileRead::open: could not open or find file (" << fileName << ")!";
oStream_ << "FileRead::open: could not open or find file (" << fileName << ")!";
handleError( StkError::FILE_NOT_FOUND );
}
@@ -104,7 +110,7 @@ void FileRead :: open( std::string fileName, bool typeRaw, unsigned int nChannel
!strncmp( header, "IM", 2 ) )
result = getMatInfo( fileName.c_str() );
else {
errorString_ << "FileRead::open: file (" << fileName << ") format unknown.";
oStream_ << "FileRead::open: file (" << fileName << ") format unknown.";
handleError( StkError::FILE_UNKNOWN_FORMAT );
}
}
@@ -116,14 +122,14 @@ void FileRead :: open( std::string fileName, bool typeRaw, unsigned int nChannel
// Check for empty files.
if ( fileSize_ == 0 ) {
errorString_ << "FileRead::open: file (" << fileName << ") data size is zero!";
oStream_ << "FileRead::open: file (" << fileName << ") data size is zero!";
handleError( StkError::FILE_ERROR );
}
return;
error:
errorString_ << "FileRead::open: error reading file (" << fileName << ")!";
oStream_ << "FileRead::open: error reading file (" << fileName << ")!";
handleError( StkError::FILE_ERROR );
}
@@ -132,7 +138,7 @@ bool FileRead :: getRawInfo( const char *fileName, unsigned int nChannels, StkFo
// Use the system call "stat" to determine the file length.
struct stat filestat;
if ( stat(fileName, &filestat) == -1 ) {
errorString_ << "FileRead: Could not stat RAW file (" << fileName << ").";
oStream_ << "FileRead: Could not stat RAW file (" << fileName << ").";
return false;
}
@@ -199,8 +205,8 @@ bool FileRead :: getWavInfo( const char *fileName )
#endif
if ( fseek(fd_, dataOffset_, SEEK_SET) == -1 ) goto error;
}
if (format_tag != 1 && format_tag != 3 ) { // PCM = 1, FLOAT = 3
errorString_ << "FileRead: "<< fileName << " contains an unsupported data format type (" << format_tag << ").";
if ( format_tag != 1 && format_tag != 3 ) { // PCM = 1, FLOAT = 3
oStream_ << "FileRead: "<< fileName << " contains an unsupported data format type (" << format_tag << ").";
return false;
}
@@ -228,21 +234,23 @@ bool FileRead :: getWavInfo( const char *fileName )
swap16((unsigned char *)&temp);
#endif
if ( format_tag == 1 ) {
if (temp == 8)
if ( temp == 8 )
dataType_ = STK_SINT8;
else if (temp == 16)
else if ( temp == 16 )
dataType_ = STK_SINT16;
else if (temp == 32)
else if ( temp == 24 )
dataType_ = STK_SINT24;
else if ( temp == 32 )
dataType_ = STK_SINT32;
}
else if ( format_tag == 3 ) {
if (temp == 32)
if ( temp == 32 )
dataType_ = STK_FLOAT32;
else if (temp == 64)
else if ( temp == 64 )
dataType_ = STK_FLOAT64;
}
if ( dataType_ == 0 ) {
errorString_ << "FileRead: " << temp << " bits per sample with data format " << format_tag << " are not supported (" << fileName << ").";
oStream_ << "FileRead: " << temp << " bits per sample with data format " << format_tag << " are not supported (" << fileName << ").";
return false;
}
@@ -268,7 +276,8 @@ bool FileRead :: getWavInfo( const char *fileName )
#ifndef __LITTLE_ENDIAN__
swap32((unsigned char *)&bytes);
#endif
fileSize_ = 8 * bytes / temp / channels_; // sample frames
fileSize_ = bytes / temp / channels_; // sample frames
fileSize_ *= 8; // sample frames
dataOffset_ = ftell(fd_);
byteswap_ = false;
@@ -280,7 +289,7 @@ bool FileRead :: getWavInfo( const char *fileName )
return true;
error:
errorString_ << "FileRead: error reading WAV file (" << fileName << ").";
oStream_ << "FileRead: error reading WAV file (" << fileName << ").";
return false;
}
@@ -293,6 +302,7 @@ bool FileRead :: getSndInfo( const char *fileName )
#ifdef __LITTLE_ENDIAN__
swap32((unsigned char *)&format);
#endif
if (format == 2) dataType_ = STK_SINT8;
else if (format == 3) dataType_ = STK_SINT16;
else if (format == 4) dataType_ = STK_SINT24;
@@ -300,7 +310,7 @@ bool FileRead :: getSndInfo( const char *fileName )
else if (format == 6) dataType_ = STK_FLOAT32;
else if (format == 7) dataType_ = STK_FLOAT64;
else {
errorString_ << "FileRead: data format in file " << fileName << " is not supported.";
oStream_ << "FileRead: data format in file " << fileName << " is not supported.";
return false;
}
@@ -320,11 +330,13 @@ bool FileRead :: getSndInfo( const char *fileName )
#endif
channels_ = chans;
UINT32 offset;
if ( fseek(fd_, 4, SEEK_SET) == -1 ) goto error;
if ( fread(&dataOffset_, 4, 1, fd_) != 1 ) goto error;
if ( fread(&offset, 4, 1, fd_) != 1 ) goto error;
#ifdef __LITTLE_ENDIAN__
swap32((unsigned char *)&dataOffset_);
swap32((unsigned char *)&offset);
#endif
dataOffset_ = offset;
// Get length of data from the header.
if ( fread(&fileSize_, 4, 1, fd_) != 1 ) goto error;
@@ -351,7 +363,7 @@ bool FileRead :: getSndInfo( const char *fileName )
return true;
error:
errorString_ << "FileRead: Error reading SND file (" << fileName << ").";
oStream_ << "FileRead: Error reading SND file (" << fileName << ").";
return false;
}
@@ -442,7 +454,7 @@ bool FileRead :: getAifInfo( const char *fileName )
else if ( (!strncmp(id, "fl64", 4) || !strncmp(id, "FL64", 4)) && temp == 64 ) dataType_ = STK_FLOAT64;
}
if ( dataType_ == 0 ) {
errorString_ << "FileRead: AIFF/AIFC file (" << fileName << ") has unsupported data type (" << id << ").";
oStream_ << "FileRead: AIFF/AIFC file (" << fileName << ") has unsupported data type (" << id << ").";
return false;
}
@@ -473,10 +485,44 @@ bool FileRead :: getAifInfo( const char *fileName )
return true;
error:
errorString_ << "FileRead: Error reading AIFF file (" << fileName << ").";
oStream_ << "FileRead: Error reading AIFF file (" << fileName << ").";
return false;
}
bool FileRead :: findNextMatArray( SINT32 *chunkSize, SINT32 *rows, SINT32 *columns, SINT32 *nametype )
{
// Look for the next data array element. The file pointer should be
// at the data element type when this function is called.
SINT32 datatype;
*chunkSize = 0;
do {
if ( fseek(fd_, *chunkSize, SEEK_CUR) == -1 ) return false;
if ( fread(&datatype, 4, 1, fd_) != 1 ) return false;
if ( byteswap_ ) swap32((unsigned char *)&datatype);
if ( fread(chunkSize, 4, 1, fd_) != 1 ) return false;
if ( byteswap_ ) swap32((unsigned char *)chunkSize);
} while ( datatype != 14 );
// Check dimension subelement size to make sure 2D
if ( fseek(fd_, 20, SEEK_CUR) == -1 ) return false;
SINT32 size;
if ( fread(&size, 4, 1, fd_) != 1 ) return false;
if ( byteswap_ ) swap32((unsigned char *)&size);
if ( size != 8 ) return false;
// Read dimensions data
if ( fread(rows, 4, 1, fd_) != 1 ) return false;
if ( byteswap_ ) swap32((unsigned char *)rows);
if ( fread(columns, 4, 1, fd_) != 1 ) return false;
if ( byteswap_ ) swap32((unsigned char *)columns);
// Read array name subelement type
if ( fread(nametype, 4, 1, fd_) != 1 ) return false;
if ( byteswap_ ) swap32((unsigned char *)nametype);
return true;
}
bool FileRead :: getMatInfo( const char *fileName )
{
// MAT-file formatting information is available at:
@@ -490,7 +536,7 @@ bool FileRead :: getMatInfo( const char *fileName )
// a Version 4 MAT-file.
head[4] = '\0';
if ( strstr(head, "0") ) {
errorString_ << "FileRead: " << fileName << " appears to be a Version 4 MAT-file, which is not currently supported.";
oStream_ << "FileRead: " << fileName << " appears to be a Version 4 MAT-file, which is not currently supported.";
return false;
}
@@ -510,79 +556,164 @@ bool FileRead :: getMatInfo( const char *fileName )
else if ( strncmp(mi, "MI", 2) ) goto error;
#endif
// Check the data element type
SINT32 datatype;
if ( fread(&datatype, 4, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap32((unsigned char *)&datatype);
if (datatype != 14) {
errorString_ << "FileRead: The file does not contain a single Matlab array (or matrix) data element.";
return false;
}
// We are expecting a data element containing the audio data and an
// optional data element containing the sample rate (with an array
// name of "fs"). Both elements should be stored as a Matlab array
// type (14).
// Determine the array data type.
SINT32 tmp;
SINT32 size;
if ( fseek(fd_, 168, SEEK_SET) == -1 ) goto error;
if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error;
if (byteswap_) swap32((unsigned char *)&tmp);
if (tmp == 1) { // array name > 4 characters
if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error; // get array name length
if (byteswap_) swap32((unsigned char *)&tmp);
size = (SINT32) ceil((float)tmp / 8);
if ( fseek(fd_, size*8, SEEK_CUR) == -1 ) goto error; // jump over array name
}
else { // array name <= 4 characters, compressed data element
if ( fseek(fd_, 4, SEEK_CUR) == -1 ) goto error;
}
if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error;
if (byteswap_) swap32((unsigned char *)&tmp);
if ( tmp == 1 ) dataType_ = STK_SINT8;
else if ( tmp == 3 ) dataType_ = STK_SINT16;
else if ( tmp == 5 ) dataType_ = STK_SINT32;
else if ( tmp == 7 ) dataType_ = STK_FLOAT32;
else if ( tmp == 9 ) dataType_ = STK_FLOAT64;
else {
errorString_ << "FileRead: The MAT-file array data format (" << tmp << ") is not supported.";
return false;
}
bool doneParsing, haveData, haveSampleRate;
SINT32 chunkSize, rows, columns, nametype;
int dataoffset;
doneParsing = false;
haveData = false;
haveSampleRate = false;
while ( !doneParsing ) {
// Get number of rows from the header.
SINT32 rows;
if ( fseek(fd_, 160, SEEK_SET) == -1 ) goto error;
if ( fread(&rows, 4, 1, fd_) != 1 ) goto error;
if (byteswap_) swap32((unsigned char *)&rows);
dataoffset = ftell( fd_ ); // save location in file
if ( findNextMatArray( &chunkSize, &rows, &columns, &nametype ) == false ) {
// No more Matlab array type chunks found.
if ( !haveData ) {
oStream_ << "FileRead: No audio data found in MAT-file (" << fileName << ").";
return false;
}
else if ( !haveSampleRate ) {
fileRate_ = 44100.0;
oStream_ << "FileRead: No sample rate found ... assuming 44100.0";
handleError( StkError::WARNING );
return true;
}
else return true;
}
// Get number of columns from the header.
SINT32 columns;
if ( fread(&columns, 4, 1, fd_) != 1 ) goto error;
if (byteswap_) swap32((unsigned char *)&columns);
if ( !haveSampleRate && rows == 1 && columns == 1 ) { // Parse for sample rate.
// Assume channels = smaller of rows or columns.
if (rows < columns) {
channels_ = rows;
fileSize_ = columns;
SINT32 namesize = 4;
if ( nametype == 1 ) { // array name > 4 characters
if ( fread(&namesize, 4, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap32((unsigned char *)namesize);
if ( namesize != 2 ) goto tryagain; // expecting name = "fs"
namesize = 8; // field must be padded to multiple of 8 bytes
}
char name[3]; name[2] = '\0';
if ( fread(&name, 2, 1, fd_) != 1) goto error;
if ( strncmp(name, "fs", 2) ) goto tryagain;
// Jump to real part data subelement, which is likely to be in a
// small data format.
if ( fseek(fd_, namesize-2, SEEK_CUR) == -1 ) goto error;
UINT32 type;
StkFloat srate;
if ( fread(&type, 4, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap32((unsigned char *)&type);
if ( (type & 0xffff0000) != 0 ) // small data format
type = (type & 0x0000ffff);
else
if ( fseek(fd_, 4, SEEK_CUR) == -1 ) goto error;
if ( type == 1 ) { // SINT8
signed char rate;
if ( fread(&rate, 1, 1, fd_) != 1 ) goto error;
srate = (StkFloat) rate;
}
if ( type == 2 ) { // UINT8
unsigned char rate;
if ( fread(&rate, 1, 1, fd_) != 1 ) goto error;
srate = (StkFloat) rate;
}
else if ( type == 3 ) { // SINT16
SINT16 rate;
if ( fread(&rate, 2, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap16((unsigned char *)&rate);
srate = (StkFloat) rate;
}
else if ( type == 4 ) { // UINT16
UINT16 rate;
if ( fread(&rate, 2, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap16((unsigned char *)&rate);
srate = (StkFloat) rate;
}
else if ( type == 5 ) { // SINT32
SINT32 rate;
if ( fread(&rate, 4, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap32((unsigned char *)&rate);
srate = (StkFloat) rate;
}
else if ( type == 6 ) { // UINT32
UINT32 rate;
if ( fread(&rate, 4, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap32((unsigned char *)&rate);
srate = (StkFloat) rate;
}
else if ( type == 7 ) { // FLOAT32
FLOAT32 rate;
if ( fread(&rate, 4, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap32((unsigned char *)&rate);
srate = (StkFloat) rate;
}
else if ( type == 9 ) { // FLOAT64
FLOAT64 rate;
if ( fread(&rate, 8, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap64((unsigned char *)&rate);
srate = (StkFloat) rate;
}
else
goto tryagain;
if ( srate > 0 ) fileRate_ = srate;
haveSampleRate = true;
}
else if ( !haveData ) { // Parse for data.
// Assume channels = smaller of rows or columns.
if ( rows < columns ) {
channels_ = rows;
fileSize_ = columns;
}
else {
oStream_ << "FileRead: Transpose the MAT-file array so that audio channels fill matrix rows (not columns).";
return false;
}
SINT32 namesize = 4;
if ( nametype == 1 ) { // array name > 4 characters
if ( fread(&namesize, 4, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap32((unsigned char *)namesize);
namesize = (SINT32) ceil((float)namesize / 8);
if ( fseek( fd_, namesize*8, SEEK_CUR) == -1 ) goto error; // jump over array name
}
else {
if ( fseek( fd_, 4, SEEK_CUR ) == -1 ) goto error;
}
// Now at real part data subelement
SINT32 type;
if ( fread(&type, 4, 1, fd_) != 1 ) goto error;
if ( byteswap_ ) swap32((unsigned char *)&type);
if ( type == 1 ) dataType_ = STK_SINT8;
else if ( type == 3 ) dataType_ = STK_SINT16;
else if ( type == 5 ) dataType_ = STK_SINT32;
else if ( type == 7 ) dataType_ = STK_FLOAT32;
else if ( type == 9 ) dataType_ = STK_FLOAT64;
else {
oStream_ << "FileRead: The MAT-file array data format (" << type << ") is not supported.";
return false;
}
// Jump to the data.
if ( fseek(fd_, 4, SEEK_CUR) == -1 ) goto error;
dataOffset_ = ftell(fd_);
haveData = true;
}
tryagain:
if ( haveData && haveSampleRate ) doneParsing = true;
else // jump to end of data element and keep trying
if ( fseek( fd_, dataoffset+chunkSize+8, SEEK_SET) == -1 ) goto error;
}
else {
errorString_ << "FileRead: Transpose the MAT-file array so that audio channels fill matrix rows (not columns).";
return false;
}
// Move read pointer to the data in the file.
SINT32 headsize;
if ( fseek(fd_, 132, SEEK_SET) == -1 ) goto error;
if ( fread(&headsize, 4, 1, fd_) != 1 ) goto error; // file size from 132nd byte
if (byteswap_) swap32((unsigned char *)&headsize);
headsize -= fileSize_ * 8 * channels_;
if ( fseek(fd_, headsize, SEEK_CUR) == -1 ) goto error;
dataOffset_ = ftell(fd_);
// Assume MAT-files have 44100 Hz sample rate.
fileRate_ = 44100.0;
return true;
error:
errorString_ << "FileRead: Error reading MAT-file (" << fileName << ").";
oStream_ << "FileRead: Error reading MAT-file (" << fileName << ") header.";
return false;
}
@@ -590,21 +721,19 @@ void FileRead :: read( StkFrames& buffer, unsigned long startFrame, bool doNorma
{
// Make sure we have an open file.
if ( fd_ == 0 ) {
errorString_ << "FileRead::read: a file is not open!";
Stk::handleError( StkError::WARNING );
return;
oStream_ << "FileRead::read: a file is not open!";
Stk::handleError( StkError::WARNING ); return;
}
// Check the buffer size.
unsigned int nFrames = buffer.frames();
if ( nFrames == 0 ) {
errorString_ << "FileRead::read: StkFrames buffer size is zero ... no data read!";
Stk::handleError( StkError::WARNING );
return;
oStream_ << "FileRead::read: StkFrames buffer size is zero ... no data read!";
Stk::handleError( StkError::WARNING ); return;
}
if ( buffer.channels() != channels_ ) {
errorString_ << "FileRead::read: StkFrames argument has incompatible number of channels!";
oStream_ << "FileRead::read: StkFrames argument has incompatible number of channels!";
Stk::handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -709,19 +838,39 @@ void FileRead :: read( StkFrames& buffer, unsigned long startFrame, bool doNorma
else if ( dataType_ == STK_SINT24 ) {
// 24-bit values are harder to import efficiently since there is
// no native 24-bit type. The following routine works but is much
// less efficient that that used for the other data types.
SINT32 buf;
StkFloat gain = 1.0 / 8388608.0;
// less efficient than that used for the other data types.
SINT32 temp;
unsigned char *ptr = (unsigned char *) &temp;
StkFloat gain = 1.0 / 2147483648.0;
if ( fseek(fd_, dataOffset_+(offset*3), SEEK_SET ) == -1 ) goto error;
for ( i=0; i<nSamples; i++ ) {
if ( fread( &buf, 3, 1, fd_ ) != 1 ) goto error;
buf >>= 8;
if ( byteswap_ )
swap32( (unsigned char *) &buf );
if ( doNormalize )
buffer[i] = buf * gain;
#ifdef __LITTLE_ENDIAN__
if ( byteswap_ ) {
if ( fread( ptr, 3, 1, fd_ ) != 1 ) goto error;
temp &= 0x00ffffff;
swap32( (unsigned char *) ptr );
}
else {
if ( fread( ptr+1, 3, 1, fd_ ) != 1 ) goto error;
temp &= 0xffffff00;
}
#else
if ( byteswap_ ) {
if ( fread( ptr+1, 3, 1, fd_ ) != 1 ) goto error;
temp &= 0xffffff00;
swap32( (unsigned char *) ptr );
}
else {
if ( fread( ptr, 3, 1, fd_ ) != 1 ) goto error;
temp &= 0x00ffffff;
}
#endif
if ( doNormalize ) {
buffer[i] = (StkFloat) temp * gain; // "gain" also includes 1 / 256 factor.
}
else
buffer[i] = buf;
buffer[i] = (StkFloat) temp / 256; // right shift without affecting the sign bit
}
}
@@ -730,7 +879,7 @@ void FileRead :: read( StkFrames& buffer, unsigned long startFrame, bool doNorma
return;
error:
errorString_ << "FileRead: Error reading file data.";
oStream_ << "FileRead: Error reading file data.";
handleError( StkError::FILE_ERROR);
}

View File

@@ -10,20 +10,21 @@
FileWrite currently supports uncompressed WAV, AIFF, AIFC, SND
(AU), MAT-file (Matlab), and STK RAW file formats. Signed integer
(8-, 16-, and 32-bit) and floating- point (32- and 64-bit) data
types are supported. STK RAW files use 16-bit integers by
(8-, 16-, 24-, and 32-bit) and floating- point (32- and 64-bit)
data types are supported. STK RAW files use 16-bit integers by
definition. MAT-files will always be written as 64-bit floats.
If a data type specification does not match the specified file
type, the data type will automatically be modified. Compressed
data types are not supported.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
#include "FileWrite.h"
#include <cstring>
#include <string>
#include <cstdio>
#include <cstring>
#include <cmath>
namespace stk {
@@ -36,58 +37,64 @@ const FileWrite::FILE_TYPE FileWrite :: FILE_MAT = 5;
// WAV header structure. See ftp://ftp.isi.edu/in-notes/rfc2361.txt
// for information regarding format codes.
struct wavhdr {
struct WaveHeader {
char riff[4]; // "RIFF"
SINT32 file_size; // in bytes
SINT32 fileSize; // in bytes
char wave[4]; // "WAVE"
char fmt[4]; // "fmt "
SINT32 chunk_size; // in bytes (16 for PCM)
SINT16 format_tag; // 1=PCM, 2=ADPCM, 3=IEEE float, 6=A-Law, 7=Mu-Law
SINT16 num_chans; // 1=mono, 2=stereo
SINT32 sample_rate;
SINT32 bytes_per_sec;
SINT16 bytes_per_samp; // 2=16-bit mono, 4=16-bit stereo
SINT16 bits_per_samp;
char data[4]; // "data"
SINT32 data_length; // in bytes
SINT32 chunkSize; // in bytes (16 for PCM)
SINT16 formatCode; // 1=PCM, 2=ADPCM, 3=IEEE float, 6=A-Law, 7=Mu-Law
SINT16 nChannels; // 1=mono, 2=stereo
SINT32 sampleRate;
SINT32 bytesPerSecond;
SINT16 bytesPerSample; // 2=16-bit mono, 4=16-bit stereo
SINT16 bitsPerSample;
SINT16 cbSize; // size of extension
SINT16 validBits; // valid bits per sample
SINT32 channelMask; // speaker position mask
char subformat[16]; // format code and GUID
char fact[4]; // "fact"
SINT32 factSize; // fact chunk size
SINT32 frames; // sample frames
};
// SND (AU) header structure (NeXT and Sun).
struct sndhdr {
struct SndHeader {
char pref[4];
SINT32 hdr_length;
SINT32 data_length;
SINT32 headerBytes;
SINT32 dataBytes;
SINT32 format;
SINT32 sample_rate;
SINT32 num_channels;
SINT32 sampleRate;
SINT32 nChannels;
char comment[16];
};
// AIFF/AIFC header structure ... only the part common to both
// formats.
struct aifhdr {
struct AifHeader {
char form[4]; // "FORM"
SINT32 form_size; // in bytes
SINT32 formSize; // in bytes
char aiff[4]; // "AIFF" or "AIFC"
char comm[4]; // "COMM"
SINT32 comm_size; // "COMM" chunk size (18 for AIFF, 24 for AIFC)
SINT16 num_chans; // number of channels
unsigned long sample_frames; // sample frames of audio data
SINT16 sample_size; // in bits
SINT32 commSize; // "COMM" chunk size (18 for AIFF, 24 for AIFC)
SINT16 nChannels; // number of channels
unsigned long sampleFrames; // sample frames of audio data
SINT16 sampleSize; // in bits
unsigned char srate[10]; // IEEE 754 floating point format
};
struct aifssnd {
struct AifSsnd {
char ssnd[4]; // "SSND"
SINT32 ssnd_size; // "SSND" chunk size
SINT32 ssndSize; // "SSND" chunk size
unsigned long offset; // data offset in data block (should be 0)
unsigned long block_size; // not used by STK (should be 0)
unsigned long blockSize; // not used by STK (should be 0)
};
// MAT-file 5 header structure.
struct mathdr {
struct MatHeader {
char heading[124]; // Header text field
SINT16 hff[2]; // Header flag fields
SINT32 fs[16]; // Sample rate data element
SINT32 adf[11]; // Array data format fields
// There's more, but it's of variable length
};
@@ -138,7 +145,7 @@ void FileWrite :: open( std::string fileName, unsigned int nChannels, FileWrite:
this->close();
if ( nChannels < 1 ) {
errorString_ << "FileWrite::open: then channels argument must be greater than zero!";
oStream_ << "FileWrite::open: then channels argument must be greater than zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -146,9 +153,9 @@ void FileWrite :: open( std::string fileName, unsigned int nChannels, FileWrite:
fileType_ = type;
if ( format != STK_SINT8 && format != STK_SINT16 &&
format != STK_SINT32 && format != STK_FLOAT32 &&
format != STK_FLOAT64 ) {
errorString_ << "FileWrite::open: unknown data type (" << format << ") specified!";
format != STK_SINT24 && format != STK_SINT32 &&
format != STK_FLOAT32 && format != STK_FLOAT64 ) {
oStream_ << "FileWrite::open: unknown data type (" << format << ") specified!";
handleError( StkError::FUNCTION_ARGUMENT );
}
dataType_ = format;
@@ -156,21 +163,21 @@ void FileWrite :: open( std::string fileName, unsigned int nChannels, FileWrite:
bool result = false;
if ( fileType_ == FILE_RAW ) {
if ( channels_ != 1 ) {
errorString_ << "FileWrite::open: STK RAW files are, by definition, always monaural (channels = " << nChannels << " not supported)!";
oStream_ << "FileWrite::open: STK RAW files are, by definition, always monaural (channels = " << nChannels << " not supported)!";
handleError( StkError::FUNCTION_ARGUMENT );
}
result = setRawFile( fileName.c_str() );
result = setRawFile( fileName );
}
else if ( fileType_ == FILE_WAV )
result = setWavFile( fileName.c_str() );
result = setWavFile( fileName );
else if ( fileType_ == FILE_SND )
result = setSndFile( fileName.c_str() );
result = setSndFile( fileName );
else if ( fileType_ == FILE_AIF )
result = setAifFile( fileName.c_str() );
result = setAifFile( fileName );
else if ( fileType_ == FILE_MAT )
result = setMatFile( fileName.c_str() );
result = setMatFile( fileName );
else {
errorString_ << "FileWrite::open: unknown file type (" << fileType_ << ") specified!";
oStream_ << "FileWrite::open: unknown file type (" << fileType_ << ") specified!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -180,21 +187,19 @@ void FileWrite :: open( std::string fileName, unsigned int nChannels, FileWrite:
frameCounter_ = 0;
}
bool FileWrite :: setRawFile( const char *fileName )
bool FileWrite :: setRawFile( std::string fileName )
{
char name[8192];
strncpy(name, fileName, 8192);
if ( strstr(name, ".raw") == NULL) strcat(name, ".raw");
fd_ = fopen(name, "wb");
if ( fileName.find( ".raw" ) == std::string::npos ) fileName += ".raw";
fd_ = fopen( fileName.c_str(), "wb" );
if ( !fd_ ) {
errorString_ << "FileWrite: could not create RAW file: " << name << '.';
oStream_ << "FileWrite: could not create RAW file: " << fileName << '.';
return false;
}
if ( dataType_ != STK_SINT16 ) {
dataType_ = STK_SINT16;
errorString_ << "FileWrite: using 16-bit signed integer data format for file " << name << '.';
handleError( StkError::DEBUG_WARNING );
oStream_ << "FileWrite: using 16-bit signed integer data format for file " << fileName << '.';
handleError( StkError::WARNING );
}
byteswap_ = false;
@@ -202,113 +207,160 @@ bool FileWrite :: setRawFile( const char *fileName )
byteswap_ = true;
#endif
errorString_ << "FileWrite: creating RAW file: " << name;
oStream_ << "FileWrite: creating RAW file: " << fileName;
handleError( StkError::STATUS );
return true;
}
bool FileWrite :: setWavFile( const char *fileName )
bool FileWrite :: setWavFile( std::string fileName )
{
char name[8192];
strncpy(name, fileName, 8192);
if ( strstr(name, ".wav") == NULL) strcat(name, ".wav");
fd_ = fopen(name, "wb");
std::string name( fileName );
if ( fileName.find( ".wav" ) == std::string::npos ) fileName += ".wav";
fd_ = fopen( fileName.c_str(), "wb" );
if ( !fd_ ) {
errorString_ << "FileWrite: could not create WAV file: " << name;
oStream_ << "FileWrite: could not create WAV file: " << fileName;
return false;
}
struct wavhdr hdr = {"RIF", 44, "WAV", "fmt", 16, 1, 1,
(SINT32) Stk::sampleRate(), 0, 2, 16, "dat", 0};
hdr.riff[3] = 'F';
hdr.wave[3] = 'E';
hdr.fmt[3] = ' ';
hdr.data[3] = 'a';
hdr.num_chans = (SINT16) channels_;
struct WaveHeader hdr = { {'R','I','F','F'}, 44, {'W','A','V','E'}, {'f','m','t',' '}, 16, 1, 1,
(SINT32) Stk::sampleRate(), 0, 2, 16, 0, 0, 0,
{'\x01','\x00','\x00','\x00','\x00','\x00','\x10','\x00','\x80','\x00','\x00','\xAA','\x00','\x38','\x9B','\x71'},
{'f','a','c','t'}, 4, 0 };
hdr.nChannels = (SINT16) channels_;
if ( dataType_ == STK_SINT8 )
hdr.bits_per_samp = 8;
hdr.bitsPerSample = 8;
else if ( dataType_ == STK_SINT16 )
hdr.bits_per_samp = 16;
hdr.bitsPerSample = 16;
else if ( dataType_ == STK_SINT24 )
hdr.bitsPerSample = 24;
else if ( dataType_ == STK_SINT32 )
hdr.bits_per_samp = 32;
hdr.bitsPerSample = 32;
else if ( dataType_ == STK_FLOAT32 ) {
hdr.format_tag = 3;
hdr.bits_per_samp = 32;
hdr.formatCode = 3;
hdr.bitsPerSample = 32;
}
else if ( dataType_ == STK_FLOAT64 ) {
hdr.format_tag = 3;
hdr.bits_per_samp = 64;
hdr.formatCode = 3;
hdr.bitsPerSample = 64;
}
hdr.bytesPerSample = (SINT16) (channels_ * hdr.bitsPerSample / 8);
hdr.bytesPerSecond = (SINT32) (hdr.sampleRate * hdr.bytesPerSample);
unsigned int bytesToWrite = 36;
bool useExtensible = false;
if ( channels_ > 2 || hdr.bitsPerSample > 16 ) { // use extensible format
useExtensible = true;
bytesToWrite = 72;
hdr.chunkSize += 24;
hdr.formatCode = 0xFFFE;
hdr.cbSize = 22;
hdr.validBits = hdr.bitsPerSample;
SINT16 *subFormat = (SINT16 *)&hdr.subformat[0];
if ( dataType_ == STK_FLOAT32 || dataType_ == STK_FLOAT64 )
*subFormat = 3;
else *subFormat = 1;
}
hdr.bytes_per_samp = (SINT16) (channels_ * hdr.bits_per_samp / 8);
hdr.bytes_per_sec = (SINT32) (hdr.sample_rate * hdr.bytes_per_samp);
byteswap_ = false;
#ifndef __LITTLE_ENDIAN__
byteswap_ = true;
swap32((unsigned char *)&hdr.file_size);
swap32((unsigned char *)&hdr.chunk_size);
swap16((unsigned char *)&hdr.format_tag);
swap16((unsigned char *)&hdr.num_chans);
swap32((unsigned char *)&hdr.sample_rate);
swap32((unsigned char *)&hdr.bytes_per_sec);
swap16((unsigned char *)&hdr.bytes_per_samp);
swap16((unsigned char *)&hdr.bits_per_samp);
swap32((unsigned char *)&hdr.chunkSize);
swap16((unsigned char *)&hdr.formatCode);
swap16((unsigned char *)&hdr.nChannels);
swap32((unsigned char *)&hdr.sampleRate);
swap32((unsigned char *)&hdr.bytesPerSecond);
swap16((unsigned char *)&hdr.bytesPerSample);
swap16((unsigned char *)&hdr.bitsPerSample);
swap16((unsigned char *)&hdr.cbSize);
swap16((unsigned char *)&hdr.validBits);
swap16((unsigned char *)&hdr.subformat[0]);
swap32((unsigned char *)&hdr.factSize);
#endif
if ( fwrite(&hdr, 4, 11, fd_) != 11 ) {
errorString_ << "FileWrite: could not write WAV header for file " << name << '.';
return false;
}
char data[4] = {'d','a','t','a'};
SINT32 dataSize = 0;
if ( fwrite(&hdr, 1, bytesToWrite, fd_) != bytesToWrite ) goto error;
if ( fwrite(&data, 4, 1, fd_) != 1 ) goto error;
if ( fwrite(&dataSize, 4, 1, fd_) != 1 ) goto error;
errorString_ << "FileWrite: creating WAV file: " << name;
oStream_ << "FileWrite: creating WAV file: " << fileName;
handleError( StkError::STATUS );
return true;
error:
oStream_ << "FileWrite: could not write WAV header for file: " << fileName;
return false;
}
void FileWrite :: closeWavFile( void )
{
int bytes_per_sample = 1;
int bytesPerSample = 1;
if ( dataType_ == STK_SINT16 )
bytes_per_sample = 2;
bytesPerSample = 2;
else if ( dataType_ == STK_SINT24 )
bytesPerSample = 3;
else if ( dataType_ == STK_SINT32 || dataType_ == STK_FLOAT32 )
bytes_per_sample = 4;
bytesPerSample = 4;
else if ( dataType_ == STK_FLOAT64 )
bytes_per_sample = 8;
bytesPerSample = 8;
SINT32 bytes = frameCounter_ * channels_ * bytes_per_sample;
bool useExtensible = false;
int dataLocation = 40;
if ( bytesPerSample > 2 || channels_ > 2 ) {
useExtensible = true;
dataLocation = 76;
}
SINT32 bytes = frameCounter_ * channels_ * bytesPerSample;
if ( bytes % 2 ) { // pad extra byte if odd
signed char sample = 0;
fwrite( &sample, 1, 1, fd_ );
}
#ifndef __LITTLE_ENDIAN__
swap32((unsigned char *)&bytes);
#endif
fseek(fd_, 40, SEEK_SET); // jump to data length
fwrite(&bytes, 4, 1, fd_);
fseek( fd_, dataLocation, SEEK_SET ); // jump to data length
fwrite( &bytes, 4, 1, fd_ );
bytes = frameCounter_ * channels_ * bytes_per_sample + 44;
bytes = frameCounter_ * channels_ * bytesPerSample + 44;
if ( useExtensible ) bytes += 36;
#ifndef __LITTLE_ENDIAN__
swap32((unsigned char *)&bytes);
#endif
fseek(fd_, 4, SEEK_SET); // jump to file size
fwrite(&bytes, 4, 1, fd_);
fseek( fd_, 4, SEEK_SET ); // jump to file size
fwrite( &bytes, 4, 1, fd_ );
if ( useExtensible ) { // fill in the "fact" chunk frames value
bytes = frameCounter_;
#ifndef __LITTLE_ENDIAN__
swap32((unsigned char *)&bytes);
#endif
fseek( fd_, 68, SEEK_SET );
fwrite( &bytes, 4, 1, fd_ );
}
fclose( fd_ );
}
bool FileWrite :: setSndFile( const char *fileName )
bool FileWrite :: setSndFile( std::string fileName )
{
char name[8192];
strncpy(name, fileName, 8192);
if ( strstr(name, ".snd") == NULL) strcat(name, ".snd");
fd_ = fopen(name, "wb");
std::string name( fileName );
if ( fileName.find( ".snd" ) == std::string::npos ) fileName += ".snd";
fd_ = fopen( fileName.c_str(), "wb" );
if ( !fd_ ) {
errorString_ << "FileWrite: could not create SND file: " << name;
oStream_ << "FileWrite: could not create SND file: " << fileName;
return false;
}
struct sndhdr hdr = {".sn", 40, 0, 3, (SINT32) Stk::sampleRate(), 1, "Created by STK"};
struct SndHeader hdr = {".sn", 40, 0, 3, (SINT32) Stk::sampleRate(), 1, "Created by STK"};
hdr.pref[3] = 'd';
hdr.num_channels = channels_;
hdr.nChannels = channels_;
if ( dataType_ == STK_SINT8 )
hdr.format = 2;
else if ( dataType_ == STK_SINT16 )
hdr.format = 3;
else if ( dataType_ == STK_SINT24 )
hdr.format = 4;
else if ( dataType_ == STK_SINT32 )
hdr.format = 5;
else if ( dataType_ == STK_FLOAT32 )
@@ -319,35 +371,37 @@ bool FileWrite :: setSndFile( const char *fileName )
byteswap_ = false;
#ifdef __LITTLE_ENDIAN__
byteswap_ = true;
swap32 ((unsigned char *)&hdr.hdr_length);
swap32 ((unsigned char *)&hdr.headerBytes);
swap32 ((unsigned char *)&hdr.format);
swap32 ((unsigned char *)&hdr.sample_rate);
swap32 ((unsigned char *)&hdr.num_channels);
swap32 ((unsigned char *)&hdr.sampleRate);
swap32 ((unsigned char *)&hdr.nChannels);
#endif
if ( fwrite(&hdr, 4, 10, fd_) != 10 ) {
errorString_ << "FileWrite: Could not write SND header for file " << name << '.';
oStream_ << "FileWrite: Could not write SND header for file " << fileName << '.';
return false;
}
errorString_ << "FileWrite: creating SND file: " << name;
oStream_ << "FileWrite: creating SND file: " << fileName;
handleError( StkError::STATUS );
return true;
}
void FileWrite :: closeSndFile( void )
{
int bytes_per_sample = 1;
int bytesPerSample = 1;
if ( dataType_ == STK_SINT16 )
bytes_per_sample = 2;
bytesPerSample = 2;
else if ( dataType_ == STK_SINT24 )
bytesPerSample = 3;
else if ( dataType_ == STK_SINT32 )
bytes_per_sample = 4;
bytesPerSample = 4;
else if ( dataType_ == STK_FLOAT32 )
bytes_per_sample = 4;
bytesPerSample = 4;
else if ( dataType_ == STK_FLOAT64 )
bytes_per_sample = 8;
bytesPerSample = 8;
SINT32 bytes = frameCounter_ * bytes_per_sample * channels_;
SINT32 bytes = frameCounter_ * bytesPerSample * channels_;
#ifdef __LITTLE_ENDIAN__
swap32 ((unsigned char *)&bytes);
#endif
@@ -356,40 +410,37 @@ void FileWrite :: closeSndFile( void )
fclose(fd_);
}
bool FileWrite :: setAifFile( const char *fileName )
bool FileWrite :: setAifFile( std::string fileName )
{
char name[8192];
strncpy(name, fileName, 8192);
if ( strstr(name, ".aif") == NULL) strcat(name, ".aif");
fd_ = fopen(name, "wb");
std::string name( fileName );
if ( fileName.find( ".aif" ) == std::string::npos ) fileName += ".aif";
fd_ = fopen( fileName.c_str(), "wb" );
if ( !fd_ ) {
errorString_ << "FileWrite: could not create AIF file: " << name;
oStream_ << "FileWrite: could not create AIF file: " << fileName;
return false;
}
// Common parts of AIFF/AIFC header.
struct aifhdr hdr = {"FOR", 46, "AIF", "COM", 18, 0, 0, 16, "0"};
struct aifssnd ssnd = {"SSN", 8, 0, 0};
hdr.form[3] = 'M';
hdr.aiff[3] = 'F';
hdr.comm[3] = 'M';
ssnd.ssnd[3] = 'D';
hdr.num_chans = channels_;
struct AifHeader hdr = {{'F','O','R','M'}, 46, {'A','I','F','F'}, {'C','O','M','M'}, 18, 0, 0, 16, "0"};
struct AifSsnd ssnd = {{'S','S','N','D'}, 8, 0, 0};
hdr.nChannels = channels_;
if ( dataType_ == STK_SINT8 )
hdr.sample_size = 8;
hdr.sampleSize = 8;
else if ( dataType_ == STK_SINT16 )
hdr.sample_size = 16;
hdr.sampleSize = 16;
else if ( dataType_ == STK_SINT24 )
hdr.sampleSize = 24;
else if ( dataType_ == STK_SINT32 )
hdr.sample_size = 32;
hdr.sampleSize = 32;
else if ( dataType_ == STK_FLOAT32 ) {
hdr.aiff[3] = 'C';
hdr.sample_size = 32;
hdr.comm_size = 24;
hdr.sampleSize = 32;
hdr.commSize = 24;
}
else if ( dataType_ == STK_FLOAT64 ) {
hdr.aiff[3] = 'C';
hdr.sample_size = 64;
hdr.comm_size = 24;
hdr.sampleSize = 64;
hdr.commSize = 24;
}
// For AIFF files, the sample rate is stored in a 10-byte,
@@ -398,11 +449,11 @@ bool FileWrite :: setAifFile( const char *fileName )
SINT16 i;
unsigned long exp;
unsigned long rate = (unsigned long) Stk::sampleRate();
memset(hdr.srate, 0, 10);
memset( hdr.srate, 0, 10 );
exp = rate;
for (i=0; i<32; i++) {
for ( i=0; i<32; i++ ) {
exp >>= 1;
if (!exp) break;
if ( !exp ) break;
}
i += 16383;
#ifdef __LITTLE_ENDIAN__
@@ -410,8 +461,8 @@ bool FileWrite :: setAifFile( const char *fileName )
#endif
*(SINT16 *)(hdr.srate) = (SINT16) i;
for (i=32; i; i--) {
if (rate & 0x80000000) break;
for ( i=32; i; i-- ) {
if ( rate & 0x80000000 ) break;
rate <<= 1;
}
@@ -423,20 +474,20 @@ bool FileWrite :: setAifFile( const char *fileName )
byteswap_ = false;
#ifdef __LITTLE_ENDIAN__
byteswap_ = true;
swap32((unsigned char *)&hdr.form_size);
swap32((unsigned char *)&hdr.comm_size);
swap16((unsigned char *)&hdr.num_chans);
swap16((unsigned char *)&hdr.sample_size);
swap32((unsigned char *)&ssnd.ssnd_size);
swap32((unsigned char *)&hdr.formSize);
swap32((unsigned char *)&hdr.commSize);
swap16((unsigned char *)&hdr.nChannels);
swap16((unsigned char *)&hdr.sampleSize);
swap32((unsigned char *)&ssnd.ssndSize);
swap32((unsigned char *)&ssnd.offset);
swap32((unsigned char *)&ssnd.block_size);
swap32((unsigned char *)&ssnd.blockSize);
#endif
// The structure boundaries don't allow a single write of 54 bytes.
if ( fwrite(&hdr, 4, 5, fd_) != 5 ) goto error;
if ( fwrite(&hdr.num_chans, 2, 1, fd_) != 1 ) goto error;
if ( fwrite(&hdr.sample_frames, 4, 1, fd_) != 1 ) goto error;
if ( fwrite(&hdr.sample_size, 2, 1, fd_) != 1 ) goto error;
if ( fwrite(&hdr.nChannels, 2, 1, fd_) != 1 ) goto error;
if ( fwrite(&hdr.sampleFrames, 4, 1, fd_) != 1 ) goto error;
if ( fwrite(&hdr.sampleSize, 2, 1, fd_) != 1 ) goto error;
if ( fwrite(&hdr.srate, 10, 1, fd_) != 1 ) goto error;
if ( dataType_ == STK_FLOAT32 ) {
@@ -454,12 +505,12 @@ bool FileWrite :: setAifFile( const char *fileName )
if ( fwrite(&ssnd, 4, 4, fd_) != 4 ) goto error;
errorString_ << "FileWrite: creating AIF file: " << name;
oStream_ << "FileWrite: creating AIF file: " << fileName;
handleError( StkError::STATUS );
return true;
error:
errorString_ << "FileWrite: could not write AIF header for file: " << name;
oStream_ << "FileWrite: could not write AIF header for file: " << fileName;
return false;
}
@@ -469,18 +520,20 @@ void FileWrite :: closeAifFile( void )
#ifdef __LITTLE_ENDIAN__
swap32((unsigned char *)&frames);
#endif
fseek(fd_, 22, SEEK_SET); // jump to "COMM" sample_frames
fseek(fd_, 22, SEEK_SET); // jump to "COMM" sampleFrames
fwrite(&frames, 4, 1, fd_);
int bytes_per_sample = 1;
int bytesPerSample = 1;
if ( dataType_ == STK_SINT16 )
bytes_per_sample = 2;
bytesPerSample = 2;
if ( dataType_ == STK_SINT24 )
bytesPerSample = 3;
else if ( dataType_ == STK_SINT32 || dataType_ == STK_FLOAT32 )
bytes_per_sample = 4;
bytesPerSample = 4;
else if ( dataType_ == STK_FLOAT64 )
bytes_per_sample = 8;
bytesPerSample = 8;
unsigned long bytes = frameCounter_ * bytes_per_sample * channels_ + 46;
unsigned long bytes = frameCounter_ * bytesPerSample * channels_ + 46;
if ( dataType_ == STK_FLOAT32 || dataType_ == STK_FLOAT64 ) bytes += 6;
#ifdef __LITTLE_ENDIAN__
swap32((unsigned char *)&bytes);
@@ -488,7 +541,7 @@ void FileWrite :: closeAifFile( void )
fseek(fd_, 4, SEEK_SET); // jump to file size
fwrite(&bytes, 4, 1, fd_);
bytes = frameCounter_ * bytes_per_sample * channels_ + 8;
bytes = frameCounter_ * bytesPerSample * channels_ + 8;
if ( dataType_ == STK_FLOAT32 || dataType_ == STK_FLOAT64 ) bytes += 6;
#ifdef __LITTLE_ENDIAN__
swap32((unsigned char *)&bytes);
@@ -502,28 +555,24 @@ void FileWrite :: closeAifFile( void )
fclose( fd_ );
}
bool FileWrite :: setMatFile( const char *fileName )
bool FileWrite :: setMatFile( std::string fileName )
{
char name[8192];
strncpy(name, fileName, 8192);
if ( strstr(name, ".mat") == NULL) strcat(name, ".mat");
fd_ = fopen(name, "w+b");
if ( fileName.find( ".mat" ) == std::string::npos ) fileName += ".mat";
fd_ = fopen( fileName.c_str(), "w+b" );
if ( !fd_ ) {
errorString_ << "FileWrite: could not create MAT file: " << name;
oStream_ << "FileWrite: could not create MAT file: " << fileName;
return false;
}
if ( dataType_ != STK_FLOAT64 ) {
dataType_ = STK_FLOAT64;
errorString_ << "FileWrite: using 64-bit floating-point data format for file " << name << '.';
handleError( StkError::DEBUG_WARNING );
oStream_ << "FileWrite: using 64-bit floating-point data format for file " << fileName << '.';
handleError( StkError::DEBUG_PRINT );
}
struct mathdr hdr;
strcpy(hdr.heading,"MATLAB 5.0 MAT-file, Generated using the Synthesis ToolKit in C++ (STK). By Perry R. Cook and Gary P. Scavone.");
int i;
for (i=strlen(hdr.heading);i<124;i++) hdr.heading[i] = ' ';
struct MatHeader hdr;
strcpy( hdr.heading,"MATLAB 5.0 MAT-file, Generated using the Synthesis ToolKit in C++ (STK). By Perry R. Cook and Gary P. Scavone." );
for ( int i=strlen(hdr.heading); i<124; i++ ) hdr.heading[i] = ' ';
// Header Flag Fields
hdr.hff[0] = (SINT16) 0x0100; // Version field
@@ -531,9 +580,34 @@ bool FileWrite :: setMatFile( const char *fileName )
hdr.hff[1] <<= 8;
hdr.hff[1] += 'I';
// Write sample rate in array data element
hdr.fs[0] = (SINT32) 14; // Matlab array data type value
hdr.fs[1] = (SINT32) 56; // Size of data element to follow (in bytes)
// Numeric Array Subelements (4):
// 1. Array Flags
hdr.fs[2] = (SINT32) 6; // Matlab 32-bit unsigned integer data type value
hdr.fs[3] = (SINT32) 8; // 8 bytes of data to follow
hdr.fs[4] = (SINT32) 6; // Double-precision array, no array flags set
hdr.fs[5] = (SINT32) 0; // 4 bytes undefined
// 2. Array Dimensions
hdr.fs[6] = (SINT32) 5; // Matlab 32-bit signed integer data type value
hdr.fs[7] = (SINT32) 8; // 8 bytes of data to follow (2D array)
hdr.fs[8] = (SINT32) 1; // 1 row
hdr.fs[9] = (SINT32) 1; // 1 column
// 3. Array Name (small data format element)
hdr.fs[10] = 0x00020001;
hdr.fs[11] = 's' << 8;
hdr.fs[11] += 'f';
// 4. Real Part
hdr.fs[12] = 9; // Matlab IEEE 754 double data type
hdr.fs[13] = 8; // 8 bytes of data to follow
FLOAT64 *sampleRate = (FLOAT64 *)&hdr.fs[14];
*sampleRate = (FLOAT64) Stk::sampleRate();
// Write audio samples in array data element
hdr.adf[0] = (SINT32) 14; // Matlab array data type value
hdr.adf[1] = (SINT32) 0; // Size of file after this point to end (in bytes)
// Don't know size yet.
// Numeric Array Subelements (4):
// 1. Array Flags
@@ -547,82 +621,83 @@ bool FileWrite :: setMatFile( const char *fileName )
hdr.adf[8] = (SINT32) channels_; // This is the number of rows
hdr.adf[9] = (SINT32) 0; // This is the number of columns
// 3. Array Name
// We'll use fileName for the matlab array name (as well as the file name).
// If fileName is 4 characters or less, we have to use a compressed data element
// format for the array name data element. Otherwise, the array name must
// be formatted in 8-byte increments (up to 31 characters + NULL).
SINT32 namelength = (SINT32) strlen(fileName);
if (strstr(fileName, ".mat")) namelength -= 4;
if (namelength > 31) namelength = 31; // Truncate name to 31 characters.
char arrayName[64];
strncpy(arrayName, fileName, namelength);
arrayName[namelength] = '\0';
if (namelength > 4) {
// 3. Array Name We'll use fileName for the matlab array name (as
// well as the file name), though we might need to strip off a
// leading directory path. If fileName is 4 characters or less, we
// have to use a small data format element for the array name data
// element. Otherwise, the array name must be formatted in 8-byte
// increments (up to 31 characters + NULL).
std::string name = fileName;
size_t found;
found = name.find_last_of("/\\");
name = name.substr(found+1);
SINT32 namelength = (SINT32) name.size() - 4; // strip off the ".mat" extension
if ( namelength > 31 ) namelength = 31; // Truncate name to 31 characters.
if ( namelength > 4 ) {
hdr.adf[10] = (SINT32) 1; // Matlab 8-bit signed integer data type value
}
else { // Compressed data element format
hdr.adf[10] = namelength;
hdr.adf[10] <<= 16;
hdr.adf[10] += 1;
hdr.adf[10] = (namelength << 16) + 1;
}
SINT32 headsize = 40; // Number of bytes in data element so far.
SINT32 headsize = 40; // Number of bytes in audio data element so far.
// Write the fixed portion of the header
if ( fwrite(&hdr, 172, 1, fd_) != 1 ) goto error;
if ( fwrite(&hdr, 236, 1, fd_) != 1 ) goto error;
// Write MATLAB array name
SINT32 tmp;
if (namelength > 4) {
if ( namelength > 4 ) {
if ( fwrite(&namelength, 4, 1, fd_) != 1) goto error;
if ( fwrite(arrayName, namelength, 1, fd_) != 1 ) goto error;
if ( fwrite(name.c_str(), namelength, 1, fd_) != 1 ) goto error;
tmp = (SINT32) ceil((float)namelength / 8);
if ( fseek(fd_, tmp*8-namelength, SEEK_CUR) == -1 ) goto error;
headsize += tmp * 8;
}
else { // Compressed data element format
if ( fwrite(arrayName, namelength, 1, fd_) != 1 ) goto error;
if ( fwrite(name.c_str(), namelength, 1, fd_) != 1 ) goto error;
tmp = 4 - namelength;
if ( fseek(fd_, tmp, SEEK_CUR) == -1 ) goto error;
}
// Finish writing known header information
//4. Real Part
tmp = 9; // Matlab IEEE 754 double data type
if ( fwrite(&tmp, 4, 1, fd_) != 1 ) goto error;
tmp = 0; // Size of real part subelement in bytes (8 per sample)
if ( fwrite(&tmp, 4, 1, fd_) != 1 ) goto error;
headsize += 8; // Total number of bytes in data element so far
if ( fseek(fd_, 132, SEEK_SET) == -1 ) goto error;
if ( fseek(fd_, 196, SEEK_SET) == -1 ) goto error;
if ( fwrite(&headsize, 4, 1, fd_) != 1 ) goto error; // Write header size ... will update at end
if ( fseek(fd_, 0, SEEK_END) == -1 ) goto error;
byteswap_ = false;
errorString_ << "FileWrite: creating MAT-file (" << name << ") containing MATLAB array: " << arrayName;
oStream_ << "FileWrite: creating MAT-file: " << fileName;
handleError( StkError::STATUS );
return true;
error:
errorString_ << "FileWrite: could not write MAT-file header for file " << name << '.';
oStream_ << "FileWrite: could not write MAT-file header for file " << fileName << '.';
return false;
}
void FileWrite :: closeMatFile( void )
{
fseek(fd_, 164, SEEK_SET); // jump to number of columns
fseek(fd_, 228, SEEK_SET); // jump to number of columns
fwrite(&frameCounter_, 4, 1, fd_);
SINT32 headsize, temp;
fseek(fd_, 132, SEEK_SET); // jump to header size
fseek(fd_, 196, SEEK_SET); // jump to header size
fread(&headsize, 4, 1, fd_);
temp = headsize;
headsize += (SINT32) (frameCounter_ * 8 * channels_);
fseek(fd_, 132, SEEK_SET);
fseek(fd_, 196, SEEK_SET);
// Write file size (minus some header info)
fwrite(&headsize, 4, 1, fd_);
fseek(fd_, temp+132, SEEK_SET); // jumpt to data size (in bytes)
fseek(fd_, temp+196, SEEK_SET); // jumpt to data size (in bytes)
temp = frameCounter_ * 8 * channels_;
fwrite(&temp, 4, 1, fd_);
@@ -632,13 +707,13 @@ void FileWrite :: closeMatFile( void )
void FileWrite :: write( StkFrames& buffer )
{
if ( fd_ == 0 ) {
errorString_ << "FileWrite::write(): a file has not yet been opened!";
oStream_ << "FileWrite::write(): a file has not yet been opened!";
handleError( StkError::WARNING );
return;
}
if ( buffer.channels() != channels_ ) {
errorString_ << "FileWrite::write(): number of channels in the StkFrames argument does not match that specified to open() function!";
oStream_ << "FileWrite::write(): number of channels in the StkFrames argument does not match that specified to open() function!";
handleError( StkError::FUNCTION_ARGUMENT );
return;
}
@@ -695,12 +770,25 @@ void FileWrite :: write( StkFrames& buffer )
if ( fwrite(&sample, 8, 1, fd_) != 1 ) goto error;
}
}
else if ( dataType_ == STK_SINT24 ) {
SINT32 sample;
for ( unsigned long k=0; k<nSamples; k++ ) {
sample = (SINT32) (buffer[k] * 8388607.0);
if ( byteswap_ ) {
swap32( (unsigned char *)&sample );
unsigned char *ptr = (unsigned char *) &sample;
if ( fwrite(ptr+1, 3, 1, fd_) != 1 ) goto error;
}
else
if ( fwrite(&sample, 3, 1, fd_) != 1 ) goto error;
}
}
frameCounter_ += buffer.frames();
return;
error:
errorString_ << "FileWrite::write(): error writing data to file!";
oStream_ << "FileWrite::write(): error writing data to file!";
handleError( StkError::FILE_ERROR );
}

View File

@@ -27,7 +27,7 @@
See the FileRead class for a description of the supported audio
file formats.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -37,7 +37,7 @@
namespace stk {
FileWvIn :: FileWvIn( unsigned long chunkThreshold, unsigned long chunkSize )
: finished_(true), interpolate_(false), time_(0.0),
: finished_(true), interpolate_(false), time_(0.0), rate_(0.0),
chunkThreshold_(chunkThreshold), chunkSize_(chunkSize)
{
Stk::addSampleRateAlert( this );
@@ -45,7 +45,7 @@ FileWvIn :: FileWvIn( unsigned long chunkThreshold, unsigned long chunkSize )
FileWvIn :: FileWvIn( std::string fileName, bool raw, bool doNormalize,
unsigned long chunkThreshold, unsigned long chunkSize )
: finished_(true), interpolate_(false), time_(0.0),
: finished_(true), interpolate_(false), time_(0.0), rate_(0.0),
chunkThreshold_(chunkThreshold), chunkSize_(chunkSize)
{
openFile( fileName, raw, doNormalize );
@@ -142,11 +142,6 @@ void FileWvIn :: normalize( StkFloat peak )
void FileWvIn :: setRate( StkFloat rate )
{
#if defined(_STK_DEBUG_)
errorString_ << "FileWvIn::setRate: changing file read rate from " << rate_ << " to " << rate << '.';
handleError( StkError::DEBUG_WARNING );
#endif
rate_ = rate;
// If negative rate and at beginning of sound, move pointer to end
@@ -174,7 +169,7 @@ StkFloat FileWvIn :: tick( unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= data_.channels() ) {
errorString_ << "FileWvIn::tick(): channel argument and soundfile data are incompatible!";
oStream_ << "FileWvIn::tick(): channel argument and soundfile data are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -231,8 +226,8 @@ StkFrames& FileWvIn :: tick( StkFrames& frames )
{
if ( !file_.isOpen() ) {
#if defined(_STK_DEBUG_)
errorString_ << "FileWvIn::tick(): no file data is loaded!";
handleError( StkError::DEBUG_WARNING );
oStream_ << "FileWvIn::tick(): no file data is loaded!";
handleError( StkError::DEBUG_PRINT );
#endif
return frames;
}
@@ -240,7 +235,7 @@ StkFrames& FileWvIn :: tick( StkFrames& frames )
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( nChannels != frames.channels() ) {
errorString_ << "FileWvIn::tick(): StkFrames argument is incompatible with file data!";
oStream_ << "FileWvIn::tick(): StkFrames argument is incompatible with file data!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif

View File

@@ -17,7 +17,7 @@
Currently, FileWvOut is non-interpolating and the output rate is
always Stk::sampleRate().
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -64,7 +64,7 @@ void FileWvOut :: openFile( std::string fileName,
closeFile();
if ( nChannels < 1 ) {
errorString_ << "FileWvOut::openFile: the channels argument must be greater than zero!";
oStream_ << "FileWvOut::openFile: the channels argument must be greater than zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -94,7 +94,7 @@ void FileWvOut :: tick( const StkFloat sample )
{
#if defined(_STK_DEBUG_)
if ( !file_.isOpen() ) {
errorString_ << "FileWvOut::tick(): no file open!";
oStream_ << "FileWvOut::tick(): no file open!";
handleError( StkError::WARNING );
return;
}
@@ -113,13 +113,13 @@ void FileWvOut :: tick( const StkFrames& frames )
{
#if defined(_STK_DEBUG_)
if ( !file_.isOpen() ) {
errorString_ << "FileWvOut::tick(): no file open!";
oStream_ << "FileWvOut::tick(): no file open!";
handleError( StkError::WARNING );
return;
}
if ( data_.channels() != frames.channels() ) {
errorString_ << "FileWvOut::tick(): incompatible channel value in StkFrames argument!";
oStream_ << "FileWvOut::tick(): incompatible channel value in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif

View File

@@ -16,11 +16,12 @@
This structure results in one extra multiply per computed sample,
but allows easy control of the overall filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
#include "Fir.h"
#include <cmath>
namespace stk {
@@ -36,7 +37,7 @@ Fir :: Fir( std::vector<StkFloat> &coefficients )
{
// Check the arguments.
if ( coefficients.size() == 0 ) {
errorString_ << "Fir: coefficient vector must have size > 0!";
oStream_ << "Fir: coefficient vector must have size > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -55,7 +56,7 @@ void Fir :: setCoefficients( std::vector<StkFloat> &coefficients, bool clearStat
{
// Check the argument.
if ( coefficients.size() == 0 ) {
errorString_ << "Fir::setCoefficients: coefficient vector must have size > 0!";
oStream_ << "Fir::setCoefficients: coefficient vector must have size > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}

View File

@@ -1,5 +1,5 @@
/***************************************************/
/*! \class Flute
/*! \Class Flute
\brief STK flute physical model class.
This class implements a simple flute
@@ -18,7 +18,7 @@
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -29,23 +29,22 @@ namespace stk {
Flute :: Flute( StkFloat lowestFrequency )
{
length_ = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
boreDelay_.setMaximumDelay( length_ );
boreDelay_.setDelay( 100.0 );
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Flute::Flute: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
jetDelay_.setMaximumDelay( length_ );
unsigned long nDelays = (unsigned long) ( Stk::sampleRate() / lowestFrequency );
boreDelay_.setMaximumDelay( nDelays + 1 );
jetDelay_.setMaximumDelay( nDelays + 1 );
jetDelay_.setDelay( 49.0 );
vibrato_.setFrequency( 5.925 );
this->clear();
filter_.setPole( 0.7 - ((StkFloat) 0.1 * 22050.0 / Stk::sampleRate() ) );
filter_.setGain( -1.0 );
filter_.setPole( 0.7 - ( 0.1 * 22050.0 / Stk::sampleRate() ) );
dcBlock_.setBlockZero();
adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010);
adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010 );
endReflection_ = 0.5;
jetReflection_ = 0.5;
noiseGain_ = 0.15; // Breath pressure random component.
@@ -53,7 +52,8 @@ Flute :: Flute( StkFloat lowestFrequency )
jetRatio_ = 0.32;
maxPressure_ = 0.0;
lastFrequency_ = 220.0;
this->clear();
this->setFrequency( 220.0 );
}
Flute :: ~Flute( void )
@@ -70,27 +70,39 @@ void Flute :: clear( void )
void Flute :: setFrequency( StkFloat frequency )
{
lastFrequency_ = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "Flute::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
lastFrequency_ = 220.0;
oStream_ << "Flute::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
// We're overblowing here.
lastFrequency_ *= 0.66666;
lastFrequency_ = frequency * 0.66666;
// delay = length - approximate filter delay.
StkFloat delay = Stk::sampleRate() / lastFrequency_ - (StkFloat) 2.0;
if ( delay <= 0.0 ) delay = 0.3;
else if ( delay > length_ ) delay = length_;
// Account for filter delay and one sample "lastOut" delay
// (previously approximated as 2.0 samples). The tuning is still
// not perfect but I'm not sure why. Also, we are not accounting
// for the dc blocking filter delay.
StkFloat delay = Stk::sampleRate() / lastFrequency_ - filter_.phaseDelay( lastFrequency_ ) - 1.0;
boreDelay_.setDelay(delay);
jetDelay_.setDelay(delay * jetRatio_);
boreDelay_.setDelay( delay );
jetDelay_.setDelay( delay * jetRatio_ );
}
void Flute :: setJetDelay( StkFloat aRatio )
{
jetRatio_ = aRatio;
jetDelay_.setDelay( boreDelay_.getDelay() * aRatio ); // Scaled by ratio.
}
void Flute :: startBlowing( StkFloat amplitude, StkFloat rate )
{
if ( amplitude <= 0.0 || rate <= 0.0 ) {
oStream_ << "Flute::startBlowing: one or more arguments is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
adsr_.setAttackRate( rate );
maxPressure_ = amplitude / (StkFloat) 0.8;
adsr_.keyOn();
@@ -98,6 +110,11 @@ void Flute :: startBlowing( StkFloat amplitude, StkFloat rate )
void Flute :: stopBlowing( StkFloat rate )
{
if ( rate <= 0.0 ) {
oStream_ << "Flute::stopBlowing: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
adsr_.setReleaseRate( rate );
adsr_.keyOff();
}
@@ -107,73 +124,39 @@ void Flute :: noteOn( StkFloat frequency, StkFloat amplitude )
this->setFrequency( frequency );
this->startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02 );
outputGain_ = amplitude + 0.001;
#if defined(_STK_DEBUG_)
errorString_ << "Flute::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Flute :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.02 );
#if defined(_STK_DEBUG_)
errorString_ << "Flute::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Flute :: setJetReflection( StkFloat coefficient )
{
jetReflection_ = coefficient;
}
void Flute :: setEndReflection( StkFloat coefficient )
{
endReflection_ = coefficient;
}
void Flute :: setJetDelay( StkFloat aRatio )
{
// Delay = length - approximate filter delay.
StkFloat temp = Stk::sampleRate() / lastFrequency_ - (StkFloat) 2.0;
jetRatio_ = aRatio;
jetDelay_.setDelay(temp * aRatio); // Scaled by ratio.
}
void Flute :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Flute::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Flute::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_JetDelay_) // 2
this->setJetDelay( (StkFloat) (0.08 + (0.48 * norm)) );
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = ( norm * 0.4);
else if (number == __SK_ModFrequency_) // 11
vibrato_.setFrequency( norm * 12.0);
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = ( norm * 0.4 );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( norm );
else {
errorString_ << "Flute::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Flute::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Flute::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_JetDelay_) // 2
this->setJetDelay( (StkFloat) (0.08 + (0.48 * normalizedValue)) );
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = ( normalizedValue * 0.4);
else if (number == __SK_ModFrequency_) // 11
vibrato_.setFrequency( normalizedValue * 12.0);
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = ( normalizedValue * 0.4 );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( normalizedValue );
#if defined(_STK_DEBUG_)
else {
oStream_ << "Flute::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -6,7 +6,7 @@
over time from one frequency setting to another. It provides
methods for controlling the sweep rate and target frequency.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -46,13 +46,24 @@ FormSwep :: ~FormSwep()
void FormSwep :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
{
if ( !ignoreSampleRateChange_ ) {
errorString_ << "FormSwep::sampleRateChanged: you may need to recompute filter coefficients!";
oStream_ << "FormSwep::sampleRateChanged: you may need to recompute filter coefficients!";
handleError( StkError::WARNING );
}
}
void FormSwep :: setResonance( StkFloat frequency, StkFloat radius )
{
#if defined(_STK_DEBUG_)
if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) {
oStream_ << "FormSwep::setResonance: frequency argument (" << frequency << ") is out of range!";
handleError( StkError::WARNING ); return;
}
if ( radius < 0.0 || radius >= 1.0 ) {
oStream_ << "FormSwep::setResonance: radius argument (" << radius << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
radius_ = radius;
frequency_ = frequency;
@@ -80,6 +91,15 @@ void FormSwep :: setStates( StkFloat frequency, StkFloat radius, StkFloat gain )
void FormSwep :: setTargets( StkFloat frequency, StkFloat radius, StkFloat gain )
{
if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) {
oStream_ << "FormSwep::setTargets: frequency argument (" << frequency << ") is out of range!";
handleError( StkError::WARNING ); return;
}
if ( radius < 0.0 || radius >= 1.0 ) {
oStream_ << "FormSwep::setTargets: radius argument (" << radius << ") is out of range!";
handleError( StkError::WARNING ); return;
}
dirty_ = true;
startFrequency_ = frequency_;
startRadius_ = radius_;
@@ -95,16 +115,22 @@ void FormSwep :: setTargets( StkFloat frequency, StkFloat radius, StkFloat gain
void FormSwep :: setSweepRate( StkFloat rate )
{
if ( rate < 0.0 || rate > 1.0 ) {
oStream_ << "FormSwep::setSweepRate: argument (" << rate << ") is out of range!";
handleError( StkError::WARNING ); return;
}
sweepRate_ = rate;
if ( sweepRate_ > 1.0 ) sweepRate_ = 1.0;
if ( sweepRate_ < 0.0 ) sweepRate_ = 0.0;
}
void FormSwep :: setSweepTime( StkFloat time )
{
sweepRate_ = 1.0 / ( time * Stk::sampleRate() );
if ( sweepRate_ > 1.0 ) sweepRate_ = 1.0;
if ( sweepRate_ < 0.0 ) sweepRate_ = 0.0;
if ( time <= 0.0 ) {
oStream_ << "FormSwep::setSweepTime: argument (" << time << ") must be > 0.0!";
handleError( StkError::WARNING ); return;
}
this->setSweepRate( 1.0 / ( time * Stk::sampleRate() ) );
}
} // stk namespace

View File

@@ -60,14 +60,14 @@ void Granulate :: setGrainParameters( unsigned int duration, unsigned int rampPe
gDuration_ = duration;
if ( gDuration_ == 0 ) {
gDuration_ = 1;
errorString_ << "Granulate::setGrainParameters: duration argument cannot be zero ... setting to 1 millisecond.";
oStream_ << "Granulate::setGrainParameters: duration argument cannot be zero ... setting to 1 millisecond.";
handleError( StkError::WARNING );
}
gRampPercent_ = rampPercent;
if ( gRampPercent_ > 100 ) {
gRampPercent_ = 100;
errorString_ << "Granulate::setGrainParameters: rampPercent argument cannot be greater than 100 ... setting to 100.";
oStream_ << "Granulate::setGrainParameters: rampPercent argument cannot be greater than 100 ... setting to 100.";
handleError( StkError::WARNING );
}
@@ -94,8 +94,9 @@ void Granulate :: openFile( std::string fileName, bool typeRaw )
this->reset();
#if defined(_STK_DEBUG_)
errorString_ << "Granulate::openFile: file = " << fileName << ", file frames = " << file.fileSize() << '.';
handleError( StkError::DEBUG_WARNING );
std::ostringstream message;
message << "Granulate::openFile: file = " << fileName << ", file frames = " << file.fileSize() << '.';
handleError( message.str(), StkError::DEBUG_PRINT );
#endif
}
@@ -120,8 +121,9 @@ void Granulate :: reset( void )
void Granulate :: setVoices( unsigned int nVoices )
{
#if defined(_STK_DEBUG_)
errorString_ << "Granulate::setVoices: nVoices = " << nVoices << ", existing voices = " << grains_.size() << '.';
handleError( StkError::DEBUG_WARNING );
std::ostringstream message;
message << "Granulate::setVoices: nVoices = " << nVoices << ", existing voices = " << grains_.size() << '.';
handleError( message.str(), StkError::DEBUG_PRINT );
#endif
unsigned int oldSize = grains_.size();
@@ -203,7 +205,7 @@ StkFloat Granulate :: tick( unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= data_.channels() ) {
errorString_ << "Granulate::tick(): channel argument and soundfile data are incompatible!";
oStream_ << "Granulate::tick(): channel argument and soundfile data are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif

View File

@@ -22,7 +22,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -70,11 +70,6 @@ void HevyMetl :: noteOn( StkFloat frequency, StkFloat amplitude )
gains_[3] = amplitude * fmGains_[68];
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
errorString_ << "HevyMetl::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace

View File

@@ -20,7 +20,7 @@
This structure results in one extra multiply per computed sample,
but allows easy control of the overall filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -42,12 +42,12 @@ Iir :: Iir( std::vector<StkFloat> &bCoefficients, std::vector<StkFloat> &aCoeffi
{
// Check the arguments.
if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) {
errorString_ << "Iir: a and b coefficient vectors must both have size > 0!";
oStream_ << "Iir: a and b coefficient vectors must both have size > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( aCoefficients[0] == 0.0 ) {
errorString_ << "Iir: a[0] coefficient cannot == 0!";
oStream_ << "Iir: a[0] coefficient cannot == 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -76,7 +76,7 @@ void Iir :: setNumerator( std::vector<StkFloat> &bCoefficients, bool clearState
{
// Check the argument.
if ( bCoefficients.size() == 0 ) {
errorString_ << "Iir::setNumerator: coefficient vector must have size > 0!";
oStream_ << "Iir::setNumerator: coefficient vector must have size > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -95,12 +95,12 @@ void Iir :: setDenominator( std::vector<StkFloat> &aCoefficients, bool clearStat
{
// Check the argument.
if ( aCoefficients.size() == 0 ) {
errorString_ << "Iir::setDenominator: coefficient vector must have size > 0!";
oStream_ << "Iir::setDenominator: coefficient vector must have size > 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( aCoefficients[0] == 0.0 ) {
errorString_ << "Iir::setDenominator: a[0] coefficient cannot == 0!";
oStream_ << "Iir::setDenominator: a[0] coefficient cannot == 0!";
handleError( StkError::FUNCTION_ARGUMENT );
}

View File

@@ -20,11 +20,12 @@
data type for the incoming stream is signed 16-bit integers,
though any of the defined StkFormats are permissible.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
#include "InetWvIn.h"
#include <sstream>
namespace stk {
@@ -47,7 +48,7 @@ InetWvIn :: InetWvIn( unsigned long bufferFrames, unsigned int nBuffers )
// Start the input thread.
if ( !thread_.start( &inputThread, &threadInfo_ ) ) {
errorString_ << "InetWvIn(): unable to start input thread in constructor!";
oStream_ << "InetWvIn(): unable to start input thread in constructor!";
handleError( StkError::PROCESS_THREAD );
}
}
@@ -70,7 +71,7 @@ void InetWvIn :: listen( int port, unsigned int nChannels,
if ( connected_ ) delete soket_;
if ( nChannels < 1 ) {
errorString_ << "InetWvIn()::listen(): the channel argument (" << nChannels << ") must be greater than zero.";
oStream_ << "InetWvIn()::listen(): the channel argument must be greater than zero.";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -79,7 +80,7 @@ void InetWvIn :: listen( int port, unsigned int nChannels,
else if ( format == STK_FLOAT64 ) dataBytes_ = 8;
else if ( format == STK_SINT8 ) dataBytes_ = 1;
else {
errorString_ << "InetWvIn(): unknown data type specified (" << format << ").";
oStream_ << "InetWvIn(): unknown data type specified!";
handleError( StkError::FUNCTION_ARGUMENT );
}
dataType_ = format;
@@ -101,14 +102,14 @@ void InetWvIn :: listen( int port, unsigned int nChannels,
if ( protocol == Socket::PROTO_TCP ) {
TcpServer *socket = new TcpServer( port );
errorString_ << "InetWvIn:listen(): waiting for TCP connection on port " << socket->port() << " ... ";
oStream_ << "InetWvIn:listen(): waiting for TCP connection on port " << socket->port() << " ... ";
handleError( StkError::STATUS );
fd_ = socket->accept();
if ( fd_ < 0) {
errorString_ << "InetWvIn::listen(): Error accepting TCP connection request!";
oStream_ << "InetWvIn::listen(): Error accepting TCP connection request!";
handleError( StkError::PROCESS_SOCKET );
}
errorString_ << "InetWvIn::listen(): TCP socket connection made!";
oStream_ << "InetWvIn::listen(): TCP socket connection made!";
handleError( StkError::STATUS );
soket_ = (Socket *) socket;
}
@@ -146,7 +147,7 @@ void InetWvIn :: receive( void )
int i = soket_->readBuffer( fd_, (void *)&buffer_[writePoint_], unfilled, 0 );
//int i = Socket::readBuffer( fd_, (void *)&buffer_[writePoint_], unfilled, 0 );
if ( i <= 0 ) {
errorString_ << "InetWvIn::receive(): the remote InetWvIn socket has closed.";
oStream_ << "InetWvIn::receive(): the remote InetWvIn socket has closed.";
handleError( StkError::STATUS );
connected_ = false;
mutex_.unlock();
@@ -261,15 +262,15 @@ StkFloat InetWvIn :: tick( unsigned int channel )
// If no connection and we've output all samples in the queue, return 0.0.
if ( !connected_ && bytesFilled_ == 0 && bufferCounter_ == 0 ) {
#if defined(_STK_DEBUG_)
errorString_ << "InetWvIn::tick(): a valid socket connection does not exist!";
handleError( StkError::DEBUG_WARNING );
oStream_ << "InetWvIn::tick(): a valid socket connection does not exist!";
handleError( StkError::DEBUG_PRINT );
#endif
return 0.0;
}
#if defined(_STK_DEBUG_)
if ( channel >= data_.channels() ) {
errorString_ << "InetWvIn::tick(): channel argument is incompatible with data stream!";
oStream_ << "InetWvIn::tick(): channel argument is incompatible with data stream!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -293,7 +294,7 @@ StkFrames& InetWvIn :: tick( StkFrames& frames )
{
#if defined(_STK_DEBUG_)
if ( data_.channels() != frames.channels() ) {
errorString_ << "InetWvIn::tick(): StkFrames argument is incompatible with streamed channels!";
oStream_ << "InetWvIn::tick(): StkFrames argument is incompatible with streamed channels!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -301,8 +302,8 @@ StkFrames& InetWvIn :: tick( StkFrames& frames )
// If no connection and we've output all samples in the queue, return.
if ( !connected_ && bytesFilled_ == 0 && bufferCounter_ == 0 ) {
#if defined(_STK_DEBUG_)
errorString_ << "InetWvIn::tick(): a valid socket connection does not exist!";
handleError( StkError::DEBUG_WARNING );
oStream_ << "InetWvIn::tick(): a valid socket connection does not exist!";
handleError( StkError::DEBUG_PRINT );
#endif
return frames;
}

View File

@@ -17,13 +17,14 @@
data type is signed 16-bit integers but any of the defined
StkFormats are permissible.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
#include "InetWvOut.h"
#include "TcpClient.h"
#include "UdpSocket.h"
#include <sstream>
namespace stk {
@@ -53,7 +54,7 @@ void InetWvOut :: connect( int port, Socket::ProtocolType protocol, std::string
disconnect();
if ( nChannels == 0 ) {
errorString_ << "InetWvOut::connect: the channel argument (" << nChannels << ") must be greater than zero!";
oStream_ << "InetWvOut::connect: the channel argument must be greater than zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -62,7 +63,7 @@ void InetWvOut :: connect( int port, Socket::ProtocolType protocol, std::string
else if ( format == STK_SINT32 || format == STK_FLOAT32 ) dataBytes_ = 4;
else if ( format == STK_FLOAT64 ) dataBytes_ = 8;
else {
errorString_ << "InetWvOut::connect: unknown data type specified (" << format << ").";
oStream_ << "InetWvOut::connect: unknown data type specified.";
handleError( StkError::FUNCTION_ARGUMENT );
}
dataType_ = format;
@@ -161,7 +162,7 @@ void InetWvOut :: writeData( unsigned long frames )
long bytes = dataBytes_ * samples;
if ( soket_->writeBuffer( (const void *)buffer_, bytes, 0 ) < 0 ) {
errorString_ << "InetWvOut: connection to socket server failed!";
oStream_ << "InetWvOut: connection to socket server failed!";
handleError( StkError::PROCESS_SOCKET );
}
}
@@ -182,8 +183,8 @@ void InetWvOut :: tick( const StkFloat sample )
{
if ( !soket_ || !soket_->isValid( soket_->id() ) ) {
#if defined(_STK_DEBUG_)
errorString_ << "InetWvOut::tick(): a valid socket connection does not exist!";
handleError( StkError::DEBUG_WARNING );
oStream_ << "InetWvOut::tick(): a valid socket connection does not exist!";
handleError( StkError::DEBUG_PRINT );
#endif
return;
}
@@ -201,15 +202,15 @@ void InetWvOut :: tick( const StkFrames& frames )
{
if ( !soket_ || !soket_->isValid( soket_->id() ) ) {
#if defined(_STK_DEBUG_)
errorString_ << "InetWvOut::tick(): a valid socket connection does not exist!";
handleError( StkError::DEBUG_WARNING );
oStream_ << "InetWvOut::tick(): a valid socket connection does not exist!";
handleError( StkError::DEBUG_PRINT );
#endif
return;
}
#if defined(_STK_DEBUG_)
if ( data_.channels() != frames.channels() ) {
errorString_ << "InetWvOut::tick(): incompatible channel value in StkFrames argument!";
oStream_ << "InetWvOut::tick(): incompatible channel value in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif

View File

@@ -2,14 +2,20 @@
/*! \class JCRev
\brief John Chowning's reverberator class.
This class takes a monophonic input signal and produces a stereo
output signal. It is derived from the CLM JCRev function, which
is based on the use of networks of simple allpass and comb delay
filters. This class implements three series allpass units,
followed by four parallel comb filters, and two decorrelation
delay lines in parallel at the output.
This class takes a monophonic input signal and
produces a stereo output signal. It is derived
from the CLM JCRev function, which is based on
the use of networks of simple allpass and comb
delay filters. This class implements three
series allpass units, followed by four parallel
comb filters, and two decorrelation delay lines
in parallel at the output.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
Although not in the original JC reverberator,
one-pole lowpass filters have been added inside
the feedback comb filters.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -20,10 +26,16 @@ namespace stk {
JCRev :: JCRev( StkFloat T60 )
{
if ( T60 <= 0.0 ) {
oStream_ << "JCRev::JCRev: argument (" << T60 << ") must be positive!";
handleError( StkError::FUNCTION_ARGUMENT );
}
lastFrame_.resize( 1, 2, 0.0 ); // resize lastFrame_ for stereo output
// Delay lengths for 44100 Hz sample rate.
int lengths[9] = {1777, 1847, 1993, 2137, 389, 127, 43, 211, 179};
// {1116, 1188, 1356, 1277, 1422, 1491, 1617, 1557} // FreeVerb comb delays
int lengths[9] = {1116, 1356, 1422, 1617, 225, 341, 441, 211, 179};
double scaler = Stk::sampleRate() / 44100.0;
int delay, i;
@@ -44,6 +56,7 @@ JCRev :: JCRev( StkFloat T60 )
for ( i=0; i<4; i++ ) {
combDelays_[i].setMaximumDelay( lengths[i] );
combDelays_[i].setDelay( lengths[i] );
combFilters_[i].setPole( 0.2 );
}
this->setT60( T60 );
@@ -73,6 +86,11 @@ void JCRev :: clear()
void JCRev :: setT60( StkFloat T60 )
{
if ( T60 <= 0.0 ) {
oStream_ << "JCRev::setT60: argument (" << T60 << ") must be positive!";
handleError( StkError::WARNING ); return;
}
for ( int i=0; i<4; i++ )
combCoefficient_[i] = pow(10.0, (-3.0 * combDelays_[i].getDelay() / (T60 * Stk::sampleRate())));
}
@@ -81,7 +99,7 @@ StkFrames& JCRev :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() - 1 ) {
errorString_ << "JCRev::tick(): channel and StkFrames arguments are incompatible!";
oStream_ << "JCRev::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -90,8 +108,7 @@ StkFrames& JCRev :: tick( StkFrames& frames, unsigned int channel )
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples = tick( *samples );
*samples++;
*samples = lastFrame_[1];
*(samples+1) = lastFrame_[1];
}
return frames;
@@ -101,7 +118,7 @@ StkFrames& JCRev :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int i
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() - 1 ) {
errorString_ << "JCRev::tick(): channel and StkFrames arguments are incompatible!";
oStream_ << "JCRev::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -110,8 +127,8 @@ StkFrames& JCRev :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int i
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
*oSamples++ = tick( *iSamples );
*oSamples = lastFrame_[1];
*oSamples = tick( *iSamples );
*(oSamples+1) = lastFrame_[1];
}
return iFrames;

View File

@@ -1,10 +1,10 @@
### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in
### libstk Makefile - for various flavors of unix
LIBRARY = libstk.a
SHAREDLIB = libstk.so
STATICLIB = libstk.a
SHAREDLIB = @sharedlib@
MAJOR = 4
RELEASE = 4.4.2
RELEASE = 4.4.3
AR = ar -rsc
RM = /bin/rm
@@ -20,11 +20,11 @@ OBJECTS = Stk.o Generator.o Noise.o Blit.o BlitSaw.o BlitSquare.o Granulate.o \
\
Effect.o PRCRev.o JCRev.o NRev.o \
Chorus.o Echo.o PitShift.o LentPitShift.o \
Function.o ReedTable.o JetTable.o BowTable.o \
Voicer.o Vector3D.o Sphere.o \
Function.o ReedTable.o JetTable.o BowTable.o Cubic.o \
Voicer.o Vector3D.o Sphere.o Twang.o \
\
Instrmnt.o Clarinet.o BlowHole.o Saxofony.o Flute.o Brass.o BlowBotl.o \
Bowed.o Plucked.o StifKarp.o Sitar.o PluckTwo.o Mandolin.o Mesh2D.o \
Bowed.o Plucked.o StifKarp.o Sitar.o Mandolin.o Mesh2D.o \
FM.o Rhodey.o Wurley.o TubeBell.o HevyMetl.o PercFlut.o BeeThree.o FMVoices.o \
Sampler.o Moog.o Simple.o Drummer.o Shakers.o \
Modal.o ModalBar.o BandedWG.o Resonate.o VoicForm.o Phonemes.o Whistle.o \
@@ -64,25 +64,24 @@ DEFS += -DRAWWAVE_PATH=\"$(RAWWAVES)\"
%.o : ../src/include/%.cpp
$(CC) $(CFLAGS) $(DEFS) -c $(<) -o $(OBJECT_PATH)/$@
all : $(LIBRARY)
all : $(STATICLIB)
$(LIBRARY) : $(OBJECTS)
$(RM) -f $(LIBRARY)
$(AR) $(LIBRARY) $(OBJECT_PATH)/*.o
$(STATICLIB) : $(OBJECTS)
$(RM) -f $(STATICLIB)
$(AR) $(STATICLIB) $(OBJECT_PATH)/*.o
$(SHAREDLIB).$(RELEASE) : $(OBJECTS)
$(SHAREDLIB) : $(OBJECTS)
$(RM) -f $(@) $(SHAREDLIB).$(MAJOR) $(SHAREDLIB)
$(CC) $(LDFLAGS) -fPIC -shared -o $(@) $(OBJECT_PATH)/*.o $(LIBS)
$(LN) -s $(SHAREDLIB).$(RELEASE) $(SHAREDLIB).$(MAJOR)
$(LN) -s $(SHAREDLIB).$(RELEASE) $(SHAREDLIB)
# $(CC) $(LDFLAGS) -fPIC -shared -Wl,-soname,$(SHAREDLIB).$(MAJOR) -o $(@) $(OBJECT_PATH)/*.o $(LIBS)
$(CC) $(LDFLAGS) -fPIC @libflags@ $(OBJECT_PATH)/*.o $(LIBS)
$(LN) -s @sharedname@ $(SHAREDLIB)
# $(LN) -s @sharedname@ $(SHAREDLIB).$(MAJOR)
$(OBJECTS) : Stk.h
clean :
$(RM) -f $(OBJECT_PATH)/*.o
$(RM) -f $(LIBRARY)
$(RM) -f $(SHAREDLIB)*
$(RM) -f $(STATICLIB)
$(RM) -f $(SHAREDLIB)* @sharedname@
$(RM) -f *~
$(RM) -fR *.dSYM

View File

@@ -2,19 +2,18 @@
/*! \class Mandolin
\brief STK mandolin instrument model class.
This class inherits from PluckTwo and uses
"commuted synthesis" techniques to model a
mandolin instrument.
This class uses two "twang" models and "commuted
synthesis" techniques to model a mandolin
instrument.
This is a digital waveguide model, making its
use possibly subject to patents held by
Stanford University, Yamaha, and others.
Commuted Synthesis, in particular, is covered
by patents, granted, pending, and/or
applied-for. All are assigned to the Board of
Trustees, Stanford University. For
information, contact the Office of Technology
Licensing, Stanford University.
use possibly subject to patents held by Stanford
University, Yamaha, and others. Commuted
Synthesis, in particular, is covered by patents,
granted, pending, and/or applied-for. All are
assigned to the Board of Trustees, Stanford
University. For information, contact the Office
of Technology Licensing, Stanford University.
Control Change Numbers:
- Body Size = 2
@@ -23,7 +22,7 @@
- String Detuning = 1
- Microphone Position = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -33,85 +32,66 @@
namespace stk {
Mandolin :: Mandolin( StkFloat lowestFrequency )
: PluckTwo( lowestFrequency )
{
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Mandolin::Mandolin: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
// Concatenate the STK rawwave path to the rawwave files
soundfile_[0] = new FileWvIn( (Stk::rawwavePath() + "mand1.raw").c_str(), true );
soundfile_[1] = new FileWvIn( (Stk::rawwavePath() + "mand2.raw").c_str(), true );
soundfile_[2] = new FileWvIn( (Stk::rawwavePath() + "mand3.raw").c_str(), true );
soundfile_[3] = new FileWvIn( (Stk::rawwavePath() + "mand4.raw").c_str(), true );
soundfile_[4] = new FileWvIn( (Stk::rawwavePath() + "mand5.raw").c_str(), true );
soundfile_[5] = new FileWvIn( (Stk::rawwavePath() + "mand6.raw").c_str(), true );
soundfile_[6] = new FileWvIn( (Stk::rawwavePath() + "mand7.raw").c_str(), true );
soundfile_[7] = new FileWvIn( (Stk::rawwavePath() + "mand8.raw").c_str(), true );
soundfile_[8] = new FileWvIn( (Stk::rawwavePath() + "mand9.raw").c_str(), true );
soundfile_[9] = new FileWvIn( (Stk::rawwavePath() + "mand10.raw").c_str(), true );
soundfile_[10] = new FileWvIn( (Stk::rawwavePath() + "mand11.raw").c_str(), true );
soundfile_[11] = new FileWvIn( (Stk::rawwavePath() + "mand12.raw").c_str(), true );
soundfile_[0].openFile( (Stk::rawwavePath() + "mand1.raw").c_str(), true );
soundfile_[1].openFile( (Stk::rawwavePath() + "mand2.raw").c_str(), true );
soundfile_[2].openFile( (Stk::rawwavePath() + "mand3.raw").c_str(), true );
soundfile_[3].openFile( (Stk::rawwavePath() + "mand4.raw").c_str(), true );
soundfile_[4].openFile( (Stk::rawwavePath() + "mand5.raw").c_str(), true );
soundfile_[5].openFile( (Stk::rawwavePath() + "mand6.raw").c_str(), true );
soundfile_[6].openFile( (Stk::rawwavePath() + "mand7.raw").c_str(), true );
soundfile_[7].openFile( (Stk::rawwavePath() + "mand8.raw").c_str(), true );
soundfile_[8].openFile( (Stk::rawwavePath() + "mand9.raw").c_str(), true );
soundfile_[9].openFile( (Stk::rawwavePath() + "mand10.raw").c_str(), true );
soundfile_[10].openFile( (Stk::rawwavePath() + "mand11.raw").c_str(), true );
soundfile_[11].openFile( (Stk::rawwavePath() + "mand12.raw").c_str(), true );
mic_ = 0;
dampTime_ = 0;
waveDone_ = soundfile_[mic_]->isFinished();
detuning_ = 0.995;
pluckAmplitude_ = 0.5;
strings_[0].setLowestFrequency( lowestFrequency );
strings_[1].setLowestFrequency( lowestFrequency );
this->setFrequency( 220.0 );
this->setPluckPosition( 0.4 );
}
Mandolin :: ~Mandolin( void )
{
for ( int i=0; i<12; i++ )
delete soundfile_[i];
}
void Mandolin :: pluck( StkFloat amplitude )
void Mandolin :: clear( void )
{
// This function gets interesting, because pluck
// may be longer than string length, so we just
// reset the soundfile and add in the pluck in
// the tick method.
soundfile_[mic_]->reset();
waveDone_ = false;
pluckAmplitude_ = amplitude;
if ( amplitude < 0.0 ) {
errorString_ << "Mandolin::pluck: amplitude parameter less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
pluckAmplitude_ = 0.0;
}
else if ( amplitude > 1.0 ) {
errorString_ << "Mandolin::pluck: amplitude parameter greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
pluckAmplitude_ = 1.0;
}
// Set the pick position, which puts zeroes at position * length.
combDelay_.setDelay( 0.5 * pluckPosition_ * lastLength_ );
dampTime_ = (long) lastLength_; // See tick method below.
strings_[0].clear();
strings_[1].clear();
}
void Mandolin :: pluck( StkFloat amplitude, StkFloat position )
void Mandolin :: setPluckPosition( StkFloat position )
{
// Pluck position puts zeroes at position * length.
pluckPosition_ = position;
if ( position < 0.0 ) {
std::cerr << "Mandolin::pluck: position parameter less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
pluckPosition_ = 0.0;
}
else if ( position > 1.0 ) {
errorString_ << "Mandolin::pluck: amplitude parameter greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
pluckPosition_ = 1.0;
if ( position < 0.0 || position > 1.0 ) {
std::cerr << "Mandolin::setPluckPosition: position parameter out of range!";
handleError( StkError::WARNING ); return;
}
this->pluck( amplitude );
strings_[0].setPluckPosition( position );
strings_[1].setPluckPosition( position );
}
void Mandolin :: noteOn( StkFloat frequency, StkFloat amplitude )
void Mandolin :: setDetune( StkFloat detune )
{
this->setFrequency( frequency );
this->pluck( amplitude );
if ( detune <= 0.0 ) {
oStream_ << "Mandolin::setDeturn: parameter is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#if defined(_STK_DEBUG_)
errorString_ << "Mandolin::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
detuning_ = detune;
strings_[1].setFrequency( frequency_ * detuning_ );
}
void Mandolin :: setBodySize( StkFloat size )
@@ -119,41 +99,87 @@ void Mandolin :: setBodySize( StkFloat size )
// Scale the commuted body response by its sample rate (22050).
StkFloat rate = size * 22050.0 / Stk::sampleRate();
for ( int i=0; i<12; i++ )
soundfile_[i]->setRate( rate );
soundfile_[i].setRate( rate );
}
void Mandolin :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "Mandolin::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
frequency_ = frequency;
strings_[0].setFrequency( frequency_ );
strings_[1].setFrequency( frequency_ * detuning_ );
}
void Mandolin :: pluck( StkFloat amplitude )
{
if ( amplitude < 0.0 || amplitude > 1.0 ) {
oStream_ << "Mandolin::pluck: amplitude parameter out of range!";
handleError( StkError::WARNING ); return;
}
soundfile_[mic_].reset();
pluckAmplitude_ = amplitude;
//strings_[0].setLoopGain( 0.97 + pluckAmplitude_ * 0.03 );
//strings_[1].setLoopGain( 0.97 + pluckAmplitude_ * 0.03 );
}
void Mandolin :: pluck( StkFloat amplitude, StkFloat position )
{
this->setPluckPosition( position );
this->pluck( amplitude );
}
void Mandolin :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
this->pluck( amplitude );
}
void Mandolin :: noteOff( StkFloat amplitude )
{
if ( amplitude < 0.0 || amplitude > 1.0 ) {
oStream_ << "Mandolin::noteOff: amplitude is out of range!";
handleError( StkError::WARNING ); return;
}
//strings_[0].setLoopGain( 0.97 + (1 - amplitude) * 0.03 );
//strings_[1].setLoopGain( 0.97 + (1 - amplitude) * 0.03 );
}
void Mandolin :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Mandolin::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Mandolin::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_BodySize_) // 2
this->setBodySize( norm * 2.0 );
else if (number == __SK_PickPosition_) // 4
this->setPluckPosition( norm );
else if (number == __SK_StringDamping_) // 11
this->setBaseLoopGain( 0.97 + (norm * 0.03));
else if (number == __SK_StringDetune_) // 1
this->setDetune( 1.0 - (norm * 0.1) );
else if (number == __SK_AfterTouch_Cont_) // 128
mic_ = (int) (norm * 11.0);
else {
errorString_ << "Mandolin::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Mandolin::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Mandolin::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if ( number == __SK_BodySize_ ) // 2
this->setBodySize( normalizedValue * 2.0 );
else if ( number == __SK_PickPosition_ ) // 4
this->setPluckPosition( normalizedValue );
else if ( number == __SK_StringDamping_ ) { // 11
strings_[0].setLoopGain( 0.97 + (normalizedValue * 0.03) );
strings_[1].setLoopGain( 0.97 + (normalizedValue * 0.03) );
}
else if ( number == __SK_StringDetune_ ) // 1
this->setDetune( 1.0 - (normalizedValue * 0.1) );
else if ( number == __SK_AfterTouch_Cont_ ) // 128
mic_ = (int) (normalizedValue * 11.0);
#if defined(_STK_DEBUG_)
else {
oStream_ << "Mandolin::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -29,27 +29,31 @@
namespace stk {
Mesh2D :: Mesh2D( short nX, short nY )
Mesh2D :: Mesh2D( unsigned short nX, unsigned short nY )
{
this->setNX(nX);
this->setNY(nY);
if ( nX == 0.0 || nY == 0.0 ) {
oStream_ << "Mesh2D::Mesh2D: one or more argument is equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
this->setNX( nX );
this->setNY( nY );
StkFloat pole = 0.05;
short i;
for (i=0; i<NYMAX; i++) {
unsigned short i;
for ( i=0; i<NYMAX; i++ ) {
filterY_[i].setPole( pole );
filterY_[i].setGain( 0.99 );
}
for (i=0; i<NXMAX; i++) {
for ( i=0; i<NXMAX; i++ ) {
filterX_[i].setPole( pole );
filterX_[i].setGain( 0.99 );
}
this->clearMesh();
counter_=0;
counter_ = 0;
xInput_ = 0;
yInput_ = 0;
}
@@ -62,26 +66,26 @@ void Mesh2D :: clear( void )
{
this->clearMesh();
short i;
for (i=0; i<NY_; i++)
unsigned short i;
for ( i=0; i<NY_; i++ )
filterY_[i].clear();
for (i=0; i<NX_; i++)
for ( i=0; i<NX_; i++ )
filterX_[i].clear();
counter_=0;
counter_ = 0;
}
void Mesh2D :: clearMesh( void )
{
int x, y;
for (x=0; x<NXMAX-1; x++) {
for (y=0; y<NYMAX-1; y++) {
for ( x=0; x<NXMAX-1; x++ ) {
for ( y=0; y<NYMAX-1; y++ ) {
v_[x][y] = 0;
}
}
for (x=0; x<NXMAX; x++) {
for (y=0; y<NYMAX; y++) {
for ( x=0; x<NXMAX; x++ ) {
for ( y=0; y<NYMAX; y++ ) {
vxp_[x][y] = 0;
vxm_[x][y] = 0;
@@ -105,8 +109,8 @@ StkFloat Mesh2D :: energy( void )
StkFloat t;
StkFloat e = 0;
if ( counter_ & 1 ) { // Ready for Mesh2D::tick1() to be called.
for (x=0; x<NX_; x++) {
for (y=0; y<NY_; y++) {
for ( x=0; x<NX_; x++ ) {
for ( y=0; y<NY_; y++ ) {
t = vxp1_[x][y];
e += t*t;
t = vxm1_[x][y];
@@ -119,8 +123,8 @@ StkFloat Mesh2D :: energy( void )
}
}
else { // Ready for Mesh2D::tick0() to be called.
for (x=0; x<NX_; x++) {
for (y=0; y<NY_; y++) {
for ( x=0; x<NX_; x++ ) {
for ( y=0; y<NY_; y++ ) {
t = vxp_[x][y];
e += t*t;
t = vxm_[x][y];
@@ -133,88 +137,66 @@ StkFloat Mesh2D :: energy( void )
}
}
return(e);
return e;
}
void Mesh2D :: setNX( short lenX )
void Mesh2D :: setNX( unsigned short lenX )
{
NX_ = lenX;
if ( lenX < 2 ) {
errorString_ << "Mesh2D::setNX(" << lenX << "): Minimum length is 2!";
handleError( StkError::WARNING );
NX_ = 2;
oStream_ << "Mesh2D::setNX(" << lenX << "): Minimum length is 2!";
handleError( StkError::WARNING ); return;
}
else if ( lenX > NXMAX ) {
errorString_ << "Mesh2D::setNX(" << lenX << "): Maximum length is " << NXMAX << '!';;
handleError( StkError::WARNING );
NX_ = NXMAX;
oStream_ << "Mesh2D::setNX(" << lenX << "): Maximum length is " << NXMAX << '!';
handleError( StkError::WARNING ); return;
}
NX_ = lenX;
}
void Mesh2D :: setNY( short lenY )
void Mesh2D :: setNY( unsigned short lenY )
{
NY_ = lenY;
if ( lenY < 2 ) {
errorString_ << "Mesh2D::setNY(" << lenY << "): Minimum length is 2!";
handleError( StkError::WARNING );
NY_ = 2;
oStream_ << "Mesh2D::setNY(" << lenY << "): Minimum length is 2!";
handleError( StkError::WARNING ); return;
}
else if ( lenY > NYMAX ) {
errorString_ << "Mesh2D::setNY(" << lenY << "): Maximum length is " << NXMAX << '!';;
handleError( StkError::WARNING );
NY_ = NYMAX;
oStream_ << "Mesh2D::setNY(" << lenY << "): Maximum length is " << NXMAX << '!';
handleError( StkError::WARNING ); return;
}
NY_ = lenY;
}
void Mesh2D :: setDecay( StkFloat decayFactor )
{
StkFloat gain = decayFactor;
if ( decayFactor < 0.0 ) {
errorString_ << "Mesh2D::setDecay: decayFactor value is less than 0.0!";
handleError( StkError::WARNING );
gain = 0.0;
}
else if ( decayFactor > 1.0 ) {
errorString_ << "Mesh2D::setDecay decayFactor value is greater than 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
if ( decayFactor < 0.0 || decayFactor > 1.0 ) {
oStream_ << "Mesh2D::setDecay: decayFactor is out of range!";
handleError( StkError::WARNING ); return;
}
int i;
for (i=0; i<NYMAX; i++)
filterY_[i].setGain( gain );
for ( i=0; i<NYMAX; i++ )
filterY_[i].setGain( decayFactor );
for (i=0; i<NXMAX; i++)
filterX_[i].setGain( gain );
filterX_[i].setGain( decayFactor );
}
void Mesh2D :: setInputPosition( StkFloat xFactor, StkFloat yFactor )
{
if ( xFactor < 0.0 ) {
errorString_ << "Mesh2D::setInputPosition xFactor value is less than 0.0!";
handleError( StkError::WARNING );
xInput_ = 0;
if ( xFactor < 0.0 || xFactor > 1.0 ) {
oStream_ << "Mesh2D::setInputPosition xFactor value is out of range!";
handleError( StkError::WARNING ); return;
}
else if ( xFactor > 1.0 ) {
errorString_ << "Mesh2D::setInputPosition xFactor value is greater than 1.0!";
handleError( StkError::WARNING );
xInput_ = NX_ - 1;
}
else
xInput_ = (short) (xFactor * (NX_ - 1));
if ( yFactor < 0.0 ) {
errorString_ << "Mesh2D::setInputPosition yFactor value is less than 0.0!";
handleError( StkError::WARNING );
yInput_ = 0;
if ( yFactor < 0.0 || yFactor > 1.0 ) {
oStream_ << "Mesh2D::setInputPosition yFactor value is out of range!";
handleError( StkError::WARNING ); return;
}
else if ( yFactor > 1.0 ) {
errorString_ << "Mesh2D::setInputPosition yFactor value is greater than 1.0!";
handleError( StkError::WARNING );
yInput_ = NY_ - 1;
}
else
yInput_ = (short) (yFactor * (NY_ - 1));
xInput_ = (unsigned short) (xFactor * (NX_ - 1));
yInput_ = (unsigned short) (yFactor * (NY_ - 1));
}
void Mesh2D :: noteOn( StkFloat frequency, StkFloat amplitude )
@@ -228,19 +210,11 @@ void Mesh2D :: noteOn( StkFloat frequency, StkFloat amplitude )
vxp_[xInput_][yInput_] += amplitude;
vyp_[xInput_][yInput_] += amplitude;
}
#if defined(_STK_DEBUG_)
errorString_ << "Mesh2D::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Mesh2D :: noteOff( StkFloat amplitude )
{
#if defined(_STK_DEBUG_)
errorString_ << "Mesh2D::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
return;
}
StkFloat Mesh2D :: inputTick( StkFloat input )
@@ -366,34 +340,27 @@ StkFloat Mesh2D :: tick1( void )
void Mesh2D :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Mesh2D::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Mesh2D::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == 2) // 2
this->setNX( (short) (norm * (NXMAX-2) + 2) );
else if (number == 4) // 4
this->setNY( (short) (norm * (NYMAX-2) + 2) );
else if (number == 11) // 11
this->setDecay( 0.9 + (norm * 0.1) );
else if (number == __SK_ModWheel_) // 1
this->setInputPosition( norm, norm );
else {
errorString_ << "Mesh2D::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Mesh2D::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Mesh2D::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if ( number == 2 ) // 2
this->setNX( (unsigned short) (normalizedValue * (NXMAX-2) + 2) );
else if ( number == 4 ) // 4
this->setNY( (unsigned short) (normalizedValue * (NYMAX-2) + 2) );
else if ( number == 11 ) // 11
this->setDecay( 0.9 + (normalizedValue * 0.1) );
else if ( number == __SK_ModWheel_ ) // 1
this->setInputPosition( normalizedValue, normalizedValue );
#if defined(_STK_DEBUG_)
else {
oStream_ << "Mesh2D::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -28,7 +28,7 @@
This class is primarily for use in STK example programs but it is
generic enough to work in many other contexts.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -85,11 +85,11 @@ bool Messager :: setScoreFile( const char* filename )
{
if ( data_.sources ) {
if ( data_.sources == STK_FILE ) {
errorString_ << "Messager::setScoreFile: already reading a scorefile!";
oStream_ << "Messager::setScoreFile: already reading a scorefile!";
handleError( StkError::WARNING );
}
else {
errorString_ << "Messager::setScoreFile: already reading realtime control input ... cannot do scorefile input too!";
oStream_ << "Messager::setScoreFile: already reading realtime control input ... cannot do scorefile input too!";
handleError( StkError::WARNING );
}
return false;
@@ -141,20 +141,20 @@ void Messager :: pushMessage( Skini::Message& message )
bool Messager :: startStdInput()
{
if ( data_.sources == STK_FILE ) {
errorString_ << "Messager::startStdInput: already reading a scorefile ... cannot do realtime control input too!";
oStream_ << "Messager::startStdInput: already reading a scorefile ... cannot do realtime control input too!";
handleError( StkError::WARNING );
return false;
}
if ( data_.sources & STK_STDIN ) {
errorString_ << "Messager::startStdInput: stdin input thread already started.";
oStream_ << "Messager::startStdInput: stdin input thread already started.";
handleError( StkError::WARNING );
return false;
}
// Start the stdin input thread.
if ( !stdinThread_.start( (THREAD_FUNCTION)&stdinHandler, &data_ ) ) {
errorString_ << "Messager::startStdInput: unable to start stdin input thread!";
oStream_ << "Messager::startStdInput: unable to start stdin input thread!";
handleError( StkError::WARNING );
return false;
}
@@ -208,7 +208,13 @@ void midiHandler( double timeStamp, std::vector<unsigned char> *bytes, void *ptr
if ( ( message.type != 0xC0 ) && ( message.type != 0xD0 ) ) {
if ( bytes->size() < 3 ) return;
message.intValues[1] = bytes->at(2);
message.floatValues[1] = (StkFloat) message.intValues[1];
if ( message.type == 0xE0 ) { // combine pithbend into single "14-bit" value
message.intValues[0] += message.intValues[1] <<= 7;
message.floatValues[0] = (StkFloat) message.intValues[0];
message.intValues[1] = 0;
}
else
message.floatValues[1] = (StkFloat) message.intValues[1];
}
while ( data->queue.size() >= data->queueLimit ) Stk::sleep( 50 );
@@ -221,13 +227,13 @@ void midiHandler( double timeStamp, std::vector<unsigned char> *bytes, void *ptr
bool Messager :: startMidiInput( int port )
{
if ( data_.sources == STK_FILE ) {
errorString_ << "Messager::startMidiInput: already reading a scorefile ... cannot do realtime control input too!";
oStream_ << "Messager::startMidiInput: already reading a scorefile ... cannot do realtime control input too!";
handleError( StkError::WARNING );
return false;
}
if ( data_.sources & STK_MIDI ) {
errorString_ << "Messager::startMidiInput: MIDI input already started.";
oStream_ << "Messager::startMidiInput: MIDI input already started.";
handleError( StkError::WARNING );
return false;
}
@@ -236,7 +242,7 @@ bool Messager :: startMidiInput( int port )
// (to allow the user to exit).
if ( !( data_.sources & STK_STDIN ) ) {
if ( this->startStdInput() == false ) {
errorString_ << "Messager::startMidiInput: unable to start input from stdin.";
oStream_ << "Messager::startMidiInput: unable to start input from stdin.";
handleError( StkError::WARNING );
return false;
}
@@ -249,7 +255,7 @@ bool Messager :: startMidiInput( int port )
else data_.midi->openPort( (unsigned int)port );
}
catch ( RtError &error ) {
errorString_ << "Messager::startMidiInput: error creating RtMidiIn instance (" << error.getMessage() << ").";
oStream_ << "Messager::startMidiInput: error creating RtMidiIn instance (" << error.getMessage() << ").";
handleError( StkError::WARNING );
return false;
}
@@ -261,13 +267,13 @@ bool Messager :: startMidiInput( int port )
bool Messager :: startSocketInput( int port )
{
if ( data_.sources == STK_FILE ) {
errorString_ << "Messager::startSocketInput: already reading a scorefile ... cannot do realtime control input too!";
oStream_ << "Messager::startSocketInput: already reading a scorefile ... cannot do realtime control input too!";
handleError( StkError::WARNING );
return false;
}
if ( data_.sources & STK_SOCKET ) {
errorString_ << "Messager::startSocketInput: socket input thread already started.";
oStream_ << "Messager::startSocketInput: socket input thread already started.";
handleError( StkError::WARNING );
return false;
}
@@ -280,7 +286,7 @@ bool Messager :: startSocketInput( int port )
return false;
}
errorString_ << "Socket server listening for connection(s) on port " << port << "...";
oStream_ << "Socket server listening for connection(s) on port " << port << "...";
handleError( StkError::STATUS );
// Initialize socket descriptor information.
@@ -291,7 +297,7 @@ bool Messager :: startSocketInput( int port )
// Start the socket thread.
if ( !socketThread_.start( (THREAD_FUNCTION)&socketHandler, &data_ ) ) {
errorString_ << "Messager::startSocketInput: unable to start socket input thread!";
oStream_ << "Messager::startSocketInput: unable to start socket input thread!";
handleError( StkError::WARNING );
return false;
}

View File

@@ -26,7 +26,7 @@ MidiFileIn :: MidiFileIn( std::string fileName )
// Attempt to open the file.
file_.open( fileName.c_str(), std::ios::in | std::ios::binary );
if ( !file_ ) {
errorString_ << "MidiFileIn: error opening or finding file (" << fileName << ").";
oStream_ << "MidiFileIn: error opening or finding file (" << fileName << ").";
handleError( StkError::FILE_NOT_FOUND );
}
@@ -41,7 +41,7 @@ MidiFileIn :: MidiFileIn( std::string fileName )
#endif
length = (SINT32 *) &buffer;
if ( strncmp( chunkType, "MThd", 4 ) || ( *length != 6 ) ) {
errorString_ << "MidiFileIn: file (" << fileName << ") does not appear to be a MIDI file!";
oStream_ << "MidiFileIn: file (" << fileName << ") does not appear to be a MIDI file!";
handleError( StkError::FILE_UNKNOWN_FORMAT );
}
@@ -53,7 +53,7 @@ MidiFileIn :: MidiFileIn( std::string fileName )
#endif
data = (SINT16 *) &buffer;
if ( *data < 0 || *data > 2 ) {
errorString_ << "MidiFileIn: the file (" << fileName << ") format is invalid!";
oStream_ << "MidiFileIn: the file (" << fileName << ") format is invalid!";
handleError( StkError::FILE_ERROR );
}
format_ = *data;
@@ -64,7 +64,7 @@ MidiFileIn :: MidiFileIn( std::string fileName )
swap16((unsigned char *)&buffer);
#endif
if ( format_ == 0 && *data != 1 ) {
errorString_ << "MidiFileIn: invalid number of tracks (>1) for a file format = 0!";
oStream_ << "MidiFileIn: invalid number of tracks (>1) for a file format = 0!";
handleError( StkError::FILE_ERROR );
}
nTracks_ = *data;
@@ -153,7 +153,7 @@ MidiFileIn :: MidiFileIn( std::string fileName )
return;
error:
errorString_ << "MidiFileIn: error reading from file (" << fileName << ").";
oStream_ << "MidiFileIn: error reading from file (" << fileName << ").";
handleError( StkError::FILE_ERROR );
}
@@ -164,26 +164,11 @@ MidiFileIn :: ~MidiFileIn()
file_.close();
}
int MidiFileIn :: getFileFormat() const
{
return format_;
}
unsigned int MidiFileIn :: getNumberOfTracks() const
{
return nTracks_;
}
int MidiFileIn :: getDivision() const
{
return division_;
}
void MidiFileIn :: rewindTrack( unsigned int track )
{
if ( track >= nTracks_ ) {
errorString_ << "MidiFileIn::getNextEvent: invalid track argument (" << track << ").";
handleError( StkError::FUNCTION_ARGUMENT );
oStream_ << "MidiFileIn::getNextEvent: invalid track argument (" << track << ").";
handleError( StkError::WARNING ); return;
}
trackPointers_[track] = trackOffsets_[track];
@@ -195,8 +180,8 @@ double MidiFileIn :: getTickSeconds( unsigned int track )
{
// Return the current tick value in seconds for the given track.
if ( track >= nTracks_ ) {
errorString_ << "MidiFileIn::getTickSeconds: invalid track argument (" << track << ").";
handleError( StkError::FUNCTION_ARGUMENT );
oStream_ << "MidiFileIn::getTickSeconds: invalid track argument (" << track << ").";
handleError( StkError::WARNING ); return 0.0;
}
return tickSeconds_[track];
@@ -218,12 +203,12 @@ unsigned long MidiFileIn :: getNextEvent( std::vector<unsigned char> *event, uns
// running sum of ticks for each track and update the tickSeconds_
// parameter as needed based on the stored tempo map.
event->clear();
if ( track >= nTracks_ ) {
errorString_ << "MidiFileIn::getNextEvent: invalid track argument (" << track << ").";
handleError( StkError::FUNCTION_ARGUMENT );
oStream_ << "MidiFileIn::getNextEvent: invalid track argument (" << track << ").";
handleError( StkError::WARNING ); return 0;
}
event->clear();
// Check for the end of the track.
if ( (trackPointers_[track] - trackOffsets_[track]) >= trackLengths_[track] )
return 0;
@@ -314,7 +299,7 @@ unsigned long MidiFileIn :: getNextEvent( std::vector<unsigned char> *event, uns
return ticks;
error:
errorString_ << "MidiFileIn::getNextEvent: file read error!";
oStream_ << "MidiFileIn::getNextEvent: file read error!";
handleError( StkError::FILE_ERROR );
return 0;
}
@@ -325,8 +310,8 @@ unsigned long MidiFileIn :: getNextMidiEvent( std::vector<unsigned char> *midiEv
// specified track (default = 0) and return the event delta time in
// ticks. Meta-Events preceeding this event are skipped and ignored.
if ( track >= nTracks_ ) {
errorString_ << "MidiFileIn::getNextMidiEvent: invalid track argument (" << track << ").";
handleError( StkError::FUNCTION_ARGUMENT );
oStream_ << "MidiFileIn::getNextMidiEvent: invalid track argument (" << track << ").";
handleError( StkError::WARNING ); return 0;
}
unsigned long ticks = getNextEvent( midiEvent, track );

View File

@@ -7,7 +7,7 @@
(non-sweeping BiQuad filters), where N is set
during instantiation.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -20,7 +20,7 @@ Modal :: Modal( unsigned int modes )
: nModes_(modes)
{
if ( nModes_ == 0 ) {
errorString_ << "Modal: 'modes' argument to constructor is zero!";
oStream_ << "Modal: 'modes' argument to constructor is zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -65,6 +65,13 @@ void Modal :: clear( void )
void Modal :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "Modal::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
baseFrequency_ = frequency;
for ( unsigned int i=0; i<nModes_; i++ )
this->setRatioAndRadius( i, ratios_[i], radii_[i] );
@@ -73,9 +80,8 @@ void Modal :: setFrequency( StkFloat frequency )
void Modal :: setRatioAndRadius( unsigned int modeIndex, StkFloat ratio, StkFloat radius )
{
if ( modeIndex >= nModes_ ) {
errorString_ << "Modal::setRatioAndRadius: modeIndex parameter is greater than number of modes!";
handleError( StkError::WARNING );
return;
oStream_ << "Modal::setRatioAndRadius: modeIndex parameter is greater than number of modes!";
handleError( StkError::WARNING ); return;
}
StkFloat nyquist = Stk::sampleRate() / 2.0;
@@ -89,8 +95,8 @@ void Modal :: setRatioAndRadius( unsigned int modeIndex, StkFloat ratio, StkFloa
while (temp * baseFrequency_ > nyquist) temp *= 0.5;
ratios_[modeIndex] = temp;
#if defined(_STK_DEBUG_)
errorString_ << "Modal::setRatioAndRadius: aliasing would occur here ... correcting.";
handleError( StkError::DEBUG_WARNING );
oStream_ << "Modal::setRatioAndRadius: aliasing would occur here ... correcting.";
handleError( StkError::DEBUG_PRINT );
#endif
}
radii_[modeIndex] = radius;
@@ -105,9 +111,8 @@ void Modal :: setRatioAndRadius( unsigned int modeIndex, StkFloat ratio, StkFloa
void Modal :: setModeGain( unsigned int modeIndex, StkFloat gain )
{
if ( modeIndex >= nModes_ ) {
errorString_ << "Modal::setModeGain: modeIndex parameter is greater than number of modes!";
handleError( StkError::WARNING );
return;
oStream_ << "Modal::setModeGain: modeIndex parameter is greater than number of modes!";
handleError( StkError::WARNING ); return;
}
filters_[modeIndex]->setGain( gain );
@@ -115,21 +120,14 @@ void Modal :: setModeGain( unsigned int modeIndex, StkFloat gain )
void Modal :: strike( StkFloat amplitude )
{
StkFloat gain = amplitude;
if ( amplitude < 0.0 ) {
errorString_ << "Modal::strike: amplitude is less than zero ... setting to zero!";
if ( amplitude < 0.0 || amplitude > 1.0 ) {
oStream_ << "Modal::strike: amplitude is out of range!";
handleError( StkError::WARNING );
gain = 0.0;
}
else if ( amplitude > 1.0 ) {
errorString_ << "Modal::strike: amplitude is greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
}
envelope_.setRate( 1.0 );
envelope_.setTarget( gain );
onepole_.setPole( 1.0 - gain );
envelope_.setTarget( amplitude );
onepole_.setPole( 1.0 - amplitude );
envelope_.tick();
wave_->reset();
@@ -145,13 +143,8 @@ void Modal :: strike( StkFloat amplitude )
void Modal :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->strike(amplitude);
this->setFrequency(frequency);
#if defined(_STK_DEBUG_)
errorString_ << "Modal::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
this->strike( amplitude );
this->setFrequency( frequency );
}
void Modal :: noteOff( StkFloat amplitude )
@@ -159,11 +152,6 @@ void Modal :: noteOff( StkFloat amplitude )
// This calls damp, but inverts the meaning of amplitude (high
// amplitude means fast damping).
this->damp( 1.0 - (amplitude * 0.03) );
#if defined(_STK_DEBUG_)
errorString_ << "Modal::NoteOff: amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Modal :: damp( StkFloat amplitude )

View File

@@ -24,7 +24,7 @@
- Two Fixed = 7
- Clump = 8
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -52,35 +52,24 @@ ModalBar :: ~ModalBar( void )
void ModalBar :: setStickHardness( StkFloat hardness )
{
stickHardness_ = hardness;
if ( hardness < 0.0 ) {
errorString_ << "ModalBar::setStickHardness: parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
stickHardness_ = 0.0;
}
else if ( hardness > 1.0 ) {
errorString_ << "ModalBar::setStickHarness: parameter is greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
stickHardness_ = 1.0;
if ( hardness < 0.0 || hardness > 1.0 ) {
oStream_ << "ModalBar::setStickHardness: parameter is out of range!";
handleError( StkError::WARNING ); return;
}
stickHardness_ = hardness;
wave_->setRate( (0.25 * pow(4.0, stickHardness_) ) );
masterGain_ = 0.1 + (1.8 * stickHardness_);
}
void ModalBar :: setStrikePosition( StkFloat position )
{
if ( position < 0.0 || position > 1.0 ) {
oStream_ << "ModalBar::setStrikePosition: parameter is out of range!";
handleError( StkError::WARNING ); return;
}
strikePosition_ = position;
if ( position < 0.0 ) {
errorString_ << "ModalBar::setStrikePosition: parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
strikePosition_ = 0.0;
}
else if ( position > 1.0 ) {
errorString_ << "ModalBar::setStrikePosition: parameter is greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
strikePosition_ = 1.0;
}
// Hack only first three modes.
StkFloat temp2 = position * PI;
@@ -160,40 +149,33 @@ void ModalBar :: setPreset( int preset )
void ModalBar :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "ModalBar::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "ModalBar::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
#if defined(_STK_DEBUG_)
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "ModalBar::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_StickHardness_) // 2
this->setStickHardness( norm );
this->setStickHardness( normalizedValue );
else if (number == __SK_StrikePosition_) // 4
this->setStrikePosition( norm );
this->setStrikePosition( normalizedValue );
else if (number == __SK_ProphesyRibbon_) // 16
this->setPreset((int) value);
else if (number == __SK_Balance_) // 8
vibratoGain_ = norm * 0.3;
vibratoGain_ = normalizedValue * 0.3;
else if (number == __SK_ModWheel_) // 1
directGain_ = norm;
directGain_ = normalizedValue;
else if (number == __SK_ModFrequency_) // 11
vibrato_.setFrequency( norm * 12.0 );
vibrato_.setFrequency( normalizedValue * 12.0 );
else if (number == __SK_AfterTouch_Cont_) // 128
envelope_.setTarget( norm );
envelope_.setTarget( normalizedValue );
#if defined(_STK_DEBUG_)
else {
errorString_ << "ModalBar::controlChange: undefined control number (" << number << ")!";
oStream_ << "ModalBar::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "ModalBar::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -6,7 +6,7 @@
modulations to give a nice, natural human
modulation function.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/

View File

@@ -14,7 +14,7 @@
- Vibrato Gain = 1
- Gain = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -46,13 +46,14 @@ Moog :: ~Moog( void )
void Moog :: setFrequency( StkFloat frequency )
{
baseFrequency_ = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "Moog::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
baseFrequency_ = 220.0;
oStream_ << "Moog::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
baseFrequency_ = frequency;
StkFloat rate = attacks_[0]->getSize() * 0.01 * baseFrequency_ / Stk::sampleRate();
attacks_[0]->setRate( rate );
loops_[0]->setFrequency( baseFrequency_ );
@@ -77,45 +78,33 @@ void Moog :: noteOn( StkFloat frequency, StkFloat amplitude )
filters_[0].setSweepRate( filterRate_ * 22050.0 / Stk::sampleRate() );
filters_[1].setSweepRate( filterRate_ * 22050.0 / Stk::sampleRate() );
#if defined(_STK_DEBUG_)
errorString_ << "Moog::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Moog :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Moog::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Moog::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_FilterQ_) // 2
filterQ_ = 0.80 + ( 0.1 * norm );
else if (number == __SK_FilterSweepRate_) // 4
filterRate_ = norm * 0.0002;
else if (number == __SK_ModFrequency_) // 11
this->setModulationSpeed( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
this->setModulationDepth( norm );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( norm );
else {
errorString_ << "Moog::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Moog::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Moog::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_FilterQ_) // 2
filterQ_ = 0.80 + ( 0.1 * normalizedValue );
else if (number == __SK_FilterSweepRate_) // 4
filterRate_ = normalizedValue * 0.0002;
else if (number == __SK_ModFrequency_) // 11
this->setModulationSpeed( normalizedValue * 12.0 );
else if (number == __SK_ModWheel_) // 1
this->setModulationDepth( normalizedValue );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( normalizedValue );
#if defined(_STK_DEBUG_)
else {
oStream_ << "Moog::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -7,7 +7,7 @@
systems, the pthread library is used. Under
Windows, critical sections are used.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/

View File

@@ -10,7 +10,7 @@
another allpass in series, followed by two allpass filters in
parallel with corresponding right and left outputs.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -21,6 +21,11 @@ namespace stk {
NRev :: NRev( StkFloat T60 )
{
if ( T60 <= 0.0 ) {
oStream_ << "NRev::NRev: argument (" << T60 << ") must be positive!";
handleError( StkError::FUNCTION_ARGUMENT );
}
lastFrame_.resize( 1, 2, 0.0 ); // resize lastFrame_ for stereo output
int lengths[15] = {1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19};
@@ -63,6 +68,11 @@ void NRev :: clear()
void NRev :: setT60( StkFloat T60 )
{
if ( T60 <= 0.0 ) {
oStream_ << "NRev::setT60: argument (" << T60 << ") must be positive!";
handleError( StkError::WARNING ); return;
}
for ( int i=0; i<6; i++ )
combCoefficient_[i] = pow(10.0, (-3.0 * combDelays_[i].getDelay() / (T60 * Stk::sampleRate())));
}
@@ -71,7 +81,7 @@ StkFrames& NRev :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() - 1 ) {
errorString_ << "NRev::tick(): channel and StkFrames arguments are incompatible!";
oStream_ << "NRev::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -80,8 +90,7 @@ StkFrames& NRev :: tick( StkFrames& frames, unsigned int channel )
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples = tick( *samples );
samples++;
*samples = lastFrame_[1];
*(samples+1) = lastFrame_[1];
}
return frames;
@@ -91,7 +100,7 @@ StkFrames& NRev :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iC
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() - 1 ) {
errorString_ << "NRev::tick(): channel and StkFrames arguments are incompatible!";
oStream_ << "NRev::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -100,8 +109,8 @@ StkFrames& NRev :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iC
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
*oSamples++ = tick( *iSamples );
*oSamples = lastFrame_[1];
*oSamples = tick( *iSamples );
*(oSamples+1) = lastFrame_[1];
}
return iFrames;

View File

@@ -6,7 +6,7 @@
C rand() function. The quality of the rand()
function varies from one OS to another.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/

View File

@@ -6,7 +6,7 @@
provided for setting the pole position along the real axis of the
z-plane while maintaining a constant peak filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -18,6 +18,7 @@ OnePole :: OnePole( StkFloat thePole )
{
b_.resize( 1 );
a_.resize( 2 );
a_[0] = 1.0;
inputs_.resize( 1, 1, 0.0 );
outputs_.resize( 2, 1, 0.0 );
@@ -30,6 +31,11 @@ OnePole :: ~OnePole()
void OnePole :: setPole( StkFloat thePole )
{
if ( std::abs( thePole ) >= 1.0 ) {
oStream_ << "OnePole::setPole: argument (" << thePole << ") should be less than 1.0!";
handleError( StkError::WARNING ); return;
}
// Normalize coefficients for peak unity gain.
if ( thePole > 0.0 )
b_[0] = (StkFloat) (1.0 - thePole);
@@ -41,6 +47,11 @@ void OnePole :: setPole( StkFloat thePole )
void OnePole :: setCoefficients( StkFloat b0, StkFloat a1, bool clearState )
{
if ( std::abs( a1 ) >= 1.0 ) {
oStream_ << "OnePole::setCoefficients: a1 argument (" << a1 << ") should be less than 1.0!";
handleError( StkError::WARNING ); return;
}
b_[0] = b0;
a_[1] = a1;

View File

@@ -6,11 +6,12 @@
provided for setting the zero position along the real axis of the
z-plane while maintaining a constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
#include "OneZero.h"
#include <cmath>
namespace stk {

View File

@@ -10,7 +10,7 @@
two series allpass units and two parallel comb
filters.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -21,10 +21,15 @@ namespace stk {
PRCRev :: PRCRev( StkFloat T60 )
{
if ( T60 <= 0.0 ) {
oStream_ << "PRCRev::PRCRev: argument (" << T60 << ") must be positive!";
handleError( StkError::FUNCTION_ARGUMENT );
}
lastFrame_.resize( 1, 2, 0.0 ); // resize lastFrame_ for stereo output
// Delay lengths for 44100 Hz sample rate.
int lengths[4]= {353, 1097, 1777, 2137};
int lengths[4]= {341, 613, 1557, 2137};
double scaler = Stk::sampleRate() / 44100.0;
// Scale the delay lengths if necessary.
@@ -64,6 +69,11 @@ void PRCRev :: clear( void )
void PRCRev :: setT60( StkFloat T60 )
{
if ( T60 <= 0.0 ) {
oStream_ << "PRCRev::setT60: argument (" << T60 << ") must be positive!";
handleError( StkError::WARNING ); return;
}
combCoefficient_[0] = pow(10.0, (-3.0 * combDelays_[0].getDelay() / (T60 * Stk::sampleRate())));
combCoefficient_[1] = pow(10.0, (-3.0 * combDelays_[1].getDelay() / (T60 * Stk::sampleRate())));
}
@@ -72,7 +82,7 @@ StkFrames& PRCRev :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() - 1 ) {
errorString_ << "PRCRev::tick(): channel and StkFrames arguments are incompatible!";
oStream_ << "PRCRev::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -81,8 +91,7 @@ StkFrames& PRCRev :: tick( StkFrames& frames, unsigned int channel )
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples = tick( *samples );
*samples++;
*samples = lastFrame_[1];
*(samples+1) = lastFrame_[1];
}
return frames;
@@ -92,7 +101,7 @@ StkFrames& PRCRev :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() - 1 ) {
errorString_ << "PRCRev::tick(): channel and StkFrames arguments are incompatible!";
oStream_ << "PRCRev::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -101,8 +110,8 @@ StkFrames& PRCRev :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
*oSamples++ = tick( *iSamples );
*oSamples = lastFrame_[1];
*oSamples = tick( *iSamples );
*(oSamples+1) = lastFrame_[1];
}
return iFrames;

View File

@@ -22,7 +22,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -62,6 +62,13 @@ PercFlut :: ~PercFlut( void )
void PercFlut :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "PercFlut::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
baseFrequency_ = frequency;
}
@@ -73,11 +80,6 @@ void PercFlut :: noteOn( StkFloat frequency, StkFloat amplitude )
gains_[3] = amplitude * fmGains_[85] * 0.5;
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
errorString_ << "PercFlut::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace

View File

@@ -6,7 +6,7 @@
set of 32 static phoneme formant parameters
and provide access to those values.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -217,9 +217,8 @@ Phonemes :: ~Phonemes(void)
const char *Phonemes :: name( unsigned int index )
{
if ( index > 31 ) {
std::ostringstream error;
error << "Phonemes::name: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
oStream_ << "Phonemes::name: index is greater than 31!";
handleError( oStream_.str(), StkError::WARNING );
return 0;
}
return phonemeNames[index];
@@ -228,9 +227,8 @@ const char *Phonemes :: name( unsigned int index )
StkFloat Phonemes :: voiceGain( unsigned int index )
{
if ( index > 31 ) {
std::ostringstream error;
error << "Phonemes::voiceGain: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
oStream_ << "Phonemes::voiceGain: index is greater than 31!";
handleError( oStream_.str(), StkError::WARNING );
return 0.0;
}
return phonemeGains[index][0];
@@ -239,9 +237,8 @@ StkFloat Phonemes :: voiceGain( unsigned int index )
StkFloat Phonemes :: noiseGain( unsigned int index )
{
if ( index > 31 ) {
std::ostringstream error;
error << "Phonemes::noiseGain: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
oStream_ << "Phonemes::noiseGain: index is greater than 31!";
handleError( oStream_.str(), StkError::WARNING );
return 0.0;
}
return phonemeGains[index][1];
@@ -249,15 +246,14 @@ StkFloat Phonemes :: noiseGain( unsigned int index )
StkFloat Phonemes :: formantFrequency( unsigned int index, unsigned int partial )
{
std::ostringstream error;
if ( index > 31 ) {
error << "Phonemes::formantFrequency: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
oStream_ << "Phonemes::formantFrequency: index is greater than 31!";
handleError( oStream_.str(), StkError::WARNING );
return 0.0;
}
if ( partial > 3 ) {
error << "Phonemes::formantFrequency: partial is greater than 3!";
handleError( error.str(), StkError::WARNING );
oStream_ << "Phonemes::formantFrequency: partial is greater than 3!";
handleError( oStream_.str(), StkError::WARNING );
return 0.0;
}
return phonemeParameters[index][partial][0];
@@ -265,15 +261,14 @@ StkFloat Phonemes :: formantFrequency( unsigned int index, unsigned int partial
StkFloat Phonemes :: formantRadius( unsigned int index, unsigned int partial )
{
std::ostringstream error;
if ( index > 31 ) {
error << "Phonemes::formantRadius: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
oStream_ << "Phonemes::formantRadius: index is greater than 31!";
handleError( oStream_.str(), StkError::WARNING );
return 0.0;
}
if ( partial > 3 ) {
error << "Phonemes::formantRadius: partial is greater than 3!";
handleError( error.str(), StkError::WARNING );
oStream_ << "Phonemes::formantRadius: partial is greater than 3!";
handleError( oStream_.str(), StkError::WARNING );
return 0.0;
}
return phonemeParameters[index][partial][1];
@@ -281,15 +276,14 @@ StkFloat Phonemes :: formantRadius( unsigned int index, unsigned int partial )
StkFloat Phonemes :: formantGain( unsigned int index, unsigned int partial )
{
std::ostringstream error;
if ( index > 31 ) {
error << "Phonemes::formantGain: index is greater than 31!";
handleError( error.str(), StkError::WARNING );
oStream_ << "Phonemes::formantGain: index is greater than 31!";
handleError( oStream_.str(), StkError::WARNING );
return 0.0;
}
if ( partial > 3 ) {
error << "Phonemes::formantGain: partial is greater than 3!";
handleError( error.str(), StkError::WARNING );
oStream_ << "Phonemes::formantGain: partial is greater than 3!";
handleError( oStream_.str(), StkError::WARNING );
return 0.0;
}
return phonemeParameters[index][partial][2];

View File

@@ -5,7 +5,7 @@
This class implements a simple pitch shifter
using delay lines.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -54,7 +54,7 @@ StkFrames& PitShift :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
errorString_ << "PitShift::tick(): channel and StkFrames arguments are incompatible!";
oStream_ << "PitShift::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -71,7 +71,7 @@ StkFrames& PitShift :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned in
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
errorString_ << "PitShift::tick(): channel and StkFrames arguments are incompatible!";
oStream_ << "PitShift::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif

View File

@@ -1,132 +0,0 @@
/***************************************************/
/*! \class PluckTwo
\brief STK enhanced plucked string model class.
This class implements an enhanced two-string,
plucked physical model, a la Jaffe-Smith,
Smith, and others.
PluckTwo is an abstract class, with no excitation
specified. Therefore, it can't be directly
instantiated.
This is a digital waveguide model, making its
use possibly subject to patents held by
Stanford University, Yamaha, and others.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
*/
/***************************************************/
#include "PluckTwo.h"
namespace stk {
PluckTwo :: PluckTwo( StkFloat lowestFrequency )
{
length_ = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
lastLength_ = length_ * 0.5;
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( lastLength_ );
delayLine2_.setMaximumDelay( length_ );
delayLine2_.setDelay( lastLength_ );
combDelay_.setMaximumDelay( length_ );
combDelay_.setDelay( lastLength_ );
baseLoopGain_ = 0.995;
loopGain_ = 0.999;
pluckAmplitude_ = 0.3;
pluckPosition_ = 0.4;
detuning_ = 0.995;
lastFrequency_ = lowestFrequency * 2.0;
}
PluckTwo :: ~PluckTwo( void )
{
}
void PluckTwo :: clear( void )
{
delayLine_.clear();
delayLine2_.clear();
combDelay_.clear();
filter_.clear();
filter2_.clear();
}
void PluckTwo :: setFrequency( StkFloat frequency )
{
lastFrequency_ = frequency;
if ( lastFrequency_ <= 0.0 ) {
errorString_ << "Clarinet::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
lastFrequency_ = 220.0;
}
// Delay = length - approximate filter delay.
lastLength_ = Stk::sampleRate() / lastFrequency_;
StkFloat delay = (lastLength_ / detuning_) - 0.5;
if ( delay <= 0.0 ) delay = 0.3;
else if ( delay > length_ ) delay = length_;
delayLine_.setDelay( delay );
delay = (lastLength_ * detuning_) - 0.5;
if ( delay <= 0.0 ) delay = 0.3;
else if ( delay > length_ ) delay = length_;
delayLine2_.setDelay( delay );
loopGain_ = baseLoopGain_ + (frequency * 0.000005);
if ( loopGain_ > 1.0 ) loopGain_ = 0.99999;
}
void PluckTwo :: setDetune( StkFloat detune )
{
detuning_ = detune;
if ( detuning_ <= 0.0 ) {
errorString_ << "Clarinet::setDeturn: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
detuning_ = 0.1;
}
delayLine_.setDelay(( lastLength_ / detuning_) - 0.5);
delayLine2_.setDelay( (lastLength_ * detuning_) - 0.5);
}
void PluckTwo :: setFreqAndDetune( StkFloat frequency, StkFloat detune )
{
detuning_ = detune;
this->setFrequency( frequency );
}
void PluckTwo :: setPluckPosition( StkFloat position )
{
pluckPosition_ = position;
if ( position < 0.0 ) {
errorString_ << "PluckTwo::setPluckPosition: parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
pluckPosition_ = 0.0;
}
else if ( position > 1.0 ) {
errorString_ << "PluckTwo::setPluckPosition: parameter is greater than one ... setting to 1.0!";
handleError( StkError::WARNING );
pluckPosition_ = 1.0;
}
}
void PluckTwo :: setBaseLoopGain( StkFloat aGain )
{
baseLoopGain_ = aGain;
loopGain_ = baseLoopGain_ + (lastFrequency_ * 0.000005);
if ( loopGain_ > 0.99999 ) loopGain_ = 0.99999;
}
void PluckTwo :: noteOff( StkFloat amplitude )
{
loopGain_ = (1.0 - amplitude) * 0.5;
#if defined(_STK_DEBUG_)
errorString_ << "PluckTwo::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace

View File

@@ -1,11 +1,14 @@
/***************************************************/
/*! \class Plucked
\brief STK plucked string model class.
\brief STK basic plucked string class.
This class implements a simple plucked string
physical model based on the Karplus-Strong
algorithm.
For a more advanced plucked string implementation,
see the stk::Twang class.
This is a digital waveguide model, making its
use possibly subject to patents held by
Stanford University, Yamaha, and others.
@@ -13,7 +16,7 @@
Stanford, bearing the names of Karplus and/or
Strong.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -23,11 +26,15 @@ namespace stk {
Plucked :: Plucked( StkFloat lowestFrequency )
{
length_ = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
loopGain_ = 0.999;
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( 0.5 * length_ );
this->clear();
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Plucked::Plucked: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned long delays = (unsigned long) ( Stk::sampleRate() / lowestFrequency );
delayLine_.setMaximumDelay( delays + 1 );
this->setFrequency( 220.0 );
}
Plucked :: ~Plucked( void )
@@ -43,42 +50,31 @@ void Plucked :: clear( void )
void Plucked :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "Plucked::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
oStream_ << "Plucked::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
// Delay = length - approximate filter delay.
StkFloat delay = (Stk::sampleRate() / freakency) - 0.5;
if ( delay <= 0.0 )
delay = 0.3;
else if ( delay > length_ )
delay = length_;
// Delay = length - filter delay.
StkFloat delay = ( Stk::sampleRate() / frequency ) - loopFilter_.phaseDelay( frequency );
delayLine_.setDelay( delay );
loopGain_ = 0.995 + (freakency * 0.000005);
loopGain_ = 0.995 + (frequency * 0.000005);
if ( loopGain_ >= 1.0 ) loopGain_ = 0.99999;
}
void Plucked :: pluck( StkFloat amplitude )
{
StkFloat gain = amplitude;
if ( gain > 1.0 ) {
errorString_ << "Plucked::pluck: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
}
else if ( gain < 0.0 ) {
errorString_ << "Plucked::pluck: amplitude is < 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
gain = 0.0;
if ( amplitude < 0.0 || amplitude > 1.0 ) {
oStream_ << "Plucked::pluck: amplitude is out of range!";
handleError( StkError::WARNING ); return;
}
pickFilter_.setPole( 0.999 - (gain * 0.15) );
pickFilter_.setGain( gain * 0.5 );
for (unsigned long i=0; i<length_; i++)
pickFilter_.setPole( 0.999 - (amplitude * 0.15) );
pickFilter_.setGain( amplitude * 0.5 );
for ( unsigned long i=0; i<delayLine_.getDelay(); i++ )
// Fill delay with noise additively with current contents.
delayLine_.tick( 0.6 * delayLine_.lastOut() + pickFilter_.tick( noise_.tick() ) );
}
@@ -87,31 +83,16 @@ void Plucked :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
this->pluck( amplitude );
#if defined(_STK_DEBUG_)
errorString_ << "Plucked::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Plucked :: noteOff( StkFloat amplitude )
{
loopGain_ = 1.0 - amplitude;
if ( loopGain_ < 0.0 ) {
errorString_ << "Plucked::noteOff: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
loopGain_ = 0.0;
}
else if ( loopGain_ > 1.0 ) {
errorString_ << "Plucked::noteOff: amplitude is < 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
loopGain_ = (StkFloat) 0.99999;
if ( amplitude < 0.0 || amplitude > 1.0 ) {
oStream_ << "Plucked::noteOff: amplitude is out of range!";
handleError( StkError::WARNING ); return;
}
#if defined(_STK_DEBUG_)
errorString_ << "Plucked::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
loopGain_ = 1.0 - amplitude;
}
} // stk namespace

View File

@@ -7,7 +7,7 @@
coefficient. Another method is provided to create a DC blocking
filter.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -32,6 +32,11 @@ PoleZero :: ~PoleZero()
void PoleZero :: setCoefficients( StkFloat b0, StkFloat b1, StkFloat a1, bool clearState )
{
if ( std::abs( a1 ) >= 1.0 ) {
oStream_ << "PoleZero::setCoefficients: a1 argument (" << a1 << ") should be less than 1.0!";
handleError( StkError::WARNING ); return;
}
b_[0] = b0;
b_[1] = b1;
a_[1] = a1;
@@ -41,6 +46,11 @@ void PoleZero :: setCoefficients( StkFloat b0, StkFloat b1, StkFloat a1, bool cl
void PoleZero :: setAllpass( StkFloat coefficient )
{
if ( std::abs( coefficient ) >= 1.0 ) {
oStream_ << "PoleZero::setAllpass: argument (" << coefficient << ") makes filter unstable!";
handleError( StkError::WARNING ); return;
}
b_[0] = coefficient;
b_[1] = 1.0;
a_[0] = 1.0; // just in case
@@ -49,6 +59,11 @@ void PoleZero :: setAllpass( StkFloat coefficient )
void PoleZero :: setBlockZero( StkFloat thePole )
{
if ( std::abs( thePole ) >= 1.0 ) {
oStream_ << "PoleZero::setBlockZero: argument (" << thePole << ") makes filter unstable!";
handleError( StkError::WARNING ); return;
}
b_[0] = 1.0;
b_[1] = -1.0;
a_[0] = 1.0; // just in case

View File

@@ -13,7 +13,7 @@
- Zero Radii = 1
- Envelope Gain = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -41,96 +41,72 @@ void Resonate :: noteOn( StkFloat frequency, StkFloat amplitude )
adsr_.setTarget( amplitude );
this->keyOn();
this->setResonance( frequency, poleRadius_ );
#if defined(_STK_DEBUG_)
errorString_ << "Resonate::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Resonate :: noteOff( StkFloat amplitude )
{
this->keyOff();
#if defined(_STK_DEBUG_)
errorString_ << "Resonate::NoteOff: amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Resonate :: setResonance( StkFloat frequency, StkFloat radius )
{
poleFrequency_ = frequency;
if ( frequency < 0.0 ) {
errorString_ << "Resonate::setResonance: frequency parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
poleFrequency_ = 0.0;
oStream_ << "Resonate::setResonance: frequency parameter is less than zero!";
handleError( StkError::WARNING ); return;
}
if ( radius < 0.0 || radius >= 1.0 ) {
std::cerr << "Resonate::setResonance: radius parameter is out of range!";
handleError( StkError::WARNING ); return;
}
poleFrequency_ = frequency;
poleRadius_ = radius;
if ( radius < 0.0 ) {
std::cerr << "Resonate::setResonance: radius parameter is less than 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
poleRadius_ = 0.0;
}
else if ( radius >= 1.0 ) {
errorString_ << "Resonate::setResonance: radius parameter is greater than or equal to 1.0, which is unstable ... correcting!";
handleError( StkError::WARNING );
poleRadius_ = 0.9999;
}
filter_.setResonance( poleFrequency_, poleRadius_, true );
}
void Resonate :: setNotch( StkFloat frequency, StkFloat radius )
{
zeroFrequency_ = frequency;
if ( frequency < 0.0 ) {
errorString_ << "Resonate::setNotch: frequency parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
zeroFrequency_ = 0.0;
oStream_ << "Resonate::setNotch: frequency parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING ); return;
}
zeroRadius_ = radius;
if ( radius < 0.0 ) {
errorString_ << "Resonate::setNotch: radius parameter is less than 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
zeroRadius_ = 0.0;
oStream_ << "Resonate::setNotch: radius parameter is less than 0.0!";
handleError( StkError::WARNING ); return;
}
zeroFrequency_ = frequency;
zeroRadius_ = radius;
filter_.setNotch( zeroFrequency_, zeroRadius_ );
}
void Resonate :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Resonate::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Resonate::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == 2) // 2
setResonance( norm * Stk::sampleRate() * 0.5, poleRadius_ );
else if (number == 4) // 4
setResonance( poleFrequency_, norm*0.9999 );
else if (number == 11) // 11
this->setNotch( norm * Stk::sampleRate() * 0.5, zeroRadius_ );
else if (number == 1)
this->setNotch( zeroFrequency_, norm );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( norm );
else {
errorString_ << "Resonate::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Resonate::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Resonate::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == 2) // 2
setResonance( normalizedValue * Stk::sampleRate() * 0.5, poleRadius_ );
else if (number == 4) // 4
setResonance( poleFrequency_, normalizedValue * 0.9999 );
else if (number == 11) // 11
this->setNotch( normalizedValue * Stk::sampleRate() * 0.5, zeroRadius_ );
else if (number == 1)
this->setNotch( zeroFrequency_, normalizedValue );
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( normalizedValue );
#if defined(_STK_DEBUG_)
else {
oStream_ << "Resonate::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -66,6 +66,13 @@ Rhodey :: ~Rhodey( void )
void Rhodey :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "Rhodey::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
baseFrequency_ = frequency * 2.0;
for (unsigned int i=0; i<nOperators_; i++ )
@@ -80,11 +87,6 @@ void Rhodey :: noteOn( StkFloat frequency, StkFloat amplitude )
gains_[3] = amplitude * fmGains_[67];
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
errorString_ << "Rhodey::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@
that takes an StkFrames object for multi-channel and/or
multi-frame data.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -65,7 +65,7 @@ void RtWvIn :: fillBuffer( void *buffer, unsigned int nFrames )
mutex_.unlock();
if ( framesFilled_ > data_.frames() ) {
framesFilled_ = data_.frames();
errorString_ << "RtWvIn: audio buffer overrun!";
oStream_ << "RtWvIn: audio buffer overrun!";
handleError( StkError::WARNING );
}
}
@@ -121,7 +121,7 @@ StkFloat RtWvIn :: tick( unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= data_.channels() ) {
errorString_ << "RtWvIn::tick(): channel argument is incompatible with streamed channels!";
oStream_ << "RtWvIn::tick(): channel argument is incompatible with streamed channels!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
@@ -150,7 +150,7 @@ StkFrames& RtWvIn :: tick( StkFrames& frames )
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( nChannels != frames.channels() ) {
errorString_ << "RtWvIn::tick(): StkFrames argument is incompatible with adc channels!";
oStream_ << "RtWvIn::tick(): StkFrames argument is incompatible with adc channels!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif

View File

@@ -14,7 +14,7 @@
that takes a reference to an StkFrames object for multi-channel
and/or multi-frame data.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -82,7 +82,7 @@ int RtWvOut :: readBuffer( void *buffer, unsigned int frameCount )
if ( framesFilled_ < 0 ) {
framesFilled_ = 0;
// writeIndex_ = readIndex_;
errorString_ << "RtWvOut: audio buffer underrun!";
oStream_ << "RtWvOut: audio buffer underrun!";
handleError( StkError::WARNING );
}
@@ -169,7 +169,7 @@ void RtWvOut :: tick( const StkFrames& frames )
{
#if defined(_STK_DEBUG_)
if ( data_.channels() != frames.channels() ) {
errorString_ << "RtWvOut::tick(): incompatible channel value in StkFrames argument!";
oStream_ << "RtWvOut::tick(): incompatible channel value in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif

View File

@@ -5,7 +5,7 @@
This instrument provides an ADSR envelope, a one-pole filter, and
structures for an arbitrary number of attack and looped files.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -48,11 +48,6 @@ void Sampler :: keyOff( void )
void Sampler :: noteOff( StkFloat amplitude )
{
this->keyOff();
#if defined(_STK_DEBUG_)
errorString_ << "Sampler::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace

View File

@@ -31,7 +31,7 @@
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -42,22 +42,29 @@ namespace stk {
Saxofony :: Saxofony( StkFloat lowestFrequency )
{
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
// Initialize blowing position to 0.2 of length / 2.
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Saxofony::Saxofony: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned long nDelays = (unsigned long) ( Stk::sampleRate() / lowestFrequency );
delays_[0].setMaximumDelay( nDelays + 1 );
delays_[1].setMaximumDelay( nDelays + 1 );
// Initialize blowing position to 0.2 of length.
position_ = 0.2;
delays_[0].setMaximumDelay( length_ );
delays_[0].setDelay( (1.0-position_) * (length_ >> 1) );
delays_[1].setMaximumDelay( length_ );
delays_[1].setDelay( (1.0-position_) * (length_ >> 1) );
reedTable_.setOffset( 0.7 );
reedTable_.setSlope( 0.3 );
vibrato_.setFrequency((StkFloat) 5.735);
vibrato_.setFrequency( 5.735 );
outputGain_ = 0.3;
noiseGain_ = 0.2;
vibratoGain_ = 0.1;
this->setFrequency( 220.0 );
this->clear();
}
Saxofony :: ~Saxofony( void )
@@ -73,17 +80,15 @@ void Saxofony :: clear( void )
void Saxofony :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "Saxofony::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
oStream_ << "Saxofony::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat delay = (Stk::sampleRate() / freakency) - (StkFloat) 3.0;
if (delay <= 0.0) delay = 0.3;
else if (delay > length_) delay = length_;
// Account for filter delay and one sample "lastOut" delay.
StkFloat delay = ( Stk::sampleRate() / frequency ) - filter_.phaseDelay( frequency ) - 1.0;
delays_[0].setDelay( (1.0-position_) * delay );
delays_[1].setDelay( position_ * delay );
}
@@ -105,12 +110,22 @@ void Saxofony :: setBlowPosition( StkFloat position )
void Saxofony :: startBlowing( StkFloat amplitude, StkFloat rate )
{
if ( amplitude <= 0.0 || rate <= 0.0 ) {
oStream_ << "Saxofony::startBlowing: one or more arguments is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
envelope_.setRate( rate );
envelope_.setTarget( amplitude );
}
void Saxofony :: stopBlowing( StkFloat rate )
{
if ( rate <= 0.0 ) {
oStream_ << "Saxofony::stopBlowing: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
envelope_.setRate( rate );
envelope_.setTarget( 0.0 );
}
@@ -120,59 +135,42 @@ void Saxofony :: noteOn( StkFloat frequency, StkFloat amplitude )
this->setFrequency( frequency );
this->startBlowing( 0.55 + (amplitude * 0.30), amplitude * 0.005 );
outputGain_ = amplitude + 0.001;
#if defined(_STK_DEBUG_)
errorString_ << "Saxofony::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Saxofony :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.01 );
#if defined(_STK_DEBUG_)
errorString_ << "Saxofony::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Saxofony :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Saxofony::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Saxofony::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_ReedStiffness_) // 2
reedTable_.setSlope( 0.1 + (0.4 * norm) );
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = ( norm * 0.4 );
else if (number == 29) // 29
vibrato_.setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = ( norm * 0.5 );
else if (number == __SK_AfterTouch_Cont_) // 128
envelope_.setValue( norm );
else if (number == 11) // 11
this->setBlowPosition( norm );
else if (number == 26) // reed table offset
reedTable_.setOffset(0.4 + ( norm * 0.6));
else {
errorString_ << "Saxofony::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Saxofony::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Saxofony::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_ReedStiffness_) // 2
reedTable_.setSlope( 0.1 + (0.4 * normalizedValue) );
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = ( normalizedValue * 0.4 );
else if (number == 29) // 29
vibrato_.setFrequency( normalizedValue * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = ( normalizedValue * 0.5 );
else if (number == __SK_AfterTouch_Cont_) // 128
envelope_.setValue( normalizedValue );
else if (number == 11) // 11
this->setBlowPosition( normalizedValue );
else if (number == 26) // reed table offset
reedTable_.setOffset(0.4 + ( normalizedValue * 0.6));
#if defined(_STK_DEBUG_)
else {
oStream_ << "Saxofony::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -48,7 +48,7 @@
- Little Rocks = 21
- Tuned Bamboo Chimes = 22
by Perry R. Cook, 1996 - 2010.
by Perry R. Cook, 1995-2011.
*/
/***************************************************/
@@ -337,17 +337,12 @@ int Shakers :: setupName( char* instr )
{
int which = 0;
for (int i=0;i<NUM_INSTR;i++) {
for ( int i=0; i<NUM_INSTR; i++ ) {
if ( !strcmp(instr,instrs[i]) )
which = i;
}
#if defined(_STK_DEBUG_)
errorString_ << "Shakers::setupName: setting instrument to " << instrs[which] << '.';
handleError( StkError::DEBUG_WARNING );
#endif
return this->setupNum(which);
return this->setupNum( which );
}
void Shakers :: setFinalZs( StkFloat z0, StkFloat z1, StkFloat z2 )
@@ -800,14 +795,10 @@ void Shakers :: noteOn( StkFloat frequency, StkFloat amplitude )
// Yep ... pretty kludgey, but it works!
int noteNum = (int) ((12*log(frequency/220.0)/log(2.0)) + 57.01) % 32;
if (instType_ != noteNum) instType_ = this->setupNum(noteNum);
shakeEnergy_ += amplitude * MAX_SHAKE * 0.1;
if (shakeEnergy_ > MAX_SHAKE) shakeEnergy_ = MAX_SHAKE;
if (instType_==10 || instType_==3) ratchetPos_ += 1;
#if defined(_STK_DEBUG_)
errorString_ << "Shakers::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Shakers :: noteOff( StkFloat amplitude )
@@ -891,23 +882,18 @@ StkFloat Shakers :: tick( unsigned int )
void Shakers :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Shakers::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Shakers::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
#if defined(_STK_DEBUG_)
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Shakers::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat temp;
int i;
StkFloat temp;
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_Breath_) { // 2 ... energy
shakeEnergy_ += norm * MAX_SHAKE * 0.1;
shakeEnergy_ += normalizedValue * MAX_SHAKE * 0.1;
if (shakeEnergy_ > MAX_SHAKE) shakeEnergy_ = MAX_SHAKE;
if (instType_==10 || instType_==3) {
ratchetPos_ = (int) fabs(value - lastRatchetPos_);
@@ -974,7 +960,7 @@ void Shakers :: controlChange( int number, StkFloat value )
}
}
else if (number == __SK_AfterTouch_Cont_) { // 128
shakeEnergy_ += norm * MAX_SHAKE * 0.1;
shakeEnergy_ += normalizedValue * MAX_SHAKE * 0.1;
if (shakeEnergy_ > MAX_SHAKE) shakeEnergy_ = MAX_SHAKE;
if (instType_==10 || instType_==3) {
ratchetPos_ = (int) fabs(value - lastRatchetPos_);
@@ -985,15 +971,12 @@ void Shakers :: controlChange( int number, StkFloat value )
else if (number == __SK_ShakerInst_) { // 1071
instType_ = (int) (value + 0.5); // Just to be safe
this->setupNum(instType_);
}
}
#if defined(_STK_DEBUG_)
else {
errorString_ << "Shakers::controlChange: undefined control number (" << number << ")!";
oStream_ << "Shakers::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Shakers::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -13,7 +13,7 @@
- Envelope Rate = 11
- Gain = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -53,62 +53,52 @@ void Simple :: noteOn( StkFloat frequency, StkFloat amplitude )
this->keyOn();
this->setFrequency( frequency );
filter_.setGain( amplitude );
#if defined(_STK_DEBUG_)
errorString_ << "Simple::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Simple :: noteOff( StkFloat amplitude )
{
this->keyOff();
#if defined(_STK_DEBUG_)
errorString_ << "Simple::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Simple :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "Simple::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
biquad_.setResonance( frequency, 0.98, true );
loop_->setFrequency( frequency );
}
void Simple :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Simple::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Simple::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
#if defined(_STK_DEBUG_)
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Simple::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_Breath_) // 2
filter_.setPole( 0.99 * (1.0 - (norm * 2.0)) );
filter_.setPole( 0.99 * (1.0 - (normalizedValue * 2.0)) );
else if (number == __SK_NoiseLevel_) // 4
loopGain_ = norm;
loopGain_ = normalizedValue;
else if (number == __SK_ModFrequency_) { // 11
norm /= 0.2 * Stk::sampleRate();
adsr_.setAttackRate( norm );
adsr_.setDecayRate( norm );
adsr_.setReleaseRate( norm );
normalizedValue /= 0.2 * Stk::sampleRate();
adsr_.setAttackRate( normalizedValue );
adsr_.setDecayRate( normalizedValue );
adsr_.setReleaseRate( normalizedValue );
}
else if (number == __SK_AfterTouch_Cont_) // 128
adsr_.setTarget( norm );
adsr_.setTarget( normalizedValue );
#if defined(_STK_DEBUG_)
else {
errorString_ << "Simple::controlChange: undefined control number (" << number << ")!";
oStream_ << "Simple::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Simple::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -9,7 +9,7 @@
The "table" length, set in SineWave.h, is 2048 samples by default.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/

View File

@@ -9,7 +9,7 @@
Within STK, it is used as an excitation source for other
instruments.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/

View File

@@ -13,7 +13,7 @@
Stanford, bearing the names of Karplus and/or
Strong.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -23,16 +23,21 @@ namespace stk {
Sitar :: Sitar( StkFloat lowestFrequency )
{
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Sitar::Sitar: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned long length = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
delayLine_.setMaximumDelay( length );
delay_ = 0.5 * length;
delayLine_.setDelay( delay_ );
targetDelay_ = delay_;
loopFilter_.setZero(0.01);
loopFilter_.setZero( 0.01 );
loopGain_ = 0.999;
envelope_.setAllTimes(0.001, 0.04, 0.0, 0.5);
envelope_.setAllTimes( 0.001, 0.04, 0.0, 0.5 );
this->clear();
}
@@ -48,17 +53,17 @@ void Sitar :: clear( void )
void Sitar :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "Sitar::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
oStream_ << "Sitar::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
targetDelay_ = (Stk::sampleRate() / freakency);
targetDelay_ = (Stk::sampleRate() / frequency);
delay_ = targetDelay_ * (1.0 + (0.05 * noise_.tick()));
delayLine_.setDelay( delay_ );
loopGain_ = 0.995 + (freakency * 0.0000005);
loopGain_ = 0.995 + (frequency * 0.0000005);
if ( loopGain_ > 0.9995 ) loopGain_ = 0.9995;
}
@@ -72,31 +77,16 @@ void Sitar :: noteOn( StkFloat frequency, StkFloat amplitude )
this->setFrequency( frequency );
this->pluck( amplitude );
amGain_ = 0.1 * amplitude;
#if defined(_STK_DEBUG_)
errorString_ << "Sitar::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void Sitar :: noteOff( StkFloat amplitude )
{
loopGain_ = (StkFloat) 1.0 - amplitude;
if ( loopGain_ < 0.0 ) {
errorString_ << "Sitar::noteOff: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
loopGain_ = 0.0;
}
else if ( loopGain_ > 1.0 ) {
errorString_ << "Sitar::noteOff: amplitude is < 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
loopGain_ = 0.99999;
if ( amplitude < 0.0 || amplitude > 1.0 ) {
oStream_ << "Sitar::noteOff: amplitude is out of range!";
handleError( StkError::WARNING ); return;
}
#if defined(_STK_DEBUG_)
errorString_ << "Sitar::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
loopGain_ = (StkFloat) 1.0 - amplitude;
}
} // stk namespace

View File

@@ -19,13 +19,14 @@
See also SKINI.txt.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
#include "Skini.h"
#include "SKINI.tbl"
#include <cstdlib>
#include <sstream>
namespace stk {
@@ -40,14 +41,14 @@ Skini :: ~Skini()
bool Skini :: setFile( std::string fileName )
{
if ( file_.is_open() ) {
errorString_ << "Skini::setFile: already reaading a file!";
oStream_ << "Skini::setFile: already reaading a file!";
handleError( StkError::WARNING );
return false;
}
file_.open( fileName.c_str() );
if ( !file_ ) {
errorString_ << "Skini::setFile: unable to open file (" << fileName << ")";
oStream_ << "Skini::setFile: unable to open file (" << fileName << ")";
handleError( StkError::WARNING );
return false;
}
@@ -65,7 +66,7 @@ long Skini :: nextMessage( Message& message )
// Read a line from the file and skip over invalid messages.
if ( std::getline( file_, line ).eof() ) {
errorString_ << "// End of Score. Thanks for using SKINI!!";
oStream_ << "// End of Score. Thanks for using SKINI!!";
handleError( StkError::STATUS );
file_.close();
message.type = 0;
@@ -105,7 +106,7 @@ long Skini :: parseString( std::string& line, Message& message )
std::string::size_type lastPos = line.find_first_not_of(" ,\t", 0);
std::string::size_type pos = line.find_first_of("/", lastPos);
if ( std::string::npos != pos ) {
errorString_ << "// Comment Line: " << line;
oStream_ << "// Comment Line: " << line;
handleError( StkError::STATUS );
return message.type;
}
@@ -126,7 +127,7 @@ long Skini :: parseString( std::string& line, Message& message )
}
if ( iSkini >= __SK_MaxMsgTypes_ ) {
errorString_ << "Skini::parseString: couldn't parse this line:\n " << line;
oStream_ << "Skini::parseString: couldn't parse this line:\n " << line;
handleError( StkError::WARNING );
return message.type;
}
@@ -138,7 +139,7 @@ long Skini :: parseString( std::string& line, Message& message )
if ( tokens[1][0] == '=' ) {
tokens[1].erase( tokens[1].begin() );
if ( tokens[1].empty() ) {
errorString_ << "Skini::parseString: couldn't parse time field in line:\n " << line;
oStream_ << "Skini::parseString: couldn't parse time field in line:\n " << line;
handleError( StkError::WARNING );
return message.type = 0;
}
@@ -156,7 +157,7 @@ long Skini :: parseString( std::string& line, Message& message )
while ( dataType != NOPE ) {
if ( tokens.size() <= (unsigned int) (iValue+3) ) {
errorString_ << "Skini::parseString: inconsistency between type table and parsed line:\n " << line;
oStream_ << "Skini::parseString: inconsistency between type table and parsed line:\n " << line;
handleError( StkError::WARNING );
return message.type = 0;
}

View File

@@ -5,7 +5,7 @@
This class provides common functionality for TCP and UDP internet
socket server and client subclasses.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/

View File

@@ -5,7 +5,7 @@
This class implements a spherical ball with
radius, mass, position, and velocity parameters.
by Perry R. Cook, 1995 - 2010.
by Perry R. Cook, 1995-2011.
*/
/***************************************************/

View File

@@ -17,7 +17,7 @@
- String Sustain = 11
- String Stretch = 1
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -29,21 +29,24 @@ namespace stk {
StifKarp :: StifKarp( StkFloat lowestFrequency )
{
length_ = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 );
delayLine_.setMaximumDelay( length_ );
delayLine_.setDelay( 0.5 * length_ );
combDelay_.setMaximumDelay( length_ );
combDelay_.setDelay( 0.2 * length_ );
if ( lowestFrequency <= 0.0 ) {
oStream_ << "StifKarp::StifKarp: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
unsigned long nDelays = (unsigned long) ( Stk::sampleRate() / lowestFrequency );
delayLine_.setMaximumDelay( nDelays + 1 );
combDelay_.setMaximumDelay( nDelays + 1 );
pluckAmplitude_ = 0.3;
pickupPosition_ = 0.4;
lastFrequency_ = lowestFrequency * 2.0;
lastLength_ = length_ * 0.5;
stretching_ = 0.9999;
baseLoopGain_ = 0.995;
loopGain_ = 0.999;
this->clear();
this->setFrequency( 220.0 );
}
StifKarp :: ~StifKarp( void )
@@ -59,19 +62,16 @@ void StifKarp :: clear( void )
void StifKarp :: setFrequency( StkFloat frequency )
{
lastFrequency_ = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "StifKarp::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
lastFrequency_ = 220.0;
oStream_ << "StifKarp::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
lastFrequency_ = frequency;
lastLength_ = Stk::sampleRate() / lastFrequency_;
StkFloat delay = lastLength_ - 0.5;
if (delay <= 0.0)
delay = 0.3;
else if (delay > length_)
delay = length_;
delayLine_.setDelay( delay );
loopGain_ = baseLoopGain_ + (frequency * 0.000005);
@@ -89,8 +89,8 @@ void StifKarp :: setStretch( StkFloat stretch )
StkFloat freq = lastFrequency_ * 2.0;
StkFloat dFreq = ( (0.5 * Stk::sampleRate()) - freq ) * 0.25;
StkFloat temp = 0.5 + (stretch * 0.5);
if (temp > 0.9999) temp = 0.9999;
for (int i=0; i<4; i++) {
if ( temp > 0.9999 ) temp = 0.9999;
for ( int i=0; i<4; i++ ) {
coefficient = temp * temp;
biquad_[i].setA2( coefficient );
biquad_[i].setB0( coefficient );
@@ -105,19 +105,14 @@ void StifKarp :: setStretch( StkFloat stretch )
}
void StifKarp :: setPickupPosition( StkFloat position ) {
pickupPosition_ = position;
if ( position < 0.0 ) {
errorString_ << "StifKarp::setPickupPosition: parameter is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
pickupPosition_ = 0.0;
}
else if ( position > 1.0 ) {
errorString_ << "StifKarp::setPickupPosition: parameter is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
pickupPosition_ = 1.0;
if ( position < 0.0 || position > 1.0 ) {
oStream_ << "StifKarp::setPickupPosition: parameter is out of range!";
handleError( StkError::WARNING ); return;
}
// Set the pick position, which puts zeroes at position * length.
pickupPosition_ = position;
combDelay_.setDelay( 0.5 * pickupPosition_ * lastLength_ );
}
@@ -130,20 +125,13 @@ void StifKarp :: setBaseLoopGain( StkFloat aGain )
void StifKarp :: pluck( StkFloat amplitude )
{
StkFloat gain = amplitude;
if ( gain > 1.0 ) {
errorString_ << "StifKarp::pluck: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
}
else if ( gain < 0.0 ) {
errorString_ << "StifKarp::pluck: amplitude is less than zero ... setting to 0.0!";
handleError( StkError::WARNING );
gain = 0.0;
if ( amplitude < 0.0 || amplitude > 1.0 ) {
oStream_ << "StifKarp::pluck: amplitude is out of range!";
handleError( StkError::WARNING ); return;
}
pluckAmplitude_ = amplitude;
for (unsigned long i=0; i<length_; i++) {
for ( unsigned long i=0; i<length_; i++ ) {
// Fill delay with noise additively with current contents.
delayLine_.tick( (delayLine_.lastOut() * 0.6) + 0.4 * noise_.tick() * pluckAmplitude_ );
//delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) );
@@ -154,62 +142,39 @@ void StifKarp :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
this->pluck( amplitude );
#if defined(_STK_DEBUG_)
errorString_ << "StifKarp::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
}
void StifKarp :: noteOff( StkFloat amplitude )
{
StkFloat gain = amplitude;
if ( gain > 1.0 ) {
errorString_ << "StifKarp::noteOff: amplitude is greater than 1.0 ... setting to 1.0!";
handleError( StkError::WARNING );
gain = 1.0;
if ( amplitude < 0.0 || amplitude > 1.0 ) {
oStream_ << "StifKarp::noteOff: amplitude is out of range!";
handleError( StkError::WARNING ); return;
}
else if ( gain < 0.0 ) {
errorString_ << "StifKarp::noteOff: amplitude is < 0.0 ... setting to 0.0!";
handleError( StkError::WARNING );
gain = 0.0;
}
loopGain_ = (1.0 - gain) * 0.5;
#if defined(_STK_DEBUG_)
errorString_ << "StifKarp::NoteOff: amplitude = " << amplitude << ".";
handleError( StkError::DEBUG_WARNING );
#endif
loopGain_ = (1.0 - amplitude) * 0.5;
}
void StifKarp :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "StifKarp::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "StifKarp::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
}
if (number == __SK_PickPosition_) // 4
this->setPickupPosition( norm );
else if (number == __SK_StringDamping_) // 11
this->setBaseLoopGain( 0.97 + (norm * 0.03) );
else if (number == __SK_StringDetune_) // 1
this->setStretch( 0.9 + (0.1 * (1.0 - norm)) );
else {
errorString_ << "StifKarp::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "StifKarp::controlChange: number = " << number << ", value = " << value << ".";
handleError( StkError::DEBUG_WARNING );
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Clarinet::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_PickPosition_) // 4
this->setPickupPosition( normalizedValue );
else if (number == __SK_StringDamping_) // 11
this->setBaseLoopGain( 0.97 + (normalizedValue * 0.03) );
else if (number == __SK_StringDetune_) // 1
this->setStretch( 0.9 + (0.1 * (1.0 - normalizedValue)) );
#if defined(_STK_DEBUG_)
else {
oStream_ << "StifKarp::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#endif
}

View File

@@ -22,7 +22,7 @@
STK WWW site: http://ccrma.stanford.edu/software/stk/
The Synthesis ToolKit in C++ (STK)
Copyright (c) 1995-2010 Perry R. Cook and Gary P. Scavone
Copyright (c) 1995-2011 Perry R. Cook and Gary P. Scavone
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
@@ -65,6 +65,7 @@ const Stk::StkFormat Stk :: STK_FLOAT64 = 0x20;
bool Stk :: showWarnings_ = true;
bool Stk :: printErrors_ = true;
std::vector<Stk *> Stk :: alertList_;
std::ostringstream Stk :: oStream_;
Stk :: Stk( void )
: ignoreSampleRateChange_(false)
@@ -192,8 +193,8 @@ void Stk :: sleep(unsigned long milliseconds)
void Stk :: handleError( StkError::Type type )
{
handleError( errorString_.str(), type );
errorString_.str( std::string() ); // reset the ostringstream buffer
handleError( oStream_.str(), type );
oStream_.str( std::string() ); // reset the ostringstream buffer
}
void Stk :: handleError( const char *message, StkError::Type type )
@@ -208,7 +209,7 @@ void Stk :: handleError( std::string message, StkError::Type type )
if ( !showWarnings_ ) return;
std::cerr << '\n' << message << '\n' << std::endl;
}
else if (type == StkError::DEBUG_WARNING) {
else if (type == StkError::DEBUG_PRINT) {
#if defined(_STK_DEBUG_)
std::cerr << '\n' << message << '\n' << std::endl;
#endif

View File

@@ -10,7 +10,7 @@
A non-interpolating delay line is typically used in fixed
delay-length applications, such as for reverberation.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -24,13 +24,13 @@ TapDelay :: TapDelay( std::vector<unsigned long> taps, unsigned long maxDelay )
// If we want to allow a delay of maxDelay, we need a
// delayline of length = maxDelay+1.
if ( maxDelay < 1 ) {
errorString_ << "TapDelay::TapDelay: maxDelay must be > 0!\n";
oStream_ << "TapDelay::TapDelay: maxDelay must be > 0!\n";
handleError( StkError::FUNCTION_ARGUMENT );
}
for ( unsigned int i=0; i<taps.size(); i++ ) {
if ( taps[i] > maxDelay ) {
errorString_ << "TapDelay::TapDelay: maxDelay must be > than all tap delay values!\n";
oStream_ << "TapDelay::TapDelay: maxDelay must be > than all tap delay values!\n";
handleError( StkError::FUNCTION_ARGUMENT );
}
}
@@ -50,17 +50,10 @@ void TapDelay :: setMaximumDelay( unsigned long delay )
{
if ( delay < inputs_.size() ) return;
if ( delay < 0 ) {
errorString_ << "TapDelay::setMaximumDelay: argument (" << delay << ") less than zero!\n";
handleError( StkError::WARNING );
return;
}
for ( unsigned int i=0; i<delays_.size(); i++ ) {
if ( delay < delays_[i] ) {
errorString_ << "TapDelay::setMaximumDelay: argument (" << delay << ") less than a current tap delay setting (" << delays_[i] << ")!\n";
handleError( StkError::WARNING );
return;
oStream_ << "TapDelay::setMaximumDelay: argument (" << delay << ") less than a current tap delay setting (" << delays_[i] << ")!\n";
handleError( StkError::WARNING ); return;
}
}
@@ -69,6 +62,18 @@ void TapDelay :: setMaximumDelay( unsigned long delay )
void TapDelay :: setTapDelays( std::vector<unsigned long> taps )
{
for ( unsigned int i=0; i<taps.size(); i++ ) {
if ( taps[i] > inputs_.size() - 1 ) { // The value is too big.
oStream_ << "TapDelay::setTapDelay: argument (" << taps[i] << ") greater than maximum!\n";
handleError( StkError::WARNING ); return;
}
if ( taps[i] < 0 ) {
error << "TapDelay::setDelay: argument (" << taps[i] << ") less than zero!\n";
handleError( StkError::WARNING ); return;
}
}
if ( taps.size() != outPoint_.size() ) {
outPoint_.resize( taps.size() );
delays_.resize( taps.size() );
@@ -76,27 +81,10 @@ void TapDelay :: setTapDelays( std::vector<unsigned long> taps )
}
for ( unsigned int i=0; i<taps.size(); i++ ) {
if ( taps[i] > inputs_.size() - 1 ) { // The value is too big.
errorString_ << "TapDelay::setTapDelay: argument (" << taps[i] << ") too big ... setting to maximum!\n";
handleError( StkError::WARNING );
// Force delay to maximum length.
outPoint_[i] = inPoint_ + 1;
if ( outPoint_[i] == inputs_.size() ) outPoint_[i] = 0;
delays_[i] = inputs_.size() - 1;
}
else if ( taps[i] < 0 ) {
errorString_ << "TapDelay::setDelay: argument (" << taps[i] << ") less than zero ... setting to zero!\n";
handleError( StkError::WARNING );
outPoint_[i] = inPoint_;
delays_[i] = 0;
}
else { // read chases write
if ( inPoint_ >= taps[i] ) outPoint_[i] = inPoint_ - taps[i];
else outPoint_[i] = inputs_.size() + inPoint_ - taps[i];
delays_[i] = taps[i];
}
// read chases write
if ( inPoint_ >= taps[i] ) outPoint_[i] = inPoint_ - taps[i];
else outPoint_[i] = inputs_.size() + inPoint_ - taps[i];
delays_[i] = taps[i];
}
}

View File

@@ -19,12 +19,13 @@
less than or equal to zero indicate a closed
or lost connection or the occurence of an error.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
#include "TcpClient.h"
#include <cstring>
#include <sstream>
namespace stk {
@@ -36,7 +37,7 @@ TcpClient :: TcpClient( int port, std::string hostname )
WSAStartup( wVersionRequested, &wsaData );
if ( wsaData.wVersion != wVersionRequested ) {
errorString_ << "TcpClient: Incompatible Windows socket library version!";
oStream_ << "TcpClient: Incompatible Windows socket library version!";
handleError( StkError::PROCESS_SOCKET );
}
#endif
@@ -57,20 +58,20 @@ int TcpClient :: connect( int port, std::string hostname )
// Create the client-side socket
soket_ = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( soket_ < 0 ) {
errorString_ << "TcpClient: Couldn't create socket client!";
oStream_ << "TcpClient: Couldn't create socket client!";
handleError( StkError::PROCESS_SOCKET );
}
int flag = 1;
int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) );
if ( result < 0 ) {
errorString_ << "TcpClient: Error setting socket options!";
oStream_ << "TcpClient: Error setting socket options!";
handleError( StkError::PROCESS_SOCKET );
}
struct hostent *hostp;
if ( ( hostp = gethostbyname( hostname.c_str() ) ) == 0 ) {
errorString_ << "TcpClient: unknown host (" << hostname << ")!";
oStream_ << "TcpClient: unknown host (" << hostname << ")!";
handleError( StkError::PROCESS_SOCKET_IPADDR );
}
@@ -82,7 +83,7 @@ int TcpClient :: connect( int port, std::string hostname )
// Connect to the server
if ( ::connect( soket_, (struct sockaddr *)&server_address, sizeof(server_address) ) < 0 ) {
errorString_ << "TcpClient: Couldn't connect to socket server!";
oStream_ << "TcpClient: Couldn't connect to socket server!";
handleError( StkError::PROCESS_SOCKET );
}

View File

@@ -19,7 +19,7 @@
less than or equal to zero indicate a closed
or lost connection or the occurence of an error.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -36,7 +36,7 @@ TcpServer :: TcpServer( int port )
WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested) {
errorString_ << "TcpServer: Incompatible Windows socket library version!";
oStream_ << "TcpServer: Incompatible Windows socket library version!";
handleError( StkError::PROCESS_SOCKET );
}
#endif
@@ -44,14 +44,14 @@ TcpServer :: TcpServer( int port )
// Create the server-side socket
soket_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (soket_ < 0) {
errorString_ << "TcpServer: Couldn't create socket server!";
oStream_ << "TcpServer: Couldn't create socket server!";
handleError( StkError::PROCESS_SOCKET );
}
int flag = 1;
int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) );
if (result < 0) {
errorString_ << "TcpServer: Error setting socket options!";
oStream_ << "TcpServer: Error setting socket options!";
handleError( StkError::PROCESS_SOCKET );
}
@@ -62,13 +62,13 @@ TcpServer :: TcpServer( int port )
// Bind socket to the appropriate port and interface (INADDR_ANY)
if ( bind( soket_, (struct sockaddr *)&address, sizeof(address) ) < 0 ) {
errorString_ << "TcpServer: Couldn't bind socket!";
oStream_ << "TcpServer: Couldn't bind socket!";
handleError( StkError::PROCESS_SOCKET );
}
// Listen for incoming connection(s)
if ( listen( soket_, 1 ) < 0 ) {
errorString_ << "TcpServer: Couldn't start server listening!";
oStream_ << "TcpServer: Couldn't start server listening!";
handleError( StkError::PROCESS_SOCKET );
}

View File

@@ -16,7 +16,7 @@
THREAD_RETURN THREAD_TYPE thread_function(void *ptr)
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -36,7 +36,7 @@ Thread :: ~Thread()
bool Thread :: start( THREAD_FUNCTION routine, void * ptr )
{
if ( thread_ ) {
errorString_ << "Thread:: a thread is already running!";
oStream_ << "Thread:: a thread is already running!";
handleError( StkError::WARNING );
return false;
}

View File

@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -73,11 +73,6 @@ void TubeBell :: noteOn( StkFloat frequency, StkFloat amplitude )
gains_[3] = amplitude * fmGains_[71];
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
errorString_ << "TubeBell::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace

108
src/Twang.cpp Normal file
View File

@@ -0,0 +1,108 @@
/***************************************************/
/*! \class Twang
\brief STK enhanced plucked string class.
This class implements an enhanced plucked-string
physical model, a la Jaffe-Smith, Smith,
Karjalainen and others. It includes a comb
filter to simulate pluck position. The tick()
function takes an input sample, which is added
to the delayline input. This can be used to
implement commuted synthesis (if the input
samples are derived from the impulse response of
a body filter) or feedback (as in an electric
guitar model).
This is a digital waveguide model, making its
use possibly subject to patents held by Stanford
University, Yamaha, and others.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
#include "Twang.h"
namespace stk {
Twang :: Twang( StkFloat lowestFrequency )
{
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Twang::Twang: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
this->setLowestFrequency( lowestFrequency );
std::vector<StkFloat> coefficients( 2, 0.5 );
loopFilter_.setCoefficients( coefficients );
lastFrame_.resize( 1, 1, 0.0 );
loopGain_ = 0.995;
pluckPosition_ = 0.4;
this->setFrequency( 220.0 );
}
Twang :: ~Twang( void )
{
}
void Twang :: clear( void )
{
delayLine_.clear();
combDelay_.clear();
loopFilter_.clear();
lastFrame_[0] = 0.0;
}
void Twang :: setLowestFrequency( StkFloat frequency )
{
unsigned long nDelays = (unsigned long) ( Stk::sampleRate() / frequency );
delayLine_.setMaximumDelay( nDelays + 1 );
combDelay_.setMaximumDelay( nDelays + 1 );
}
void Twang :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "Twang::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
// Delay = length - filter delay.
StkFloat delay = ( Stk::sampleRate() / frequency ) - loopFilter_.phaseDelay( frequency );
delayLine_.setDelay( delay );
this->setLoopGain( loopGain_ );
// Set the pluck position, which puts zeroes at position * length.
combDelay_.setDelay( 0.5 * pluckPosition_ * delay );
}
void Twang :: setLoopGain( StkFloat loopGain )
{
if ( loopGain < 0.0 || loopGain >= 1.0 ) {
oStream_ << "Twang::setLoopGain: parameter is out of range!";
handleError( StkError::WARNING ); return;
}
loopGain_ = loopGain;
StkFloat gain = loopGain_ + (frequency_ * 0.000005);
if ( gain >= 1.0 ) gain = 0.99999;
loopFilter_.setGain( gain );
}
void Twang :: setPluckPosition( StkFloat position )
{
if ( position < 0.0 || position > 1.0 ) {
oStream_ << "Twang::setPluckPosition: argument (" << position << ") is out of range!";
handleError( StkError::WARNING ); return;
}
pluckPosition_ = position;
}
} // stk namespace

View File

@@ -6,7 +6,7 @@
provided for creating a resonance in the frequency response while
maintaining a nearly constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -35,13 +35,24 @@ TwoPole :: ~TwoPole()
void TwoPole :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
{
if ( !ignoreSampleRateChange_ ) {
errorString_ << "TwoPole::sampleRateChanged: you may need to recompute filter coefficients!";
oStream_ << "TwoPole::sampleRateChanged: you may need to recompute filter coefficients!";
handleError( StkError::WARNING );
}
}
void TwoPole :: setResonance( StkFloat frequency, StkFloat radius, bool normalize )
{
#if defined(_STK_DEBUG_)
if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) {
oStream_ << "TwoPole::setResonance: frequency argument (" << frequency << ") is out of range!";
handleError( StkError::WARNING ); return;
}
if ( radius < 0.0 || radius >= 1.0 ) {
oStream_ << "TwoPole::setResonance: radius argument (" << radius << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
a_[2] = radius * radius;
a_[1] = (StkFloat) -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate());

View File

@@ -6,7 +6,7 @@
provided for creating a "notch" in the frequency response while
maintaining a constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -32,7 +32,7 @@ TwoZero :: ~TwoZero()
void TwoZero :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
{
if ( !ignoreSampleRateChange_ ) {
errorString_ << "TwoZero::sampleRateChanged: you may need to recompute filter coefficients!";
oStream_ << "TwoZero::sampleRateChanged: you may need to recompute filter coefficients!";
handleError( StkError::WARNING );
}
}
@@ -48,8 +48,19 @@ void TwoZero :: setCoefficients( StkFloat b0, StkFloat b1, StkFloat b2, bool cle
void TwoZero :: setNotch( StkFloat frequency, StkFloat radius )
{
#if defined(_STK_DEBUG_)
if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) {
oStream_ << "TwoZero::setNotch: frequency argument (" << frequency << ") is out of range!";
handleError( StkError::WARNING ); return;
}
if ( radius < 0.0 ) {
oStream_ << "TwoZero::setNotch: radius argument (" << radius << ") is negative!";
handleError( StkError::WARNING ); return;
}
#endif
b_[2] = radius * radius;
b_[1] = (StkFloat) -2.0 * radius * cos(TWO_PI * (double) frequency / Stk::sampleRate());
b_[1] = -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate());
// Normalize the filter gain.
if ( b_[1] > 0.0 ) // Maximum at z = 0.

View File

@@ -17,12 +17,13 @@
read/write methods. Values less than or equal to zero indicate
the occurence of an error.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
#include "UdpSocket.h"
#include <cstring>
#include <sstream>
namespace stk {
@@ -36,7 +37,7 @@ UdpSocket :: UdpSocket(int port )
WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested) {
errorString_ << "UdpSocket: Incompatible Windows socket library version!";
oStream_ << "UdpSocket: Incompatible Windows socket library version!";
handleError( StkError::PROCESS_SOCKET );
}
#endif
@@ -44,7 +45,7 @@ UdpSocket :: UdpSocket(int port )
// Create the UDP socket
soket_ = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( soket_ < 0 ) {
errorString_ << "UdpSocket: Couldn't create UDP socket!";
oStream_ << "UdpSocket: Couldn't create UDP socket!";
handleError( StkError::PROCESS_SOCKET );
}
@@ -55,7 +56,7 @@ UdpSocket :: UdpSocket(int port )
// Bind socket to the appropriate port and interface (INADDR_ANY)
if ( bind(soket_, (struct sockaddr *)&address, sizeof(address)) < 0 ) {
errorString_ << "UdpSocket: Couldn't bind socket in constructor!";
oStream_ << "UdpSocket: Couldn't bind socket in constructor!";
handleError( StkError::PROCESS_SOCKET );
}
@@ -76,7 +77,7 @@ void UdpSocket :: setAddress( struct sockaddr_in *address, int port, std::string
{
struct hostent *hostp;
if ( (hostp = gethostbyname( hostname.c_str() )) == 0 ) {
errorString_ << "UdpSocket::setAddress: unknown host (" << hostname << ")!";
oStream_ << "UdpSocket::setAddress: unknown host (" << hostname << ")!";
handleError( StkError::PROCESS_SOCKET_IPADDR );
}

View File

@@ -21,7 +21,7 @@
- Vibrato Gain = 1
- Loudness (Spectral Tilt) = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -69,14 +69,14 @@ void VoicForm :: clear( void )
void VoicForm :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "VoicForm::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
oStream_ << "VoicForm::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
voiced_->setFrequency( freakency );
voiced_->setFrequency( frequency );
}
bool VoicForm :: setPhoneme( const char *phoneme )
@@ -92,16 +92,12 @@ bool VoicForm :: setPhoneme( const char *phoneme )
filters_[3].setTargets( Phonemes::formantFrequency(i, 3), Phonemes::formantRadius(i, 3), pow(10.0, Phonemes::formantGain(i, 3 ) / 20.0) );
this->setVoiced( Phonemes::voiceGain( i ) );
this->setUnVoiced( Phonemes::noiseGain( i ) );
#if defined(_STK_DEBUG_)
errorString_ << "VoicForm::setPhoneme: found formant " << phoneme << " (number " << i << ").";
handleError( StkError::DEBUG_WARNING );
#endif
}
i++;
}
if ( !found ) {
errorString_ << "VoicForm::setPhoneme: phoneme " << phoneme << " not found!";
oStream_ << "VoicForm::setPhoneme: phoneme " << phoneme << " not found!";
handleError( StkError::WARNING );
}
@@ -111,9 +107,8 @@ bool VoicForm :: setPhoneme( const char *phoneme )
void VoicForm :: setFilterSweepRate( unsigned int whichOne, StkFloat rate )
{
if ( whichOne < 0 || whichOne > 3 ) {
errorString_ << "VoicForm::setFilterSweepRate: filter select argument outside range 0-3!";
handleError( StkError::WARNING );
return;
oStream_ << "VoicForm::setFilterSweepRate: filter select argument outside range 0-3!";
handleError( StkError::WARNING ); return;
}
filters_[whichOne].setSweepRate(rate);
@@ -134,21 +129,17 @@ void VoicForm :: noteOn( StkFloat frequency, StkFloat amplitude )
void VoicForm :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "VoicForm::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "VoicForm::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
#if defined(_STK_DEBUG_)
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Clarinet::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if (number == __SK_Breath_) { // 2
this->setVoiced( 1.0 - norm );
this->setUnVoiced( 0.01 * norm );
this->setVoiced( 1.0 - normalizedValue );
this->setUnVoiced( 0.01 * normalizedValue );
}
else if (number == __SK_FootControl_) { // 4
StkFloat temp = 0.0;
@@ -180,21 +171,18 @@ void VoicForm :: controlChange( int number, StkFloat value )
this->setUnVoiced( Phonemes::noiseGain( i ) );
}
else if (number == __SK_ModFrequency_) // 11
voiced_->setVibratoRate( norm * 12.0); // 0 to 12 Hz
voiced_->setVibratoRate( normalizedValue * 12.0); // 0 to 12 Hz
else if (number == __SK_ModWheel_) // 1
voiced_->setVibratoGain( norm * 0.2);
voiced_->setVibratoGain( normalizedValue * 0.2);
else if (number == __SK_AfterTouch_Cont_) { // 128
this->setVoiced( norm );
onepole_.setPole( 0.97 - ( norm * 0.2) );
this->setVoiced( normalizedValue );
onepole_.setPole( 0.97 - ( normalizedValue * 0.2) );
}
#if defined(_STK_DEBUG_)
else {
errorString_ << "VoicForm::controlChange: undefined control number (" << number << ")!";
oStream_ << "VoicForm::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "VoicForm::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -19,7 +19,7 @@
Alternately, control changes can be sent to all voices in a given
group.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -30,6 +30,11 @@ namespace stk {
Voicer :: Voicer( StkFloat decayTime )
{
if ( decayTime < 0.0 ) {
oStream_ << "Voicer::Voicer: argument (" << decayTime << ") must be positive!";
handleError( StkError::FUNCTION_ARGUMENT );
}
tags_ = 23456;
muteTime_ = (int) ( decayTime * Stk::sampleRate() );
lastFrame_.resize( 1, 1, 0.0 );
@@ -73,7 +78,7 @@ void Voicer :: removeInstrument( Instrmnt *instrument )
lastFrame_.resize( 1, maxChannels );
}
else {
errorString_ << "Voicer::removeInstrument: instrument pointer not found in current voices!";
oStream_ << "Voicer::removeInstrument: instrument pointer not found in current voices!";
handleError( StkError::WARNING );
}
}

View File

@@ -1,5 +1,5 @@
/***************************************************/
/*! \class Whistle
/*! \Class Whistle
\brief STK police/referee whistle instrument class.
This class implements a hybrid physical/spectral
@@ -12,7 +12,7 @@
- Blowing Frequency Modulation = 2
- Volume = 128
by Perry R. Cook 1996 - 2010.
by Perry R. Cook 1995-2011.
*/
/***************************************************/
@@ -82,24 +82,34 @@ void Whistle :: clear( void )
void Whistle :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency * 4; // the whistle is a transposing instrument
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
errorString_ << "Whistle::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING );
freakency = 220.0;
oStream_ << "Whistle::setFrequency: parameter is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
baseFrequency_ = freakency;
baseFrequency_ = frequency * 4; // the whistle is a transposing instrument
}
void Whistle :: startBlowing( StkFloat amplitude, StkFloat rate )
{
if ( amplitude <= 0.0 || rate <= 0.0 ) {
oStream_ << "Whistle::startBlowing: one or more arguments is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
envelope_.setRate( ENV_RATE );
envelope_.setTarget( amplitude );
}
void Whistle :: stopBlowing( StkFloat rate )
{
if ( rate <= 0.0 ) {
oStream_ << "Whistle::stopBlowing: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
envelope_.setRate( rate );
envelope_.keyOff();
}
@@ -108,20 +118,11 @@ void Whistle :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
this->startBlowing( amplitude*2.0 ,amplitude * 0.2 );
#if defined(_STK_DEBUG_)
errorString_ << "Whistle::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
void Whistle :: noteOff( StkFloat amplitude )
{
this->stopBlowing( amplitude * 0.02 );
#if defined(_STK_DEBUG_)
errorString_ << "Whistle::NoteOff: amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
int frameCount = 0;
@@ -221,41 +222,34 @@ StkFloat Whistle :: tick( unsigned int )
void Whistle :: controlChange( int number, StkFloat value )
{
StkFloat norm = value * ONE_OVER_128;
if ( norm < 0 ) {
norm = 0.0;
errorString_ << "Whistle::controlChange: control value less than zero ... setting to zero!";
handleError( StkError::WARNING );
}
else if ( norm > 1.0 ) {
norm = 1.0;
errorString_ << "Whistle::controlChange: control value greater than 128.0 ... setting to 128.0!";
handleError( StkError::WARNING );
#if defined(_STK_DEBUG_)
if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
oStream_ << "Whistle::controlChange: value (" << value << ") is out of range!";
handleError( StkError::WARNING ); return;
}
#endif
StkFloat normalizedValue = value * ONE_OVER_128;
if ( number == __SK_NoiseLevel_ ) // 4
noiseGain_ = 0.25 * norm;
noiseGain_ = 0.25 * normalizedValue;
else if ( number == __SK_ModFrequency_ ) // 11
fippleFreqMod_ = norm;
fippleFreqMod_ = normalizedValue;
else if ( number == __SK_ModWheel_ ) // 1
fippleGainMod_ = norm;
fippleGainMod_ = normalizedValue;
else if ( number == __SK_AfterTouch_Cont_ ) // 128
envelope_.setTarget( norm * 2.0 );
envelope_.setTarget( normalizedValue * 2.0 );
else if ( number == __SK_Breath_ ) // 2
blowFreqMod_ = norm * 0.5;
blowFreqMod_ = normalizedValue * 0.5;
else if ( number == __SK_Sustain_ ) { // 64
subSample_ = (int) value;
if ( subSample_ < 1.0 ) subSample_ = 1;
envelope_.setRate( ENV_RATE / subSample_ );
}
#if defined(_STK_DEBUG_)
else {
errorString_ << "Whistle::controlChange: undefined control number (" << number << ")!";
oStream_ << "Whistle::controlChange: undefined control number (" << number << ")!";
handleError( StkError::WARNING );
}
#if defined(_STK_DEBUG_)
errorString_ << "Whistle::controlChange: number = " << number << ", value = " << value << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}

View File

@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2010.
by Perry R. Cook and Gary P. Scavone, 1995-2011.
*/
/***************************************************/
@@ -66,7 +66,14 @@ Wurley :: ~Wurley( void )
}
void Wurley :: setFrequency( StkFloat frequency )
{
{
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "Wurley::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
baseFrequency_ = frequency;
waves_[0]->setFrequency( baseFrequency_ * ratios_[0]);
waves_[1]->setFrequency( baseFrequency_ * ratios_[1]);
@@ -82,11 +89,6 @@ void Wurley :: noteOn( StkFloat frequency, StkFloat amplitude )
gains_[3] = amplitude * fmGains_[68];
this->setFrequency( frequency );
this->keyOn();
#if defined(_STK_DEBUG_)
errorString_ << "Wurley::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << '.';
handleError( StkError::DEBUG_WARNING );
#endif
}
} // stk namespace