Beispiel #1
0
byte metronomeTick(byte midiNote, byte volume) {
  byte i = findNoteIndex();
  initNote(i, midiNote);
  note[i].startTime = millis();
  note[i].waveform = METRONOME_WAVEFORM;
  note[i].waveformBuf = waveformBuffers[METRONOME_WAVEFORM];
  note[i].isSample = true;
  note[i].sampleLength = sampleLength[METRONOME_WAVEFORM - N_WAVEFORMS];
  note[i].envelopePhase = ATTACK;
  note[i].volIndex = volume;
  note[i].volume = volume;
  note[i].volumeNext = volume;
  setPhaseIncrement(i);
  return i;
}
Beispiel #2
0
byte doNoteOn(byte channelNum, byte midiNote, byte velocity) {
  byte i = findNoteIndex();
  if (velocity > MAX_VELOCITY) {
    velocity = MAX_VELOCITY;
  }
  initNote(i, midiNote);
  note[i].startTime = millis();
  note[i].midiChannel = channelNum;
  byte waveformNum = settings[channelNum-1].waveform;
  note[i].waveform = waveformNum;
  note[i].waveformBuf = waveformBuffers[waveformNum];
  if (waveformNum >= N_WAVEFORMS) {
    note[i].isSample = true;
    note[i].sampleLength = sampleLength[waveformNum - N_WAVEFORMS];
  }
  note[i].envelopePhase = ATTACK;
  note[i].volIndexInc = 1;
  note[i].volLevelDuration = settings[channelNum-1].attackVolLevelDuration;
  note[i].volLevelRemaining = settings[channelNum-1].attackVolLevelDuration;

  note[i].targetVolIndex = map(velocity, 0, MAX_VELOCITY, 0, MAX_NOTE_VOL);

  if ((settings[channelNum-1].attackVolLevelDuration > 0) && (!note[i].isSample)) {
    note[i].volIndex = 0;
    note[i].targetVolIndex = inverseAttackLogVolume[logVolume[note[i].targetVolIndex]];
  } else {
    // optimize if there is no attack.  go directly to target volume
    note[i].volIndex = note[i].targetVolIndex;
    note[i].volume = logVolume[note[i].volIndex];
    note[i].volumeNext = note[i].volume;
  }

  // Restart filter LFO
  lfoPhase[LFO_FILTER] = 0;
  return i;
}
Beispiel #3
0
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(&note);

		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;
}
Beispiel #4
0
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(&note);
		//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;
}