/***************************************************/ /*! \class Mesh2D \brief Two-dimensional rectilinear waveguide mesh class. This class implements a rectilinear, two-dimensional digital waveguide mesh structure. For details, see Van Duyne and Smith, "Physical Modeling with the 2-D Digital Waveguide Mesh", Proceedings of the 1993 International Computer Music Conference. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - X Dimension = 2 - Y Dimension = 4 - Mesh Decay = 11 - X-Y Input Position = 1 by Julius Smith, 2000 - 2002. Revised by Gary Scavone for STK, 2002. */ /***************************************************/ #include "Mesh2D.h" #include "SKINImsg.h" namespace stk { Mesh2D :: Mesh2D( unsigned short nX, unsigned short 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; unsigned short i; for ( i=0; iclearMesh(); counter_ = 0; xInput_ = 0; yInput_ = 0; } Mesh2D :: ~Mesh2D( void ) { } void Mesh2D :: clear( void ) { this->clearMesh(); unsigned short i; for ( i=0; i NXMAX ) { oStream_ << "Mesh2D::setNX(" << lenX << "): Maximum length is " << NXMAX << '!'; handleError( StkError::WARNING ); return; } NX_ = lenX; } void Mesh2D :: setNY( unsigned short lenY ) { if ( lenY < 2 ) { oStream_ << "Mesh2D::setNY(" << lenY << "): Minimum length is 2!"; handleError( StkError::WARNING ); return; } else if ( lenY > NYMAX ) { oStream_ << "Mesh2D::setNY(" << lenY << "): Maximum length is " << NXMAX << '!'; handleError( StkError::WARNING ); return; } NY_ = lenY; } void Mesh2D :: setDecay( StkFloat decayFactor ) { 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 1.0 ) { oStream_ << "Mesh2D::setInputPosition xFactor value is out of range!"; handleError( StkError::WARNING ); return; } if ( yFactor < 0.0 || yFactor > 1.0 ) { oStream_ << "Mesh2D::setInputPosition yFactor value is out of range!"; handleError( StkError::WARNING ); return; } xInput_ = (unsigned short) (xFactor * (NX_ - 1)); yInput_ = (unsigned short) (yFactor * (NY_ - 1)); } void Mesh2D :: noteOn( StkFloat frequency, StkFloat amplitude ) { // Input at corner. if ( counter_ & 1 ) { vxp1_[xInput_][yInput_] += amplitude; vyp1_[xInput_][yInput_] += amplitude; } else { vxp_[xInput_][yInput_] += amplitude; vyp_[xInput_][yInput_] += amplitude; } } void Mesh2D :: noteOff( StkFloat amplitude ) { return; } StkFloat Mesh2D :: inputTick( StkFloat input ) { if ( counter_ & 1 ) { vxp1_[xInput_][yInput_] += input; vyp1_[xInput_][yInput_] += input; lastFrame_[0] = tick1(); } else { vxp_[xInput_][yInput_] += input; vyp_[xInput_][yInput_] += input; lastFrame_[0] = tick0(); } counter_++; return lastFrame_[0]; } StkFloat Mesh2D :: tick( unsigned int ) { lastFrame_[0] = ((counter_ & 1) ? this->tick1() : this->tick0()); counter_++; return lastFrame_[0]; } const StkFloat VSCALE = 0.5; StkFloat Mesh2D :: tick0( void ) { int x, y; StkFloat outsamp = 0; // Update junction velocities. for (x=0; xsetNX( (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 } } // stk namespace