/***************************************************** * stdMidiD.vmm * * Standaard Midi functionality. * * * * This library encapsulates "out()" function * * with more friendly procedures * * * * Written by Mark Meeus * * * * A Channel Argument should be between 1-16 * * All other arguments must be between 0-127 * * * * DEBUG VERSION!!! * * MEANING:An error message 999999 will be * * shown whenever an invalid argument * * is passed to any of these functions! * * Use this library to test your algorithm for * * any invalid MIDI Function call's. * * * * Use 'stdMidi.vmm" when you're done testing * * It should be more performant. * *****************************************************/ /**************************************************** * * PROCEDURES DEFINED IN THIS LIBRARY: * * X NoteOn(Channel,Pitch,Velocity) * * X NoteOff(Channel,Pitch) * * X AfterTouch(Channel,Pitch,Pressure) * * X ChannelPressure(Channel,Pressure) * * X Controller(Channel,ControllerNumber,Value) * * X ProgramChange(Channel,Program) * * X PitchBend(Channel,Range,Amount) * * **************************************************/ /************************************************** * CONSTANT SECTION * **************************************************/ const ERR_MESSAGE = 999999; const _7BIT_MAX = 0x7F; // MAXIMUM VALUE FOR MIDI DATA const _MIDI_CHAN_MAX = 0x10; // MAXIMUM MIDI CHANNELS const NOTE_OFF = 0x80; const NOTE_ON = 0x90; // THESE CONSTANTS const AFTERTOUCH = 0xA0; // REPRESENT THE MIDI STATUS BYTE const CONTROLLER = 0xB0; // WITHOUT THE CHANNEL NUMBER. const PROGCHANGE = 0xC0; const CHANPRESSURE = 0xD0; const PITCHBEND = 0xE0; /**************************************************** * Procedure NoteOn: * DESCRIPTION * Plays a specific note on a specific channel, * with a specifice amount of volume * * PARAMS: * Channel The channelwhere the note has to be played * Pitch The Pitch of the note to play * Velocity The volume of the note. * REMARK * Use NoteOff with same channel and note * to turn this note off. *****************************************************/ proc NoteOn(Channel,Pitch,Velocity){ // BEGIN CHECK ARGUMENTS if ((Channel < 1)||(Channel > _MIDI_CHAN_MAX)){ debug(ERR_MESSAGE); return(0); } if ((Pitch < 0)||(Pitch > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } if ((Velocity < 0)||(Velocity > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } // END CHECK out ((Velocity * 0x10000) + (((Pitch*0x100) + (Channel-1)) + NOTE_ON)); } /*************************************************** * Procedure NoteOff: * DESCRIPTION * Turns a specific note on a specific channel off * * PARAMS: * Channel The channelwhere the note is now playing * Pitch The Pitch of the note to turn off. * REMARK * This procedure has the same result as a NoteOn * with velocity 0 ***************************************************/ proc NoteOff(Channel,Pitch){ // BEGIN CHECK ARGUMENTS if ((Channel < 1)||(Channel > _MIDI_CHAN_MAX)){ debug(ERR_MESSAGE); return(0); } if ((Pitch < 0)||(Pitch > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } // END CHECK out((Pitch*0x100) + ((Channel-1) + NOTE_OFF)); } /*************************************************** * Procedure AfterTouch: * DESCRIPTION * Modifies the volume of a specific note on a * specific channel * PARAMS: * Channel The channel where the note is now playing * Pitch The Pitch of the note to change. * Pressure The amount of pressure, or volume ***************************************************/ proc AfterTouch(Channel,Pitch,Pressure){ // BEGIN CHECK ARGUMENTS if ((Channel < 1)||(Channel > _MIDI_CHAN_MAX)){ debug(ERR_MESSAGE); return(0); } if ((Pitch < 0)||(Pitch > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } if ((Pressure < 0)||(Pressure > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } // END CHECK out ((Pressure * 0x10000) + (((Pitch*0x100) + (Channel-1)) + AFTERTOUCH)); } /*************************************************** * Procedure ChannelPressure: * DESCRIPTION * Modifies the amount of pressure for * all notes on a specific channel * * PARAMS: * Channel The channel to modify. * Pressure The amount of pressure, or volume * *************************************************/ proc ChannelPressure(Channel,Pressure){ // BEGIN CHECK ARGUMENTS if ((Channel < 1)||(Channel > _MIDI_CHAN_MAX)){ debug(ERR_MESSAGE); return(0); } if ((Pressure < 0)||(Pressure > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } // END CHECK out((Pressure*0x100) + ((Channel-1) + CHANPRESSURE)); } /*************************************************** * Procedure Controller: * DESCRIPTION * Sets the value for a specific controller on a * specific channel. * * PARAMS: * Channel The channel where where the new controller value * will be applied * ControllerNumber The number of the targetted controller * Value The value of the controller * REMARK * Most controllers have a coarse and fine controller number. * If you want to use them both, call this function twice * with the 2 controllernumber. ***************************************************/ proc Controller(Channel,ControllerNumber,Value){ // BEGIN CHECK ARGUMENTS if ((Channel < 1)||(Channel > _MIDI_CHAN_MAX)){ debug(ERR_MESSAGE); return(0); } if ((ControllerNumber < 0)||(ControllerNumber > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } if ((Value < 0)||(Value > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } // END CHECK out((Value * 0x10000) + (( (ControllerNumber*0x100) + (Channel-1)) + CONTROLLER)); } /*************************************************** * Procedure ProgramChange: * DESCRIPTION * Changes the program (or instrument) * for a specific channel * * PARAMS: * Channel The channel where the new Program will * be applied. * Program the new program * * REMARK * It is possible that the targetted MIDI device has more than 128 * instruments. If so, use the Controller 'BANKSELECT' to select * a different Bank. ***************************************************/ proc ProgramChange(Channel,Program){ // BEGIN CHECK ARGUMENTS if ((Channel < 1)||(Channel > _MIDI_CHAN_MAX)){ debug(ERR_MESSAGE); return(0); } if ((Program < 0)||(Program > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } // END CHECK out((Program * 0x100) + ((Channel-1) + PROGCHANGE )); } /*************************************************** * Procedure PitchBend: * DESCRIPTION * Applies a Pitchbend on a specific channel * for a specific amount for a specific range. * * PARAMS: * Channel The channel where the PitchBend will be applied * Range the range to bend (Coarse control) * Amount The amount of pitchbend. (Fine control) * ***************************************************/ proc PitchBend(Channel,Range,Amount){ // BEGIN CHECK ARGUMENTS if ((Channel < 1)||(Channel > _MIDI_CHAN_MAX)){ debug(ERR_MESSAGE); return(0); } if ((Range < 0)||(Range > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } if ((Amount < 0)||(Amount > _7BIT_MAX)){ debug(ERR_MESSAGE); return(0); } // END CHECK out((Range * 0x10000) + (( (Amount*0x100) + (Channel-1)) + PITCHBEND)); }