/***************************************************************************
*	NAME:  IWMIDI.C $Revision: 1.3 $
**	COPYRIGHT:
**	"Copyright (c) 1994,1995 by e-Tek Labs"
**
**       "This software is furnished under a license and may be used,
**       copied, or disclosed only in accordance with the terms of such
**       license and with the inclusion of the above copyright notice.
**       This software or any other copies thereof may not be provided or
**       otherwise made available to any other person. No title to and
**       ownership of the software is hereby transfered."
****************************************************************************
* $Log: iwmidi.c $
* Revision 1.3  1995/10/13 17:31:14  mleibow
* Added controllers 91 and 93 for reverb and chorus.
* Revision 1.2  1995/05/03 08:36:44  sdsmith
* Added tremelo to mod wheel
* Revision 1.1  1995/02/23 11:07:13  unknown
* Initial revision
***************************************************************************/

#include <dos.h>
#include "iw.h"

long	iw_log_table[] =
{ 1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933 };

/*
** Pitch bend sensitivity is 2 semitones by default
*/
static unsigned int pbs_msb[16]={2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
static unsigned int pbs_lsb[16]={0};
/*
** buffer for changing registered midi parameters
*/
static int rpn_msb[16]={0};
static int rpn_lsb[16]={0};
static int nrpn_msb[16]={0};
static int nrpn_lsb[16]={0};
#define RPN  1
#define NRPN 2
static int rpn_or_nrpn = RPN;

void	iw_midi_pitch_bend( int channel, int lsb, int msb )
{
#define MID_PITCH 8192
    unsigned int bend;
    ULONG wheel;
    long sensitivity;
    unsigned int semitones;
    ULONG mantissa;
    ULONG f1, f2;
    unsigned int f1_index, f2_index, f1_power, f2_power;
    char bend_down = 0; 

    /*
    ** this equation will turn the 14 bit number into
    ** a frequency multiplier ranging from 512 to 2048 (.5 to 2).
    ** This should give a possible 1 octave swing in either
    ** direction.
    */
    if (pbs_msb[channel]) {
	wheel = ((long)msb<<7) + (long)lsb - MID_PITCH;
	sensitivity = pbs_msb[channel] * wheel;
	if (sensitivity < 0) {
	    bend_down = 1;
	    sensitivity = -sensitivity;
	}
	semitones = (unsigned int)(sensitivity >> 13);
	mantissa = sensitivity % MID_PITCH;
	f1_index = semitones % IW_LOG_TAB_SIZE;
	f2_index = (semitones + 1) % IW_LOG_TAB_SIZE;
	f1_power = semitones / IW_LOG_TAB_SIZE;
	f2_power = (semitones + 1) / IW_LOG_TAB_SIZE;
	f1 = iw_log_table[f1_index] << f1_power;
	f2 = iw_log_table[f2_index] << f2_power;
	bend = (unsigned int)((((f2 - f1) * mantissa) >> 13) + f1);
	if (bend_down) bend = (unsigned int)(1048576L / (long)bend);
    } else {
	bend = 1024;
    }
    iw_channel_pitch_bend(channel, bend);
}

void	iw_midi_parameter( int channel, int control, int value )
{
    switch (control) {
	case 1: { /* modulation wheel */
  		iw_midi_set_vibrato(channel, value);
  		iw_midi_set_tremolo(channel, value);
		break;
	    }
	case 6: /* data entry msb */
	    if (rpn_or_nrpn == RPN) {
		if (rpn_msb[channel] == 0 && rpn_lsb[channel] == 0) {
		    if (value > 24) value = 24;
		    pbs_msb[channel] = value;
		}
	    }
	    break;
	case 38: /* data entry lsb */
	    if (rpn_or_nrpn == RPN) {
		if (rpn_msb[channel] == 0 && rpn_lsb[channel] == 0) {
		    pbs_lsb[channel] = value;
		}
	    }
	    break;
	case 96: /* data increment */
	    if (rpn_or_nrpn == RPN) {
		if (rpn_msb[channel] == 0 && rpn_lsb[channel] == 0) {
		    pbs_lsb[channel] += value;
		}
	    }
	    break;
	case 97: /* data decrement */
	    if (rpn_or_nrpn == RPN) {
		if (rpn_msb[channel] == 0 && rpn_lsb[channel] == 0) {
		    pbs_lsb[channel] -= value;
		}
	    }
	    break;
	case 7: /* channel volume */
	    iw_midi_change_volume(channel, value);
	    break;
	case 39:
	    /* volume lsb ignored */
	    break;
	case 91: /* channel 1 effect (reverb) */
	    iw_midi_effect_level(channel, 1, value);
	    break;
	case 93: /* channel 3 effect (chorus) */
	    iw_midi_effect_level(channel, 3, value);
	    break;
	case 10: /* pan (balance) */
	    iw_midi_set_balance(channel, value);
	    break;
	case 11: /* channel exporession (volume) */
	    iw_midi_change_expression(channel, value);
	    break;
	case 43: /* expression lsb ignored */
	    break;
	case 64: /* sustain (damper pedal) */
	    iw_midi_channel_sustain(channel, value >= 64);
	    break;
	case 98:
	    rpn_or_nrpn = NRPN;
	    nrpn_lsb[channel]=value;
	    break;
	case 99:
	    rpn_or_nrpn = NRPN;
	    nrpn_msb[channel]=value;
	    break;
	case 100: /* set registered parameter number */
	    rpn_or_nrpn = RPN;
	    rpn_lsb[channel]=value;
	    break;
	case 101: /* set registered parameter number */
	    rpn_or_nrpn = RPN;
	    rpn_msb[channel]=value;
	    break;
	case 121: /* reset all controllers */
	    iw_midi_channel_sustain(channel, 0);
	    iw_midi_set_vibrato(channel, 0);
	    iw_midi_set_tremolo(channel, 0);
	    iw_channel_pitch_bend(channel, 1024);
	    iw_midi_change_volume(channel, 100);
	    iw_midi_change_expression(channel, 100);
	    iw_midi_set_balance(channel, 64); /* use patch builtin pan */
	    iw_midi_effect_level(channel, 1, 40); /* reverb */
	    iw_midi_effect_level(channel, 3, 0); /* chorus */
	    break;
	case 120: /* all sounds off */
	    iw_midi_all_sounds_off(channel);
	    break;
	case 123: /* all notes off */
	case 124: /* omni off */
	case 125: /* omni on */
	case 126: /* mono */
	case 127: /* mono */
	    iw_midi_all_notes_off(channel);
	    break;
    }
}
