📄 mesh2d.cpp
字号:
/***************************************************//*! \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 "SKINI.msg"Mesh2D :: Mesh2D(short nX, short nY){ this->setNX(nX); this->setNY(nY); StkFloat pole = 0.05; short i; for (i=0; i<NYMAX; i++) { filterY_[i].setPole( pole ); filterY_[i].setGain( 0.99 ); } for (i=0; i<NXMAX; i++) { filterX_[i].setPole( pole ); filterX_[i].setGain( 0.99 ); } this->clearMesh(); counter_=0; xInput_ = 0; yInput_ = 0;}Mesh2D :: ~Mesh2D(){}void Mesh2D :: clear(){ this->clearMesh(); short i; for (i=0; i<NY_; i++) filterY_[i].clear(); for (i=0; i<NX_; i++) filterX_[i].clear(); counter_=0;}void Mesh2D :: clearMesh(){ int x, 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++) { vxp_[x][y] = 0; vxm_[x][y] = 0; vyp_[x][y] = 0; vym_[x][y] = 0; vxp1_[x][y] = 0; vxm1_[x][y] = 0; vyp1_[x][y] = 0; vym1_[x][y] = 0; } }}StkFloat Mesh2D :: energy(){ // Return total energy contained in wave variables Note that some // energy is also contained in any filter delay elements. int x, y; 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++) { t = vxp1_[x][y]; e += t*t; t = vxm1_[x][y]; e += t*t; t = vyp1_[x][y]; e += t*t; t = vym1_[x][y]; e += t*t; } } } else { // Ready for Mesh2D::tick0() to be called. for (x=0; x<NX_; x++) { for (y=0; y<NY_; y++) { t = vxp_[x][y]; e += t*t; t = vxm_[x][y]; e += t*t; t = vyp_[x][y]; e += t*t; t = vym_[x][y]; e += t*t; } } } return(e);}void Mesh2D :: setNX(short lenX){ NX_ = lenX; if ( lenX < 2 ) {#if !defined(SYMBIAN) errorString_ << "Mesh2D::setNX(" << lenX << "): Minimum length is 2!"; handleError( StkError::WARNING );#endif NX_ = 2; } else if ( lenX > NXMAX ) {#if !defined(SYMBIAN) errorString_ << "Mesh2D::setNX(" << lenX << "): Maximum length is " << NXMAX << '!';; handleError( StkError::WARNING );#endif NX_ = NXMAX; }}void Mesh2D :: setNY(short lenY){ NY_ = lenY; if ( lenY < 2 ) {#if !defined(SYMBIAN) errorString_ << "Mesh2D::setNY(" << lenY << "): Minimum length is 2!"; handleError( StkError::WARNING );#endif NY_ = 2; } else if ( lenY > NYMAX ) {#if !defined(SYMBIAN) errorString_ << "Mesh2D::setNY(" << lenY << "): Maximum length is " << NXMAX << '!';; handleError( StkError::WARNING );#endif NY_ = NYMAX; }}void Mesh2D :: setDecay(StkFloat decayFactor){ StkFloat gain = decayFactor; if ( decayFactor < 0.0 ) {#if !defined(SYMBIAN) errorString_ << "Mesh2D::setDecay: decayFactor value is less than 0.0!"; handleError( StkError::WARNING );#endif gain = 0.0; } else if ( decayFactor > 1.0 ) {#if !defined(SYMBIAN) errorString_ << "Mesh2D::setDecay decayFactor value is greater than 1.0!"; handleError( StkError::WARNING );#endif gain = 1.0; } int i; for (i=0; i<NYMAX; i++) filterY_[i].setGain( gain ); for (i=0; i<NXMAX; i++) filterX_[i].setGain( gain );}void Mesh2D :: setInputPosition(StkFloat xFactor, StkFloat yFactor){ if ( xFactor < 0.0 ) {#if !defined(SYMBIAN) errorString_ << "Mesh2D::setInputPosition xFactor value is less than 0.0!"; handleError( StkError::WARNING );#endif xInput_ = 0; } else if ( xFactor > 1.0 ) {#if !defined(SYMBIAN) errorString_ << "Mesh2D::setInputPosition xFactor value is greater than 1.0!"; handleError( StkError::WARNING );#endif xInput_ = NX_ - 1; } else xInput_ = (short) (xFactor * (NX_ - 1)); if ( yFactor < 0.0 ) {#if !defined(SYMBIAN) errorString_ << "Mesh2D::setInputPosition yFactor value is less than 0.0!"; handleError( StkError::WARNING );#endif yInput_ = 0; } else if ( yFactor > 1.0 ) {#if !defined(SYMBIAN) errorString_ << "Mesh2D::setInputPosition yFactor value is greater than 1.0!"; handleError( StkError::WARNING );#endif yInput_ = NY_ - 1; } else yInput_ = (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; }#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}StkFloat Mesh2D :: inputTick( StkFloat input ){ if ( counter_ & 1 ) { vxp1_[xInput_][yInput_] += input; vyp1_[xInput_][yInput_] += input; lastOutput_ = tick1(); } else { vxp_[xInput_][yInput_] += input; vyp_[xInput_][yInput_] += input; lastOutput_ = tick0(); } counter_++; return lastOutput_;}StkFloat Mesh2D :: computeSample(){ lastOutput_ = ((counter_ & 1) ? this->tick1() : this->tick0()); counter_++; return lastOutput_;}const StkFloat VSCALE = 0.5;StkFloat Mesh2D :: tick0(){ int x, y; StkFloat outsamp = 0; // Update junction velocities. for (x=0; x<NX_-1; x++) { for (y=0; y<NY_-1; y++) { v_[x][y] = ( vxp_[x][y] + vxm_[x+1][y] + vyp_[x][y] + vym_[x][y+1] ) * VSCALE; } } // Update junction outgoing waves, using alternate wave-variable buffers. for (x=0; x<NX_-1; x++) { for (y=0; y<NY_-1; y++) { StkFloat vxy = v_[x][y]; // Update positive-going waves. vxp1_[x+1][y] = vxy - vxm_[x+1][y]; vyp1_[x][y+1] = vxy - vym_[x][y+1]; // Update minus-going waves. vxm1_[x][y] = vxy - vxp_[x][y]; vym1_[x][y] = vxy - vyp_[x][y]; } } // Loop over velocity-junction boundary faces, update edge // reflections, with filtering. We're only filtering on one x and y // edge here and even this could be made much sparser. for (y=0; y<NY_-1; y++) { vxp1_[0][y] = filterY_[y].tick(vxm_[0][y]); vxm1_[NX_-1][y] = vxp_[NX_-1][y]; } for (x=0; x<NX_-1; x++) { vyp1_[x][0] = filterX_[x].tick(vym_[x][0]); vym1_[x][NY_-1] = vyp_[x][NY_-1]; } // Output = sum of outgoing waves at far corner. Note that the last // index in each coordinate direction is used only with the other // coordinate indices at their next-to-last values. This is because // the "unit strings" attached to each velocity node to terminate // the mesh are not themselves connected together. outsamp = vxp_[NX_-1][NY_-2] + vyp_[NX_-2][NY_-1]; return outsamp;}StkFloat Mesh2D :: tick1(){ int x, y; StkFloat outsamp = 0; // Update junction velocities. for (x=0; x<NX_-1; x++) { for (y=0; y<NY_-1; y++) { v_[x][y] = ( vxp1_[x][y] + vxm1_[x+1][y] + vyp1_[x][y] + vym1_[x][y+1] ) * VSCALE; } } // Update junction outgoing waves, // using alternate wave-variable buffers. for (x=0; x<NX_-1; x++) { for (y=0; y<NY_-1; y++) { StkFloat vxy = v_[x][y]; // Update positive-going waves. vxp_[x+1][y] = vxy - vxm1_[x+1][y]; vyp_[x][y+1] = vxy - vym1_[x][y+1]; // Update minus-going waves. vxm_[x][y] = vxy - vxp1_[x][y]; vym_[x][y] = vxy - vyp1_[x][y]; } } // Loop over velocity-junction boundary faces, update edge // reflections, with filtering. We're only filtering on one x and y // edge here and even this could be made much sparser. for (y=0; y<NY_-1; y++) { vxp_[0][y] = filterY_[y].tick(vxm1_[0][y]); vxm_[NX_-1][y] = vxp1_[NX_-1][y]; } for (x=0; x<NX_-1; x++) { vyp_[x][0] = filterX_[x].tick(vym1_[x][0]); vym_[x][NY_-1] = vyp1_[x][NY_-1]; } // Output = sum of outgoing waves at far corner. outsamp = vxp1_[NX_-1][NY_-2] + vyp1_[NX_-2][NY_-1]; return outsamp;}void Mesh2D :: controlChange(int number, StkFloat value){ StkFloat norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0;#if !defined(SYMBIAN) errorString_ << "Mesh2D::controlChange: control value less than zero ... setting to zero!"; handleError( StkError::WARNING );#endif } else if ( norm > 1.0 ) { norm = 1.0;#if !defined(SYMBIAN) errorString_ << "Mesh2D::controlChange: control value greater than 128.0 ... setting to 128.0!"; handleError( StkError::WARNING );#endif } 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 {#if !defined(SYMBIAN) errorString_ << "Mesh2D::controlChange: undefined control number (" << number << ")!"; handleError( StkError::WARNING );#endif }#if defined(_STK_DEBUG_) errorString_ << "Mesh2D::controlChange: number = " << number << ", value = " << value << "."; handleError( StkError::DEBUG_WARNING );#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -