//----------------------------------------------------------------------------- // name: ksvoice.cpp // desc: sample class for Karplus Strong // // Music 256a, Fall 2009, Stanford University // http://ccrma.stanford.edu/courses/256a-fall-2009/ //----------------------------------------------------------------------------- #include "ksvoice.h" #include #include #include #include using namespace std; KSVoice::KSVoice() { // initialize members m_delay = NULL; m_delayMax = 200000; m_delayLen = 800; m_factor = .99; m_prev = 0.0; m_writer = 0; m_reader = 0; m_pluck = 0; } bool KSVoice::init( long delayLen ) { // check if( delayLen > m_delayMax ) { cerr << "BAD! requested delay length exceeds hard coded max" << endl; return false; } // set delayLen m_delayLen = delayLen; // dynamically allocate delay line m_delay = new SAMPLE[m_delayMax]; // zero out memset( m_delay, 0, m_delayMax*sizeof(SAMPLE) ); // set indices m_reader = m_writer - m_delayLen; // wrap if( m_reader < 0 ) m_reader += m_delayMax; return true; } void KSVoice::pluck() { m_pluck = m_delayLen; } void KSVoice::synthesize( SAMPLE * buffy, long numFrames ) { // sanity check assert( m_delay != NULL ); for( long i = 0; i < numFrames; i++ ) { // write into the buffer if( m_pluck > 0 ) { m_delay[m_writer] = ((SAMPLE)rand() / RAND_MAX)*2 - 1; m_pluck--; } else m_delay[m_writer] = 0.0; // feedback, attenuation, and moving average m_delay[m_writer] += m_factor * (.5 * m_delay[m_reader] + .5 * m_prev); // remember the previous output m_prev = m_delay[m_reader]; // read out of the buffer buffy[i] = m_delay[m_reader]; // increment m_writer++; m_reader++; // wrap m_writer %= m_delayMax; m_reader %= m_delayMax; } }