mirror of
https://github.com/thestk/stk
synced 2026-01-15 14:01:52 +00:00
Version 4.4.3
This commit is contained in:
committed by
Stephen Sinclair
parent
baca57040b
commit
0aec39260a
228
src/Mandolin.cpp
228
src/Mandolin.cpp
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user