/*=============================================================================
	CAAUMIDIMap.h
	
	$Log: CAAUMIDIMap.cpp,v $
	Revision 1.19  2004/12/10 01:24:16  bills
	tweaks to print
	
	Revision 1.18  2004/12/08 03:33:52  bills
	slight tweak to print
	
	Revision 1.17  2004/11/24 02:05:51  cbruyns
	there is no single event for on/off note matching
	
	Revision 1.16  2004/11/23 21:09:56  dwyatt
	add bipolar handling of note-on/off
	
	Revision 1.15  2004/11/13 02:15:20  bills
	tweak print
	
	Revision 1.14  2004/11/12 02:41:21  bills
	const methods
	
	Revision 1.13  2004/11/08 23:55:31  asynth
	fix warning
	
	Revision 1.12  2004/11/04 23:23:17  cbruyns
	moved save and restore to CAAEPersistence.cpp
	
	Revision 1.11  2004/11/04 21:50:22  cbruyns
	moved save and restore out of map manager.  also ignore previous CVS notes, those were for the CAServices project not these source files.
	
	Revision 1.10  2004/11/04 19:56:00  cbruyns
	moved the midi map files to the Components target
	removed AudioToolbox from AudioUnit target
	
	Revision 1.9  2004/10/26 20:56:28  cbruyns
	updated mapping passing
	
	Revision 1.8  2004/10/21 23:27:45  cbruyns
	new remove and return all
	
	Revision 1.7  2004/10/13 02:24:39  cbruyns
	midi matches update
	
	Revision 1.6  2004/10/12 22:15:45  cbruyns
	handling subrange and parameter ranges in value reporting
	
	Revision 1.5  2004/10/12 05:57:44  cbruyns
	range function begining
	
	Revision 1.4  2004/09/28 19:33:16  bills
	revise based on latest spec...
	
	Revision 1.3  2004/09/21 21:48:56  cbruyns
	Dealing with new AudioUnitProperties.h and AudioUnitParameters.h
	
	Revision 1.2  2004/09/03 21:31:07  bills
	take out NRPN handling (as its probably unnecessary at this stage)
	
	Revision 1.1  2004/09/03 18:25:10  bills
	add MIDI Matches method
	
	

	created 31 Aug 2004, William Stewart
	Copyright (c) 2004 Apple Computer, Inc.  All Rights Reserved

	$NoKeywords: $
=============================================================================*/

#include "CAAUMIDIMap.h"


static MIDILinearTransformer linearTrans; 
static MIDILogTransformer logTrans;
static MIDIExpTransformer expTrans;
static MIDISqrtTransformer sqrtTrans;
static MIDISquareTransformer squareTrans;
static MIDICubeRtTransformer cubeRtTrans;
static MIDICubeTransformer cubeTrans;

MIDIValueTransformer *	CAAUMIDIMap::GetTransformer (UInt32 inFlags)
{
	if (AudioUnitDisplayTypeIsLogarithmic(inFlags))
		return &logTrans;
	else if (AudioUnitDisplayTypeIsExponential(inFlags))
		return &expTrans;
	else if (AudioUnitDisplayTypeIsSquareRoot(inFlags))
		return &sqrtTrans;
	else if (AudioUnitDisplayTypeIsSquared(inFlags))
		return &squareTrans;
	else if (AudioUnitDisplayTypeIsCubed(inFlags))
		return &cubeTrans;
	else if (AudioUnitDisplayTypeIsCubeRoot(inFlags))
		return &cubeRtTrans;
	else
		return &linearTrans;
}

// The CALLER of this method must ensure that the status byte's MIDI Command matches!!!
bool	CAAUMIDIMap::MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const
{
	// see if the channels match first
	SInt8 chan = Channel();
	// channel matches (if chan is less than zero, "Any Channel" flag is set)
	if (chan >= 0 && chan != inChannel)
		return false;

	// match the special cases first
	if (IsKeyEvent()) {
		// we're using this key event as an on/off type switch
		if (IsBipolar()) {
			if (IsKeyPressure()){
				if (IsBipolar_OnValue()) {
					if (inData2 > 63) {
						outLinear = 1;
						return true;
					}
				} else {
					if (inData2 < 64) {
						outLinear = 0;
						return true;
					}
				}
				return false;
			}
			else {
				if (IsBipolar_OnValue()) {
					if (inData1 > 63) {
						outLinear = 1;
						return true;
					}
				} else {
					if (inData1 < 64) {
						outLinear = 0;
						return true;
					}
				}
				return false;
			}
		}
		if (IsAnyNote()) {
// not quite sure how to interpret this...
			if (IsKeyPressure())
				outLinear = inData2 / 127.0;
			else
				outLinear = inData1 / 127.0;
			return true;
		}
		if (mData1 == inData1) {
			if (IsKeyPressure())
				outLinear = inData2 / 127.0;
			else
				outLinear = 1;
			return true;
		}
		return false;
	}
	else if (IsControlChange()) {
		// controller ID matches
		if (mData1 == inData1) {
			if (IsBipolar()) {
				if (IsBipolar_OnValue()) {
					if (inData2 > 63) {
						outLinear = 1;
						return true;
					}
				} else {
					if (inData2 < 64) {
						outLinear = 0;
						return true;
					}
				}
				return false;
			}
			//printf("this in midi matches %X with ", this); 
			outLinear = inData2 / 127.; 
			return true;
		}
		return false;
	}
	
		// this just matches on the patch change value itself...
	if (IsPatchChange()) {
		if (mData1 == inData1) {
			outLinear = 1;
			return true;
		}
		return false;
	}

	// finally, for the other two, just check the bi-polar matching conditions
	// pitch bend and after touch
	if (IsBipolar()) {
		if (IsBipolar_OnValue()) {
			if (inData1 > 63) {
				outLinear = 1;
				return true;
			}
		} else {
			if (inData1 < 64) {
				outLinear = 0;
				return true;
			}
		}
		return false;
	}

	if (IsPitchBend()) {
		UInt16 value = (inData2 << 7) | inData1;
		outLinear = value / 16383.;
	}
	else if (IsChannelPressure()) {
		outLinear = inData1 / 127.0;
	}

	return true;
}


void		CAAUMIDIMap::Print () const
{
	printf ("CAAUMIDIMap:0x%X, (%lu/%lu), mParamID %lu, IsValid:%c, Status:0x%X, mData1 %d, Flags:0x%lX\n", int(this), mScope, mElement, mParameterID, (IsValid() ? 'T' : 'F'), mStatus, mData1, mFlags);
}
