mirror of
https://github.com/thestk/stk
synced 2026-01-11 20:11:52 +00:00
187 lines
5.7 KiB
C++
187 lines
5.7 KiB
C++
/***************************************************/
|
|
/*! \class Mandolin
|
|
\brief STK mandolin instrument model class.
|
|
|
|
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.
|
|
|
|
Control Change Numbers:
|
|
- Body Size = 2
|
|
- Pluck Position = 4
|
|
- String Sustain = 11
|
|
- String Detuning = 1
|
|
- Microphone Position = 128
|
|
|
|
by Perry R. Cook and Gary P. Scavone, 1995--2014.
|
|
*/
|
|
/***************************************************/
|
|
|
|
#include "Mandolin.h"
|
|
#include "SKINImsg.h"
|
|
|
|
namespace stk {
|
|
|
|
Mandolin :: Mandolin( StkFloat 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].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;
|
|
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 )
|
|
{
|
|
}
|
|
|
|
void Mandolin :: clear( void )
|
|
{
|
|
strings_[0].clear();
|
|
strings_[1].clear();
|
|
}
|
|
|
|
void Mandolin :: setPluckPosition( StkFloat position )
|
|
{
|
|
if ( position < 0.0 || position > 1.0 ) {
|
|
std::cerr << "Mandolin::setPluckPosition: position parameter out of range!";
|
|
handleError( StkError::WARNING ); return;
|
|
}
|
|
|
|
strings_[0].setPluckPosition( position );
|
|
strings_[1].setPluckPosition( position );
|
|
}
|
|
|
|
void Mandolin :: setDetune( StkFloat detune )
|
|
{
|
|
if ( detune <= 0.0 ) {
|
|
oStream_ << "Mandolin::setDeturn: parameter is less than or equal to zero!";
|
|
handleError( StkError::WARNING ); return;
|
|
}
|
|
|
|
detuning_ = detune;
|
|
strings_[1].setFrequency( frequency_ * detuning_ );
|
|
}
|
|
|
|
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 );
|
|
}
|
|
|
|
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 )
|
|
{
|
|
#if defined(_STK_DEBUG_)
|
|
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
|
|
}
|
|
|
|
} // stk namespace
|