void lb302Synth::processNote( NotePlayHandle * _n ) { /// Start a new note. if( _n->m_pluginData != this ) { m_playingNote = _n; new_freq = true; _n->m_pluginData = this; } if( ! m_playingNote && ! _n->isReleased() && release_frame > 0 ) { m_playingNote = _n; if ( slideToggle.value() ) { vco_slideinc = GET_INC( _n->frequency() ); } } // Check for slide if( m_playingNote == _n ) { true_freq = _n->frequency(); if( slideToggle.value() ) { vco_slidebase = GET_INC( true_freq ); // The REAL frequency } else { vco_inc = GET_INC( true_freq ); } } }
void lb302Synth::playNote( notePlayHandle * _n, sampleFrame * _working_buffer ) { //fpp_t framesPerPeriod = engine::getMixer()->framesPerPeriod(); if( _n->isArpeggioBaseNote() ) { return; } // Currently have release/decay disabled // Start the release decay if this is the first release period. //if (_n->released() && catch_decay == 0) // catch_decay = 1; bool decay_note = false; release_frame = _n->framesLeft() - desiredReleaseFrames(); //LB303 if ( _n->totalFramesPlayed() <= 0 ) { // This code is obsolete, hence the "if false" // Existing note. Allow it to decay. if(deadToggle.value() == 0 && decay_note) { /* lb302Note note; note.vco_inc = _n->frequency()*vco_detune/engine::getMixer()->processingSampleRate(); // TODO: Use actual sampling rate. note.dead = deadToggle.value(); initNote(¬e); vca_mode=0; */ } /// Start a new note. else if( _n->totalFramesPlayed() == 0 ) { new_freq = _n->unpitchedFrequency(); true_freq = _n->frequency(); _n->m_pluginData = this; } // Check for slide if( _n->unpitchedFrequency() == current_freq ) { true_freq = _n->frequency(); if( slideToggle.value() ) { vco_slidebase = GET_INC( true_freq ); // The REAL frequency } else { vco_inc = GET_INC( true_freq ); } } //LB303 } }
void lb303Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) { if( _n->arpBaseNote() ) { //return; } // Currently have release/decay disabled // Start the release decay if this is the first release period. //if (_n->released() && catch_decay == 0) // catch_decay = 1; bool decay_note = false; release_frame = _n->framesLeft() - desiredReleaseFrames(); if(deadToggle.value() == 0 && decay_note) { } /// Start a new note. else if( _n->totalFramesPlayed() == 0 ) { new_freq = _n->unpitchedFrequency(); true_freq = _n->frequency(); _n->m_pluginData = this; } // Check for slide if( _n->unpitchedFrequency() == current_freq ) { true_freq = _n->frequency(); if( slideToggle.value() ) { vco_slidebase = GET_INC( true_freq ); // The REAL frequency } else { vco_inc = GET_INC( true_freq ); } } }
int lb302Synth::process(sampleFrame *outbuf, const int size) { const float sampleRatio = 44100.f / engine::mixer()->processingSampleRate(); float w; float samp; // Hold on to the current VCF, and use it throughout this period lb302Filter *filter = vcf; if( release_frame == 0 || ! m_playingNote ) { vca_mode = 1; } if( new_freq ) { //printf(" playing new note..\n"); lb302Note note; note.vco_inc = GET_INC( true_freq ); note.dead = deadToggle.value(); initNote(¬e); new_freq = false; } // TODO: NORMAL RELEASE // vca_mode = 1; for( int i=0; i<size; i++ ) { // start decay if we're past release if( i >= release_frame ) { vca_mode = 1; } // update vcf if(vcf_envpos >= ENVINC) { filter->envRecalc(); vcf_envpos = 0; if (vco_slide) { vco_inc = vco_slidebase - vco_slide; // Calculate coeff from dec_knob on knob change. vco_slide -= vco_slide * ( 0.1f - slide_dec_knob.value() * 0.0999f ) * sampleRatio; // TODO: Adjust for ENVINC } } sample_cnt++; vcf_envpos++; //int decay_frames = 128; // update vco vco_c += vco_inc; if(vco_c > 0.5) vco_c -= 1.0; switch(int(rint(wave_shape.value()))) { case 0: vco_shape = SAWTOOTH; break; case 1: vco_shape = TRIANGLE; break; case 2: vco_shape = SQUARE; break; case 3: vco_shape = ROUND_SQUARE; break; case 4: vco_shape = MOOG; break; case 5: vco_shape = SINE; break; case 6: vco_shape = EXPONENTIAL; break; case 7: vco_shape = WHITE_NOISE; break; case 8: vco_shape = BL_SAWTOOTH; break; case 9: vco_shape = BL_SQUARE; break; case 10: vco_shape = BL_TRIANGLE; break; case 11: vco_shape = BL_MOOG; break; default: vco_shape = SAWTOOTH; break; } // add vco_shape_param the changes the shape of each curve. // merge sawtooths with triangle and square with round square? switch (vco_shape) { case SAWTOOTH: // p0: curviness of line vco_k = vco_c; // Is this sawtooth backwards? break; case TRIANGLE: // p0: duty rev.saw<->triangle<->saw p1: curviness vco_k = (vco_c*2.0)+0.5; if (vco_k>0.5) vco_k = 1.0- vco_k; break; case SQUARE: // p0: slope of top vco_k = (vco_c<0)?0.5:-0.5; break; case ROUND_SQUARE: // p0: width of round vco_k = (vco_c<0)?(sqrtf(1-(vco_c*vco_c*4))-0.5):-0.5; break; case MOOG: // Maybe the fall should be exponential/sinsoidal instead of quadric. // [-0.5, 0]: Rise, [0,0.25]: Slope down, [0.25,0.5]: Low vco_k = (vco_c*2.0)+0.5; if (vco_k>1.0) { vco_k = -0.5 ; } else if (vco_k>0.5) { w = 2.0*(vco_k-0.5)-1.0; vco_k = 0.5 - sqrtf(1.0-(w*w)); } vco_k *= 2.0; // MOOG wave gets filtered away break; case SINE: // [-0.5, 0.5] : [-pi, pi] vco_k = 0.5f * Oscillator::sinSample( vco_c ); break; case EXPONENTIAL: vco_k = 0.5 * Oscillator::expSample( vco_c ); break; case WHITE_NOISE: vco_k = 0.5 * Oscillator::noiseSample( vco_c ); break; case BL_SAWTOOTH: vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLSaw ) * 0.5f; break; case BL_SQUARE: vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLSquare ) * 0.5f; break; case BL_TRIANGLE: vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLTriangle ) * 0.5f; break; case BL_MOOG: vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLMoog ); break; } //vca_a = 0.5; // Write out samples. #ifdef LB_FILTERED //samp = vcf->process(vco_k)*2.0*vca_a; //samp = vcf->process(vco_k)*2.0; samp = filter->process(vco_k) * vca_a; //printf("%f %d\n", vco_c, sample_cnt); //samp = vco_k * vca_a; if( sample_cnt <= 4 ) { // vca_a = 0; } #else //samp = vco_k*vca_a; #endif /* float releaseFrames = desiredReleaseFrames(); samp *= (releaseFrames - catch_decay)/releaseFrames; */ //LB302 samp *= (float)(decay_frames - catch_decay)/(float)decay_frames; for( int c = 0; c < DEFAULT_CHANNELS; c++ ) { outbuf[i][c] = samp; } // Handle Envelope if(vca_mode==0) { vca_a+=(vca_a0-vca_a)*vca_attack; if(sample_cnt>=0.5*engine::mixer()->processingSampleRate()) vca_mode = 2; } else if(vca_mode == 1) { vca_a *= vca_decay; // the following line actually speeds up processing if(vca_a < (1/65536.0)) { vca_a = 0; vca_mode = 3; } } } return 1; }
int lb302Synth::process(sampleFrame *outbuf, const Uint32 size) { unsigned int i; float w; float samp; if( delete_freq == current_freq ) { // Normal release delete_freq = -1; vca_mode = 1; } if( new_freq > 0.0f ) { //printf(" playing new note..\n"); lb302Note note; note.vco_inc = GET_INC( true_freq ); //printf("GET_INC %f %f %d\n", note.vco_inc, new_freq, vca_mode ); ///**vco_detune*//engine::getMixer()->processingSampleRate(); // TODO: Use actual sampling rate. //printf("VCO_INC = %f\n", note.vco_inc); note.dead = deadToggle.value(); initNote(¬e); //printf("%f %f, ", vco_inc, vco_c); current_freq = new_freq; new_freq = -1.0f; //printf("GOT_INC %f %f %d\n\n", note.vco_inc, new_freq, vca_mode ); } // TODO: NORMAL RELEASE // vca_mode = 1; for(i=0;i<size;i++) { // update vcf if(vcf_envpos >= ENVINC) { vcf->envRecalc(); vcf_envpos = 0; if (vco_slide) { vco_inc=vco_slidebase-vco_slide; // Calculate coeff from dec_knob on knob change. vco_slide*= 0.9+(slide_dec_knob.value()*0.0999); // TODO: Adjust for Hz and ENVINC } } sample_cnt++; vcf_envpos++; //int decay_frames = 128; // update vco vco_c += vco_inc; if(vco_c > 0.5) vco_c -= 1.0; /*LB303 if (catch_decay > 0) { if (catch_decay < decay_frames) { catch_decay++; } }*/ switch(int(rint(wave_shape.value()))) { case 0: vco_shape = SAWTOOTH; break; case 1: vco_shape = TRIANGLE; break; case 2: vco_shape = SQUARE; break; case 3: vco_shape = ROUND_SQUARE; break; case 4: vco_shape = MOOG; break; case 5: vco_shape = SINE; break; case 6: vco_shape = EXPONENTIAL; break; case 7: vco_shape = WHITE_NOISE; break; default: vco_shape = SAWTOOTH; break; } // add vco_shape_param the changes the shape of each curve. // merge sawtooths with triangle and square with round square? switch (vco_shape) { case SAWTOOTH: // p0: curviness of line vco_k = vco_c; // Is this sawtooth backwards? break; case TRIANGLE: // p0: duty rev.saw<->triangle<->saw p1: curviness vco_k = (vco_c*2.0)+0.5; if (vco_k>0.5) vco_k = 1.0- vco_k; break; case SQUARE: // p0: slope of top vco_k = (vco_c<0)?0.5:-0.5; break; case ROUND_SQUARE: // p0: width of round vco_k = (vco_c<0)?(sqrtf(1-(vco_c*vco_c*4))-0.5):-0.5; break; case MOOG: // Maybe the fall should be exponential/sinsoidal instead of quadric. // [-0.5, 0]: Rise, [0,0.25]: Slope down, [0.25,0.5]: Low vco_k = (vco_c*2.0)+0.5; if (vco_k>1.0) { vco_k = -0.5 ; } else if (vco_k>0.5) { w = 2.0*(vco_k-0.5)-1.0; vco_k = 0.5 - sqrtf(1.0-(w*w)); } vco_k *= 2.0; // MOOG wave gets filtered away break; case SINE: // [-0.5, 0.5] : [-pi, pi] vco_k = 0.5f * Oscillator::sinSample( vco_c ); break; case EXPONENTIAL: vco_k = 0.5 * Oscillator::expSample( vco_c ); break; case WHITE_NOISE: vco_k = 0.5 * Oscillator::noiseSample( vco_c ); break; } //vca_a = 0.5; // Write out samples. #ifdef LB_FILTERED //samp = vcf->process(vco_k)*2.0*vca_a; //samp = vcf->process(vco_k)*2.0; samp = vcf->process(vco_k) * vca_a; //printf("%f %d\n", vco_c, sample_cnt); //samp = vco_k * vca_a; if( sample_cnt <= 4 ) { // vca_a = 0; } #else //samp = vco_k*vca_a; #endif /* float releaseFrames = desiredReleaseFrames(); samp *= (releaseFrames - catch_decay)/releaseFrames; */ //LB302 samp *= (float)(decay_frames - catch_decay)/(float)decay_frames; for(int c=0; c<DEFAULT_CHANNELS; c++) { outbuf[i][c]=samp; } /*LB303 if((int)i>=release_frame) { vca_mode=1; } */ // Handle Envelope if(vca_mode==0) { vca_a+=(vca_a0-vca_a)*vca_attack; if(sample_cnt>=0.5*engine::getMixer()->processingSampleRate()) vca_mode = 2; } else if(vca_mode == 1) { vca_a *= vca_decay; // the following line actually speeds up processing if(vca_a < (1/65536.0)) { vca_a = 0; vca_mode = 3; } } } return 1; }