Esempio n. 1
0
//-----------------------------------------------------------------------------------------
void MidiNotesToCC::setParameter(VstInt32 index, float value){
     
     MidiNotesToCCProgram* ap = &programs[curProgram];

    switch(index){
        case kNoteHi  :
            if (value<fNoteLo) setParameterAutomated(kNoteLo,value);
            fNoteHi  = ap->fNoteHi  = value;
            break;
        case kNoteLo  :
            if (value>fNoteHi) setParameterAutomated(kNoteHi,value);
            fNoteLo  = ap->fNoteLo  = value;
            break;
        case kVeloHi  :
            if (value<fVeloLo) setParameterAutomated(kVeloLo,value);
            fVeloHi  = ap->fVeloHi  = value;
            break;
        case kVeloLo  :
            if (value>fVeloHi) setParameterAutomated(kVeloHi,value);
            fVeloLo  = ap->fVeloLo  = value;
            break;
        case kChin    : fChin    = ap->fChin    = value; break;
        case kNCC     : fNCC     = ap->fNCC     = value; break;
        case kNCCoff  : fNCCoff  = ap->fNCCoff  = value; break;
        case kNCCHi   : fNCCHi   = ap->fNCCHi   = value; break;
        case kNCCLo   : fNCCLo   = ap->fNCCLo   = value; break;
        case kVCC     : fVCC     = ap->fVCC     = value; break;
        case kVCCoff  : fVCCoff  = ap->fVCCoff  = value; break;
        case kVCCHi   : fVCCHi   = ap->fVCCHi   = value; break;
        case kVCCLo   : fVCCLo   = ap->fVCCLo   = value; break;
        case kChout   : fChout   = ap->fChout   = value; break;
        case kThru    : fThru    = ap->fThru    = value; break;
        default : break;        
    }                        
}                         
Esempio n. 2
0
//-----------------------------------------------------------------------------------------
void ForceToRange::setParameter (VstInt32 index, float value) {
	if (index < numParams) {
		ForceToRangeProgram* ap = &programs[curProgram];
		param[index] = ap->param[index] = value;
		if (index==kHighNote) {
			if (value<param[kLowNote]) setParameterAutomated(kLowNote,value);
		}
		else if (index==kLowNote) {
			if (value>param[kHighNote]) setParameterAutomated(kHighNote,value);
		}
	}
}
Esempio n. 3
0
//-----------------------------------------------------------------------------------------
void MidiCCStepper::setParameter(VstInt32 index, float value){
	MidiCCStepperProgram* ap = &programs[curProgram];
	param[index] = ap->param[index] = value;
	switch(index) {
		 case kLowCC:
			 if (value>param[kHighCC]) setParameterAutomated(kHighCC,value);
			 break;
		 case kHighCC:
			 if (value<param[kLowCC]) setParameterAutomated(kLowCC,value);
			 break;
		 case kTimeQ: //beatdiv = "how many fit in a beat"
			 if (param[index]==0.0f)      beatdiv = 32.0f; //128th
			 else if (param[index]<0.05f) beatdiv = 24.f; //64th triplet
			 else if (param[index]<0.1f)  beatdiv = 21.33333333f; //dotted 128th
			 else if (param[index]<0.15f) beatdiv = 16.f; //64th
			 else if (param[index]<0.2f)  beatdiv = 12.f; //32nd triplet
			 else if (param[index]<0.25f) beatdiv = 10.66666667f; //dotted 64th
			 else if (param[index]<0.3f)  beatdiv = 8.f; //32nd
			 else if (param[index]<0.35f) beatdiv = 6.f; //16th triplet
			 else if (param[index]<0.4f)  beatdiv = 5.333333333f; //dotted 32nd
			 else if (param[index]<0.45)  beatdiv = 4.f; //16th
			 else if (param[index]<0.5f)  beatdiv = 3.f; //8th triplet
			 else if (param[index]<0.55f) beatdiv = 2.666666667f; //dotted 16th
			 else if (param[index]<0.6f)  beatdiv = 2.f; //8th
			 else if (param[index]<0.65f) beatdiv = 1.5f; //quarter triplet
			 else if (param[index]<0.7f)  beatdiv = 1.333333333f; //dotted 8th
			 else if (param[index]<0.75f) beatdiv = 1.f;  //quarter
			 else if (param[index]<0.8f)  beatdiv = 0.75f; //half triplet
			 else if (param[index]<0.85f) beatdiv = 0.666666667f; //dotted quarter
			 else if (param[index]<0.9f)  beatdiv = 0.5; //half
			 else if (param[index]<0.95f) beatdiv = 0.375f; //whole triplet
			 else if (param[index]<1.0f)  beatdiv = 0.333333333f; //dotted half
			 else                         beatdiv = 0.25f; //whole
			 break;
			 //case kBeatOffset:
			 //     if (param[kSync]<0.5f)
			 //        leftOverSamples = roundToInt((float)samplesPerStep*(param[kBeatOffset]/beatdiv));
			 //     break;
		 default: break;
	}
}
Esempio n. 4
0
// The user has changed some control's value
void ZynWise::ParamChanged(int index, double value)
{
	if (index < 0)
		return;

	if (index < kParamsCount)
		// notify the host
		setParameterAutomated(index, (float)value);
	else
	{
		_gui->GetView()->OnUpdate(index, value);			
	}
}
Esempio n. 5
0
//------------------------------------------------------------------------
void Midi16CCRouter::setProgram (VstInt32 program) {
	Midi16CCRouterProgram* ap = &programs[program];

	curProgram = program;
    if (automated) {
        for (int i=0;i<kNumParams;i++) {
	        setParameterAutomated (i, ap->param[i]);	
        }
        updateDisplay();
        automated=false;
    }
    else {
        for (int i=0;i<kNumParams;i++) {
	        setParameter (i, ap->param[i]);	
        }
    }
}
Esempio n. 6
0
void MidiChs::Reset() {
	setParameterAutomated (kChannel1,  CHANNEL_TO_FLOAT(0)  ); 
	setParameterAutomated (kChannel2,  CHANNEL_TO_FLOAT(1)  ); 
	setParameterAutomated (kChannel3,  CHANNEL_TO_FLOAT(2)  ); 
	setParameterAutomated (kChannel4,  CHANNEL_TO_FLOAT(3)  ); 
	setParameterAutomated (kChannel5,  CHANNEL_TO_FLOAT(4)  ); 
	setParameterAutomated (kChannel6,  CHANNEL_TO_FLOAT(5)  ); 
	setParameterAutomated (kChannel7,  CHANNEL_TO_FLOAT(6)  ); 
	setParameterAutomated (kChannel8,  CHANNEL_TO_FLOAT(7)  ); 
	setParameterAutomated (kChannel9,  CHANNEL_TO_FLOAT(8)  ); 
	setParameterAutomated (kChannel10, CHANNEL_TO_FLOAT(9) );
	setParameterAutomated (kChannel11, CHANNEL_TO_FLOAT(10) );
	setParameterAutomated (kChannel12, CHANNEL_TO_FLOAT(11) );
	setParameterAutomated (kChannel13, CHANNEL_TO_FLOAT(12) );
	setParameterAutomated (kChannel14, CHANNEL_TO_FLOAT(13) );
	setParameterAutomated (kChannel15, CHANNEL_TO_FLOAT(14) );
	setParameterAutomated (kChannel16, CHANNEL_TO_FLOAT(15) );  
	setParameterAutomated (kClear, 0.4f);
    setParameterAutomated (kReset, 0.4f);
    updateDisplay();
}
Esempio n. 7
0
void MidiChs::Clear() {
	setParameterAutomated (kChannel1,  0 ); 
	setParameterAutomated (kChannel2,  0 ); 
	setParameterAutomated (kChannel3,  0 ); 
	setParameterAutomated (kChannel4,  0 ); 
	setParameterAutomated (kChannel5,  0 ); 
	setParameterAutomated (kChannel6,  0 ); 
	setParameterAutomated (kChannel7,  0 ); 
	setParameterAutomated (kChannel8,  0 ); 
	setParameterAutomated (kChannel9,  0 ); 
	setParameterAutomated (kChannel10, 0 );
	setParameterAutomated (kChannel11, 0 );
	setParameterAutomated (kChannel12, 0 );
	setParameterAutomated (kChannel13, 0 );
	setParameterAutomated (kChannel14, 0 );
	setParameterAutomated (kChannel15, 0 );
	setParameterAutomated (kChannel16, 0 );    
	setParameterAutomated (kReset, 0.4f);
    setParameterAutomated (kClear, 0.4f);
    updateDisplay();
}
Esempio n. 8
0
void MidiSostenuto::processMidiEvents(VstMidiEventVec *inputs, VstMidiEventVec *outputs, VstInt32 sampleFrames)
{
    short outchannel = FLOAT_TO_CHANNEL015(fParam05);
    int n;
    discard=0;

    // use "Pedal Position" parameter as the pedal
    CCvalue_current = FLOAT_TO_MIDI(fParam04);
    if (CCvalue_current >= PEDAL_THRESHOLD && CCvalue_prev < PEDAL_THRESHOLD) {
        sostenuto = 1;
        for (n=0; n<128; n++) {
            sustained_notes[n] = held_notes[n];
        }
    }
    else if (CCvalue_current < PEDAL_THRESHOLD && CCvalue_prev >= PEDAL_THRESHOLD && sostenuto == 1) {
        sostenuto = 0;
        for (n=0; n<128; n++) {
            if (sustained_notes[n] == 1) {
                sustained_notes[n] = 0;
                if (held_notes[n] != 1) { //don't turn it off if it's being held manually
                    VstMidiEvent noteoffplease = inputs[0][0];
                    noteoffplease.midiData[0] = MIDI_NOTEOFF + outchannel;
                    noteoffplease.midiData[1] = n;
                    noteoffplease.midiData[2] = 0;
                    outputs[0].push_back(noteoffplease);
                }
            }
        }
    }
    CCvalue_prev = CCvalue_current;



    // process incoming events
    for (unsigned int i=0; i<inputs[0].size(); i++) {
        //copying event "i" from input (with all its fields)
        VstMidiEvent tomod = inputs[0][i];

        short status     = tomod.midiData[0] & 0xf0;   // scraping  channel
        short channel    = tomod.midiData[0] & 0x0f;   // isolating channel
        short data1      = tomod.midiData[1] & 0x7f;
        short data2		= tomod.midiData[2] & 0x7f;
        short listenCC	= FLOAT_TO_MIDI(fParam01);
        short lownote	= FLOAT_TO_MIDI(fParam02);
        short highnote	= FLOAT_TO_MIDI(fParam03);

        if (channel == outchannel) { //only look at the selected channel
            if (status == MIDI_CONTROLCHANGE && data1 == MIDI_ALL_NOTES_OFF) { //handle midi panic
                setParameter(kParam04, MIDI_TO_FLOAT(0));
                sostenuto = 0;
                for (n=0; n<128; n++) {
                    if (sustained_notes[n] == 1) {
                        sustained_notes[n] = 0;
                        VstMidiEvent noteoffplease = inputs[0][i];
                        noteoffplease.midiData[0] = MIDI_NOTEOFF + outchannel;
                        noteoffplease.midiData[1] = n;
                        noteoffplease.midiData[2] = 0;
                        outputs[0].push_back(noteoffplease);
                    }
                }
            }

            if (status == MIDI_NOTEON && data2 > 0) {
                if (data1 >= lownote && data1 <= highnote) {
                    if (sostenuto == 1) {
                        if (sustained_notes[data1] == 1) {
                            tomod.midiData[0] = MIDI_NOTEOFF + outchannel;
                            noteon_queue[data1] = 1;
                            noteon_queue_velocity[data1] = data2;
                        }
                    }
                    held_notes[data1] = 1;
                }
            }

            else if ((status == MIDI_NOTEOFF) || (status == MIDI_NOTEON && data2 == 0))	{
                held_notes[data1] = 0;
                if (sustained_notes[data1] == 1) {
                    discard = 1;
                }
            }

            else if (status == MIDI_CONTROLCHANGE && data1 == listenCC) {
                setParameterAutomated(kParam04, MIDI_TO_FLOAT(data2)); //energyXT2 used to move the slider with the CC. anybody else?
                discard = 1; //don't send the CC through
                if (data2 >= PEDAL_THRESHOLD && sostenuto == 0) {
                    sostenuto = 1;
                    for (n=0; n<128; n++) {
                        sustained_notes[n] = held_notes[n];
                    }
                }

                else if (data2 < PEDAL_THRESHOLD && sostenuto == 1) {
                    sostenuto = 0;
                    for (n=0; n<128; n++)	{
                        if (sustained_notes[n] == 1) {
                            sustained_notes[n] = 0;
                            if (held_notes[n] != 1) { //don't turn it off if it's being held manually
                                VstMidiEvent noteoffplease = inputs[0][i];
                                noteoffplease.midiData[0] = MIDI_NOTEOFF + outchannel;
                                noteoffplease.midiData[1] = n;
                                noteoffplease.midiData[2] = 0;
                                outputs[0].push_back(noteoffplease);
                            }
                        }
                    }
                }
            }
        }

        //pushing back our copied midi event from input, modified or not!
        if (discard != 1) outputs[0].push_back(tomod);
        //else discard = 0;

        //create queued events
        for (n=0; n<128; n++) {
            if (noteon_queue[n] == 1) {
                VstMidiEvent noteonplease = inputs[0][i];
                noteonplease.midiData[0] = MIDI_NOTEON + outchannel;
                noteonplease.midiData[1] = n;
                noteonplease.midiData[2] = (char)noteon_queue_velocity[n];
                outputs[0].push_back(noteonplease);
                noteon_queue[n] = 0;
            }
        }
    }
}
Esempio n. 9
0
void MidiKeySplit4::processMidiEvents(VstMidiEventVec *inputs, VstMidiEventVec *outputs, VstInt32 sampleFrames) 
{
    const char ch = FLOAT_TO_CHANNEL015(param[kInChannel]);
    signed char ch1 = FLOAT_TO_CHANNEL(param[kOutChannel1]);
    signed char ch2 = FLOAT_TO_CHANNEL(param[kOutChannel2]);
    signed char ch3 = FLOAT_TO_CHANNEL(param[kOutChannel3]);
    signed char ch4 = FLOAT_TO_CHANNEL(param[kOutChannel4]);
    const char split1 = FLOAT_TO_MIDI_X(param[kSplit1]);
    const char split2 = FLOAT_TO_MIDI_X(param[kSplit2]);
    const char split3 = FLOAT_TO_MIDI_X(param[kSplit3]);
    const char transp1 = roundToInt(96.f*param[kTransp1])-48;
    const char transp2 = roundToInt(96.f*param[kTransp2])-48;
    const char transp3 = roundToInt(96.f*param[kTransp3])-48;
    const char transp4 = roundToInt(96.f*param[kTransp4])-48;

	// process incoming events
    for (unsigned int i=0;i<inputs[0].size();i++) {
        //copying event "i" from input (with all its fields)
		VstMidiEvent tomod = inputs[0][i];

        int status     = tomod.midiData[0] & 0xf0;   // scraping  channel
        int channel    = tomod.midiData[0] & 0x0f;   // isolating channel
        int data1      = tomod.midiData[1] & 0x7f;
        int data2		 = tomod.midiData[2] & 0x7f;

        if (status==MIDI_NOTEON && data2==0) status=MIDI_NOTEOFF;
        
        if (ch1==-1) ch1=channel;
        if (ch2==-1) ch2=channel;
        if (ch3==-1) ch3=channel;
        if (ch4==-1) ch4=channel;

		if (channel==ch) { 
            if (status==MIDI_NOTEON) {
                if (split1==learn) {
                    setParameterAutomated(kSplit1,MIDI_TO_FLOAT_X(data1));
                }
                if (split2==learn) {
                    setParameterAutomated(kSplit2,MIDI_TO_FLOAT_X(data1));
                }
                if (split3==learn) {
                    setParameterAutomated(kSplit3,MIDI_TO_FLOAT_X(data1));
                }

                if (data1<split1) {
                    transposed[data1] = transp1;
                    tomod.midiData[0] = status | ch1;
                    tomod.midiData[1] = midiLimit(data1+transp1);
                }
                else if (data1<split2) {
                    transposed[data1] = transp2;
                    tomod.midiData[0] = status | ch2;
                    tomod.midiData[1] = midiLimit(data1+transp2);
                }
                else if (data1<split3) {
                    transposed[data1] = transp3;
                    tomod.midiData[0] = status | ch3;
                    tomod.midiData[1] = midiLimit(data1+transp3);
                }
                else {
                    transposed[data1] = transp4;
                    tomod.midiData[0] = status | ch4;
                    tomod.midiData[1] = midiLimit(data1+transp4);
                }
            }
            else if (status==MIDI_NOTEOFF) {
                if (data1<split1) {
                    tomod.midiData[0] = status | ch1;
                    tomod.midiData[1] = midiLimit(data1+transposed[data1]);
                    transposed[data1]=-999;
                }
                else if (data1<split2) {
                    tomod.midiData[0] = status | ch2;
                    tomod.midiData[1] = midiLimit(data1+transposed[data1]);
                    transposed[data1]=-999;
                }
                else if (data1<split3) {
                    tomod.midiData[0] = status | ch3;
                    tomod.midiData[1] = midiLimit(data1+transposed[data1]);
                    transposed[data1]=-999;
                }
                else {
                    tomod.midiData[0] = status | ch4;
                    tomod.midiData[1] = midiLimit(data1+transposed[data1]);
                    transposed[data1]=-999;
                }
            }
            if (status==MIDI_POLYKEYPRESSURE) {
                if (data1<split1) {
					tomod.midiData[0] = status | ch1;
                    tomod.midiData[1] = midiLimit(data1+transp1);
                }
                else if (data1<split2) {
                    tomod.midiData[0] = status | ch2;
                    tomod.midiData[1] = midiLimit(data1+transp2);
                }
                else if (data1<split3) {
                    tomod.midiData[0] = status | ch3;
                    tomod.midiData[1] = midiLimit(data1+transp3);
                }
                else {
                    tomod.midiData[0] = status | ch4;
                    tomod.midiData[1] = midiLimit(data1+transp4);
                }
            }
		}
	    outputs[0].push_back(tomod);
    }
}
Esempio n. 10
0
void MidiNoteGroups::processMidiEvents(VstMidiEventVec *inputs, VstMidiEventVec *outputs, VstInt32 samples)
{
     //process incoming events-------------------------------------------------------
    for (unsigned int i=0;i<inputs[0].size();i++) {
        //copying event "i" from input (with all its fields)
        VstMidiEvent tomod = inputs[0][i];

        const int channel    = tomod.midiData[0] & 0x0f;   // isolating channel (0-15)
        const int data1      = tomod.midiData[1] & 0x7f;
        const int data2	   = tomod.midiData[2] & 0x7f;
        const int status     = (tomod.midiData[0] & 0xf0)==MIDI_NOTEON && data2==0 ? MIDI_NOTEOFF : tomod.midiData[0] & 0xf0;   // scraping  channel

        int listenchannel = FLOAT_TO_CHANNEL015(param[kChannel]);
        bool discard = param[kThru]<0.5f;

        Slot slot[kNumSlots];
        for (int s=0;s<kNumSlots;s++) {
            slot[s].note = FLOAT_TO_MIDI3(param[kNote+s*3]);
            slot[s].playgroup = FLOAT_TO_GROUP(param[kPlay+s*3]);
            slot[s].chokegroup = FLOAT_TO_GROUP(param[kChoke+s*3]);
        }

        if (channel == listenchannel) {
            if (status == MIDI_NOTEON) {
                for (int i=0;i<kNumSlots;i++) {
                    if (slot[i].note==learn) {
                        discard=true;
                        setParameterAutomated(kNote+i*3,MIDI_TO_FLOAT3(data1));
                    }
                    if (data1 == slot[i].note) {
                        discard=false;
                        if (slot[i].chokegroup>-1) {
                            //end other notes in choke group
                            for (int s=0;s<kNumSlots;s++) {
                                if (slot[s].chokegroup==slot[i].chokegroup) {
                                    if (notesPlaying[slot[s].note]) {
                                        VstMidiEvent m = tomod;
                                        m.midiData[0] = MIDI_NOTEOFF | channel;
                                        m.midiData[1] = slot[s].note;
                                        m.midiData[2] = 0;
                                        outputs[0].push_back(m);
                                        notesPlaying[slot[s].note]=false;
                                    }
                                }
                            }
                        }
                        if (slot[i].playgroup>-1) {
                            //play other notes in play group
                            for (int s=0;s<kNumSlots;s++) {
                                if (slot[s].playgroup==slot[i].playgroup) {
                                    if (!notesPlaying[slot[s].note]) {
                                        VstMidiEvent m = tomod;
                                        m.midiData[0] = MIDI_NOTEON | channel;
                                        m.midiData[1] = slot[s].note;
                                        m.midiData[2] = data2;
                                        outputs[0].push_back(m);
                                        notesPlaying[slot[s].note]=true;
                                    }
                                }
                            }
                        }
                    }
                }
                if (notesPlaying[data1]) discard=true;
                if (!discard) notesPlaying[data1]=true;
            }
            else if (status == MIDI_NOTEOFF) {
                for (int i=0;i<kNumSlots;i++) {
                    if (data1 == slot[i].note) {
                        discard=false;
                        if (slot[i].playgroup>-1) {
                            //end other notes in play group
                            for (int s=0;s<kNumSlots;s++) {
                                if (slot[s].playgroup==slot[i].playgroup) {
                                    if (notesPlaying[slot[s].note]) {
                                        VstMidiEvent m = tomod;
                                        m.midiData[0] = MIDI_NOTEOFF | channel;
                                        m.midiData[1] = slot[s].note;
                                        m.midiData[2] = 0;
                                        outputs[0].push_back(m);
                                        notesPlaying[slot[s].note]=false;
                                    }
                                }
                            }
                        }
                    }
                }
                if (!notesPlaying[data1]) discard=true;
                if (!discard) notesPlaying[data1]=false;
            }
            else if (status == MIDI_PROGRAMCHANGE) {
                //end playing notes before changing program
                for (int i=0;i<128;i++) {
                    if (notesPlaying[i]) {
                        VstMidiEvent m = tomod;
                        m.midiData[0] = MIDI_NOTEOFF | channel;
                        m.midiData[1] = i;
                        m.midiData[2] = 0;
                        notesPlaying[i]=false;
                    }
                }
                if (param[kProgCh]>=0.5f) setProgram(data1);
            }
        }

        if (!discard) outputs[0].push_back(tomod);

    }//for() inputs loop

    wasplaying=isplaying;
}
Esempio n. 11
0
void MidiForceToKey::processMidiEvents(VstMidiEventVec *inputs, VstMidiEventVec *outputs, VstInt32 sampleFrames)
{
	const int tchannel = FLOAT_TO_CHANNEL(fChannel);
	const int nchannel = FLOAT_TO_CHANNEL(fNChannel);
	int transposey    = roundToInt(fTranspose*100.f)-50;
	bool noteswitch[12] = {n0>=0.5f,n1>=0.5f,n2>=0.5f,n3>=0.5f,n4>=0.5f,n5>=0.5f,
		n6>=0.5f,n7>=0.5f,n8>=0.5f,n9>=0.5f,n10>=0.5f,n11>=0.5f};

	for (unsigned int i=0;i<inputs[0].size();i++) {
		VstMidiEvent tomod = inputs[0][i];
		const int status     = tomod.midiData[0] & 0xf0;   // scraping  channel
		const int channel    = tomod.midiData[0] & 0x0f;  // isolating channel (0-15)
		const int data1      = tomod.midiData[1] & 0x7f;
		//int data2	   = tomod.midiData[2] & 0x7f;
		bool discard = false;

		if (status==MIDI_PROGRAMCHANGE)
		{
			if (data1<kNumPrograms && fUsePC>=0.5f) {
				setProgram(data1);
				updateDisplay();
			}
		}
		//set key notes based on "note channel"
		if (channel == nchannel) {
			discard = true;
			if (isNoteOn(tomod)) {
				int n = data1%12;
				if (fNChMode<0.5f && !noteswitch[n])
				{
					noteswitch[n] = true;
					setParameterAutomated(k0+n, 1.f);
				}
				else
				{
					noteswitch[n] = !noteswitch[n];
					setParameterAutomated(k0+n, noteswitch[n] ? 1.f : 0.f);
				}
			}
			else if (isNoteOff(tomod) && fNChMode<0.5f) {
				int n = data1%12;
				noteswitch[n] = false;
				setParameterAutomated(k0+n, 0.f);
			}
		}
		else {
			if (isNoteOn(tomod)) {
				if (!noteswitch[data1%12]) {
					dbg("wrong note " << data1);
					int transpose = 0;
					int j = -1;
					switch (mode)
					{
						//nearest note, down when tied (same as ndc)
					case nearest:
						discard = true;
						while (j<12) {
							if (noteswitch[(data1+j)%12]) {
								transpose = j;
								discard = false;
								break;
							}
							if (j<0) j = -j;
							else j = -j - 1;
						}
						break;
						//always up
					case alwaysup:
						j = 1;
						discard = true;
						while (j<12) {
							if (noteswitch[(data1+j)%12]) {
								transpose = j;
								discard = false;
								break;
							}
							j++;
						}
						break;
						//always down
					case alwaysdown:
						discard = true;
						while (j<12) {
							if (noteswitch[(data1+j)%12]) {
								transpose = j;
								discard = false;
								break;
							}
							j--;
						}
						break;
						//block wrong notes
					case block:
						dbg("block note");
						discard = true;
						transposed[data1][channel]=-999;
						break;
					case off:
					default:
						break;
					}
					tomod.midiData[1] = data1 + transpose;
				}
				//transpose based on notes on "transpose channel"
				if (channel==tchannel)
				{
					dbg("tchannel");
					discard=true;
					int root=FLOAT_TO_MIDI(fRoot);
					int m = 0;
					int counter=0;
					if (tomod.midiData[1] > root) {
						while (counter<(tomod.midiData[1]-root)) {
							m++;
							if (noteswitch[(root+m)%12]) counter++;
							if (tomod.midiData[1] - m == root) break;
						}
					}
					else if (tomod.midiData[1] < root) {
						while (counter>(tomod.midiData[1]-root)) {
							m++;
							if (noteswitch[(root-m)%12]) counter--;
							if (tomod.midiData[1] + m == root) break;
						}
					}
					transposey = counter;
					setParameterAutomated(kTranspose, ((float)(transposey+50))*0.01f);
				}
			}
		}
		if (!discard) {
			dbg("keep event");
			if (isNoteOn(tomod) || status==MIDI_POLYKEYPRESSURE) {
				if (transposey > 0) {
					//move the note up to the right scale degree
					int counter=0;
					int m=0;
					while (counter<transposey) {
						m++;
						if (noteswitch[(tomod.midiData[1]+m)%12]) counter++;
						if ((tomod.midiData[1]+m) == 127) break;
					}
					tomod.midiData[1] += m;
				}
				else if (transposey < 0) {
					//move the note down the scale
					int counter=0;
					int m=0;
					while (counter>transposey) {
						m++;
						if (noteswitch[(tomod.midiData[1]-m)%12]) counter--;
						if ((tomod.midiData[1]-m) == 0) break;
					}
					tomod.midiData[1] -= m;
				}
				if (isNoteOn(tomod)) 
					transposed[data1][channel] = tomod.midiData[1];
			}
			else if (isNoteOff(tomod)) {
				dbg("noteoff " << data1 << " transposed " << transposed[data1][channel]);
				if (channel == tchannel) discard = true;
				// always transpose noteoff by the same amount as the noteon was transposed
				if (transposed[data1][channel]==-999) discard = true;
				else tomod.midiData[1] = transposed[data1][channel];
				transposed[data1][channel] = data1;
			}
			if (!discard) outputs[0].push_back(tomod);
		}
	}
}