/* ------------------------- chord   ------------------------------------------ */
/*                                                                              */
/* Tries to detect a chord (or any harmonic relations) of incoming notes.       */
/* Written by Olaf Matthes (olaf.matthes@gmx.de)                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* This program is free software; you can redistribute it and/or                */
/* modify it under the terms of the GNU General Public License                  */
/* as published by the Free Software Foundation; either version 2               */
/* of the License, or (at your option) any later version.                       */
/*                                                                              */
/* This program is distributed in the hope that it will be useful,              */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of               */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
/* GNU General Public License for more details.                                 */
/*                                                                              */
/* You should have received a copy of the GNU General Public License            */
/* along with this program; if not, write to the Free Software                  */
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#define MAX_POLY 32                 /* maximum number of notes played at a time */

#define kUnison 0
#define kMaj 1
#define kMin 2
#define kDim 3
#define kAug 4
#define kMaj7 5
#define kDom7  6
#define kMin7  7
#define kHalfDim7 8
#define kDim7  9
#define kMinMaj7 10
#define kMaj7s5  11
#define kMaj7b5  12
#define kDom7s5  13
#define kDom7b5  14
#define kDomb9 15
#define kMaj9  16
#define kDom9  17
#define kMin9  18
#define kHalfDim9 19
#define kMinMaj9  20
#define kDimMaj9  21
#define kMaj9b5  22
#define kDom9b5  23
#define kDom9b13  24
#define kMin9s11  25
#define kmM9b11  26
#define kMaj7b9  27
#define kMaj7s5b9  28
#define kDom7b9  29
#define kMin7b9  30
#define kMinb9s11  31
#define kHalfDimb9  32
#define kDim7b9 33
#define kMinMajb9 34 
#define kDimMajb9 35
#define kMaj7s9  36
#define kDom7s9  37
#define kMaj7s11  38
#define kMs9s11  39
#define kHDimb11 40
#define kMaj11  41
#define kDom11  42
#define kMin11  43
#define kHalfDim11 44  
#define kDim11  45
#define kMinMaj11 46 
#define kDimMaj11 47
#define kMaj11b5  48
#define kMaj11s5  49
#define kMaj11b9  50
#define kMaj11s9  51
#define kMaj11b13  52
#define kMaj11s13  53
#define kM11b5b9  54
#define kDom11b5  55
#define kDom11b9  56
#define kDom11s9  57
#define kHalfDim11b9 58
#define kDom7s11  59
#define kMin7s11  60
#define kDom13s11  61
#define kM7b913  62
#define kMaj7s13  63
#define kMaj9s13  64
#define kM7b9s13  65
#define kDom7b13  66
#define kChrom  67
#define kNone  68

#define kXX -1


static char *version = "chord v0.2, written by Olaf Matthes <olaf.matthes@gmx.de>";

static char* pitch_class[13] = {"C ", "Db ", "D ", "Eb ", "E ", "F ", "Gb ", "G ", "Ab ", "A ", "Bb ", "B ", "no root "};
static char name_class[7] = {'C', 'D', 'E', 'F', 'G', 'A', 'B'};

typedef struct {
	int  type;
	int  rootMember;
} t_type_root;
 
typedef struct chord
{
  t_object x_ob;
  t_outlet *x_outchordval;          /* chord as MIDI note number of base note */
  t_outlet *x_outchordclass;        /* class of chord's bass note */
  t_outlet *x_outchordname;         /* chord name, e.g. "Cmajor7" */
  t_outlet *x_outchordinversion;    /* inversion of the chord (root = 0, 1st = 1, 2nd = 2) */
  t_outlet *x_outchordnotes;        /* list with note numbers belonging to the chord */

  t_int    x_pitch;
  t_int    x_pc[12];                /* pitch class array */
  t_int    x_abs_pc[12];            /* pitch class array: absolute MIDI note numbers */
  t_int    x_velo;
  t_int    x_alloctable[MAX_POLY];  /* a table used to store all playing notes */
  t_int    x_poly;                  /* number of notes currently playing */
  t_atom   x_chordlist[12];			/* list that stores the note numbers for output */
  t_int    x_split;                 /* highes note number to process */

  t_int    x_chord_type;			/* chord's type (number between 0 and 68) */
  t_int    x_chord_root;            /* chord's root (pitch class) */
  t_int    x_chord_bass;            /* chord's bass note (MIDI note number) */
  t_int    x_chord_inversion;       /* chord's state of inversion (root, 1st, 2nd) */

} t_chord;

/* functions */
static void chord_kick_out_member(t_chord *x, t_int number, t_int *members);
static void chord_chord_finder(t_chord *x, t_int num_pcs);
static void chord_draw_chord_type(t_chord *x, t_int num_pcs);


static void chord_unison(t_chord *x)
{
	int i;
	int member = 0;
	for(i = 0; i < 12; i++)
		if(x->x_pc[i])
		{
			member = i;				// find pitch class
			break;
		}
	x->x_chord_type  = 0;
	x->x_chord_root  = member;
	chord_draw_chord_type(x, 1);				// output onto the screen
}

static void chord_dyad(t_chord *x)
{
	static t_type_root dyads[11] = 
	 {{ kMaj7,  1 }, { kDom7, 1 }, { kMin, 0 }, { kMaj, 0 }, { kMaj,  1 },
	  { kDom7 , 0 }, { kMaj,  0 }, { kMaj, 1 }, { kMin, 1 }, { kDom7, 0 }, { kMaj7,  0 }};
	register t_type_root* t;

	int members[2];
	int i, j = 0;
	int interval1;

	for(i = 0; i < 12; i++)
		if(x->x_pc[i]) members[j++] = i;		/* load members array with chord pitch classes */
	interval1 = members[1] - members[0];		/* calculate interval between first two members */
	interval1 = interval1 - 1;					/* reduce interval1 to start at zero */
	t = &(dyads[interval1]);					/* find TypeRoot struct for this interval */
	x->x_chord_type = t->type;
	if (interval1 == 5)
		x->x_chord_root = (members[0]+8)%12;
	else
		x->x_chord_root = members[t->rootMember];
	x->x_chord_inversion = t->rootMember;		/* get state of inversion */
	chord_draw_chord_type(x, 2);				/* output results */
}

static void chord_triad(t_chord *x)
{
	static t_type_root triads[10][10] = 
	{/* interval1 is a half step			*/
	 {{ kMaj7b9,   1 }, { kMaj9,     1 }, { kMinMaj7, 1 }, { kMaj7,     1 }, { kDom7s11,2 },
	  { kDomb9 ,   0 }, { kMaj7,     1 }, { kMaj7s5,  1 }, { kMin9,     2 }, { kMaj7b9, 0 }},
	 /* interval1 is a whole step			*/
	 {{ kMin9,     0 }, { kDom9,     0 }, { kMin7,    1 }, { kDom7,     1 }, { kDom9,   0 },
	  { kHalfDim7, 1 }, { kDom7,     1 }, { kDom9,    0 }, { kMaj9,     0 }},
	 /* interval1 is a minor third			*/
	 {{ kMaj7s5,   2 }, { kDom7,     2 }, { kDim,     0 }, { kMin,      0 }, { kMaj,    2 },
	  { kDim,      2 }, { kMin7,     0 }, { kMinMaj7, 0 }},
	 /* interval1 is a major third			*/
	 {{ kMaj7,     2 }, { kHalfDim7, 2 }, { kMaj,     0 }, { kAug,      0 }, { kMin,    2 },
	  { kDom7,     0 }, { kMaj7,     0 }},
	 /* interval1 is a perfect fourth		*/
	 {{ kDomb9,    1 }, { kDom9,     1 }, { kMin,     1 }, { kMaj,      1 }, { kDom9,   2 },
	  { kDom7s11,  1 }},
	 /* interval1 is an augmented fourth	*/
	 {{ kDom7s11,  0 }, { kDom7,     2 }, { kDim,     1 }, { kHalfDim7, 0 }, { kDomb9,  2 }},
	 /* interval1 is a perfect fifth		*/
	 {{ kMaj7,     2 }, { kMin7,     2 }, { kDom7,    0 }, { kMaj7,     0 }},
	 /* interval1 is a minor sixth			*/
	 {{ kMinMaj7,  2 }, { kDom9,     1 }, { kMaj7s5,  0 }},
	 /* interval1 is a major sixth			*/
	 {{ kMaj9,     2 }, { kMin9,     1 }},
	 /* interval1 is a minor seventh		*/
	 {{ kMaj7b9,   2 }}
	};
	register t_type_root* t;
	
	int members[3];
	int i, j = 0;
	int interval1, interval2;

	for(i = 0; i < 12; i++)
		if(x->x_pc[i]) members[j++] = i;		/* load members array with chord pitch classes */
	interval1 = members[1] - members[0];		/* calculate interval between first two members */
	interval2 = members[2] - members[0];		/* calculate interval between first and third */
	interval2 = interval2 - interval1 - 1;		/* reduce interval2 to start at zero */
	interval1 = interval1 - 1;					/* reduce interval1 to start at zero */
	t = &(triads[interval1][interval2]);		/* find TypeRoot struct for this interval vector */
	x->x_chord_type = t->type;
	x->x_chord_root = members[t->rootMember];
	switch(t->rootMember) {						/* get state of inversion */
			case 0: 
				x->x_chord_inversion = 0;
				break;
			case 1: 
				x->x_chord_inversion = 2;
				break;
			case 2: 
				x->x_chord_inversion = 1;
	}
	chord_draw_chord_type(x, 3);				/* output onto the screen */
}

static void chord_quartad(t_chord *x)
{
	static t_type_root quartads[9][9][9] =
	{
	 {/* interval1 is a half step			*/
	   {/* interval2 is a whole step		*/
		{ kM7b9s13, 2 }, { kMinMajb9,1 }, { kMaj7b9,   1 }, { kMaj7s13,  2 }, { kDimMajb9, 1 },
		{ kMaj7b9,  1 }, { kMaj7s13, 2 }, { kM7b913,   1 }, { kM7b9s13,  1 }},
	   {/* interval2 is a minor third		*/
		{ kMinMaj9, 1 }, { kMaj9,    1 }, { kHalfDimb9,0 }, { kMin7b9,   0 }, { kMaj9,     1 },
		{ kDim7b9,  0 }, { kMin7b9,  0 }, { kMinMajb9, 0 }},
	   {/* interval2 is a major third		*/
		{ kMaj7s9,  1 }, { kDom7s11, 3 }, { kDomb9,    0 }, { kMinMaj7,  1 }, { kDom7s9,   3 },
		{ kDomb9,   0 }, { kMaj7b9,  0 }},
	   {/* interval2 is a perfect fourth	*/
		{ kMaj11,   1 }, { kMaj7b5,  1 }, { kMaj7,     1 }, { kMaj7s5,   1 }, { kMin9,     3 },
		{ kMaj7s13, 1 }},
	   {/* interval2 is a tritone			*/
		{ kDimMaj9, 3 }, { kDom11,   3 }, { kDim7b9,   0 }, { kHalfDimb9,0 }, { kDimMajb9, 0 }},
	   {/* interval2 is a perfect fifth		*/
		{ kMaj11,   3 }, { kDom7s9,  3 }, { kDomb9,    0 }, { kMaj7b9,   0 }},
	   {/* interval2 is a minor sixth		*/
		{ kMaj7s9,  3 }, { kMin9,    3 }, { kMaj7s13,  1 }},
	   {/* interval2 is a major sixth		*/
		{ kMinMaj9, 3 }, { kM7b913,  0 }},
	   {/* interval2 is a minor seventh		*/
		{ kM7b9s13, 0 }}
	 },
	 {/* interval1 is a whole step			*/
	   {/* interval2 is a minor third		*/
		{ kM7b913,   2 }, { kMin7b9, 1 }, { kDomb9,    1 }, { kMin9,     0 }, { kHalfDimb9,1 },
		{ kDomb9,    1 }, { kMin9,   0 }, { kMinMaj9,  0 }},
	   {/* interval2 is a major third		*/
		{ kMin9,     1 }, { kDom9,   1 }, { kDom9,     0 }, { kDom7s5,   2 }, { kDom9,     1 },
		{ kDom9,     0 }, { kMaj9,   0 }},
	   {/* interval2 is a perfect fourth	*/
		{ kDom7s9,   1 }, { kDom11,  3 }, { kHalfDim7, 1 }, { kMin7,     1 }, { kDom9,     3 },
		{ kHalfDimb9,3 }},
	   {/* interval2 is a tritone			*/
		{ kDom11,    1 }, { kDom7b5, 3 }, { kDom7,     1 }, { kDom7s5,   1 }, { kMin7b9,   3 }},
	   {/* interval2 is a perfect fifth		*/
		{ kMaj7b5,   3 }, { kDom11,  1 }, { kDom9,     0 }, { kMaj9,     0 }},
	   {/* interval2 is a minor sixth		*/
		{ kDom7s11,  1 }, { kDom9,   3 }, { kDim7b9,   3 }},
	   {/* interval2 is a major sixth		*/
		{ kMaj9,     3 }, { kMin7b9, 3 }},
	   {/* interval2 is a minor seventh		*/
		{ kMinMajb9, 3 }}
	 },
	 {/* interval1 is a minor third			*/
	   {/* interval2 is a major third		*/
		{ kMaj7s13,  3 }, { kDim7b9,  1 }, { kDom7s9,   0 }, { kMaj7s5,   2 }, { kDim7b9,   1 },
		{ kDom7s9,   0 }, { kMaj7s9,  0 }},
	   {/* interval2 is a perfect fourth	*/
		{ kDomb9,    2 }, { kDom9,    2 }, { kMin7,     2 }, { kDom7,     2 }, { kDom11,    2 },
		{ kDom7s11,  2 }},
	   {/* interval2 is a tritone			*/
		{ kDim7b9,   2 }, { kDom7,    3 }, { kDim7,     0 }, { kHalfDim7, 0 }, { kDomb9,    3 }},
	   {/* interval2 is a perfect fifth		*/
		{ kMaj7,     3 }, { kHalfDim7,3 }, { kMin7,     0 }, { kMinMaj7,  0 }},
	   {/* interval2 is a minor sixth		*/
		{ kDomb9,    2 }, { kDom9,    2 }, { kDom7s9,   2 }},
	   {/* interval2 is a major sixth		*/
		{ kHalfDimb9,2 }, { kDomb9,   3 }},
	   {/* interval2 is a minor seventh		*/
		{ kMaj7b9,   3 }}
	 },
	 {/* interval1 is a major third			*/
	   {/* interval2 is a perfect fourth	*/
		{ kMaj7b9,   2 }, { kMaj9,    2 }, { kMinMaj7,   2 }, { kMaj7,     2 }, { kDom11,  0 },
		{ kMaj11,    0 }},
	   {/* interval2 is a tritone			*/
		{ kHalfDimb9,2 }, { kDom7s5,  3 }, { kHalfDim7,  2 }, { kDom7b5,   0 }, { kMaj7b5, 0 }},
	   {/* interval2 is a perfect fifth		*/
		{ kMaj7s5,   3 }, { kMin7,    3 }, { kDom7,      0 }, { kMaj7,     0 }},
	   {/* interval2 is a minor sixth		*/
		{ kMinMaj7,  3 }, { kDom7s5,  0 }, { kMaj7s5,    0 }},
	   {/* interval2 is a major sixth		*/
		{ kMin7b9,   2 }, { kMin9,    2 }},
	   {/* interval2 is a minor seventh		*/
		{ kMaj7s13,  0 }}
	 },
	 {/* interval1 is a perfect fourth		*/
	   {/* interval2 is a tritone			*/
		{ kDimMajb9, 2 }, { kMin7b9, 1 }, { kDomb9,  1 }, { kMaj7b5,  2 }, { kDimMaj9, 0 }},
	   {/* interval2 is a perfect fifth		*/
		{ kMin9,     1 }, { kDom9,   1 }, { kDom11,  0 }, { kDom11,   2 }},
	   {/* interval2 is a minor sixth		*/
		{ kDom7s9,   1 }, { kDom9,   3 }, { kDim7b9, 3 }},
	   {/* interval2 is a major sixth		*/
		{ kMaj9,     3 }, { kHalfDimb9,3 }},
	   {/* interval2 is a minor seventh		*/
		{ kDimMajb9, 3 }}
	 },
	 {/* interval1 is a tritone				*/
	   {/* interval2 is a perfect fifth		*/
		{ kMaj7s13,  3 }, { kHalfDimb9,1 }, { kDom7s11, 0 }, { kMaj11,   2 }},
	   {/* interval2 is a minor sixth		*/
		{ kDomb9,    2 }, { kDom9,     2 }, { kDom7s9,  2 }},
	   {/* interval2 is a major sixth		*/
		{ kDim7b9,   2 }, { kDomb9,    3 }},
	   {/* interval2 is a minor seventh		*/
		{ kMaj7b9,   3 }}
	 },
	 {/* interval1 is a perfect fifth		*/
	   {/* interval2 is a minor sixth		*/
		{ kMaj7b9,    2 }, { kMaj9,    2 }, { kMaj7s9,   2 }},
	   {/* interval2 is a major sixth		*/
		{ kMin7b9,    2 }, { kMin9,    2 }},
	   {/* interval2 is a minor seventh		*/
		{ kMaj7s13,   0 }}
	 },
	 {/* interval1 is a minor sixth			*/
	   {/* interval2 is a major sixth		*/
		{ kMinMajb9,  2 }, { kMinMaj9, 2 }},
	   {/* interval2 is a minor seventh		*/
		{ kM7b913,    3 }}
	 },
	 {/* interval1 is a major sixth			*/
	   {/* interval2 is a minor seventh		*/
		{ kM7b9s13,   2 }}
	 }
	};

	register t_type_root* t;
	
	int members[4];
	int interval1, interval2, interval3;
	int i, j = 0;
	for (i=0; i<12; i++)
		if (x->x_pc[i]) members[j++] = i;		/* load members array with chord pitch classes */
	interval1 = members[1] - members[0];		/* calculate interval between first two members */
	interval2 = members[2] - members[0];		/* calculate interval between first and third */
	interval3 = members[3] - members[0];		/* calculate interval between first and third */
	interval3 = interval3 - interval2 - 1;		/* reduce interval3 to start at zero */
	interval2 = interval2 - interval1 - 1;		/* reduce interval2 to start at zero */
	interval1 = interval1 - 1;					/* reduce interval1 to start at zero */

		/* find TypeRoot struct for this interval set */
	t = &(quartads[interval1][interval2][interval3]);
	x->x_chord_type = t->type;
	x->x_chord_root = members[t->rootMember];
	switch(t->rootMember) {						/* get state of inversion */
			case 0: 
				x->x_chord_inversion = 0;
				break;
			case 1: 
				x->x_chord_inversion = 2;
				break;
			case 2: 
				x->x_chord_inversion = 2;
				break;
			case 3: 
				x->x_chord_inversion = 1;
	}
	chord_draw_chord_type(x, 4);				/* output results */
}

static void chord_fatal_error(char* s1, char* s2)
{
	post("chord: error: %s : %s", s1, s2);
}

static void chord_quintad(t_chord *x)
{
	static int initialized = 0;
	static t_type_root quintads[8][8][8][8];
	register int i, j, k, l;
	register t_type_root *t;
	t_int members[5];
	int interval1, interval2, interval3, interval4;
	int *st;
	int maj9[5][4] = {{1,1,2,3}, {0,1,1,2}, {3,0,1,1}, {2,3,0,1}, {1,2,3,0}};
	int dom9[5][4] = {{1,1,2,2}, {1,1,1,2}, {2,1,1,1}, {2,2,1,1}, {1,2,2,1}};
	int min9[5][4] = {{1,0,3,2}, {1,1,0,3}, {2,1,1,0}, {3,2,1,1}, {0,3,2,1}};
	int had9[5][4] = {{1,0,2,3}, {1,1,0,2}, {3,1,1,0}, {2,3,1,1}, {0,2,3,1}};
	int miM9[5][4] = {{1,0,3,3}, {0,1,0,3}, {3,0,1,0}, {3,3,0,1}, {0,3,3,0}};
	int diM9[5][4] = {{1,0,2,4}, {0,1,0,2}, {4,0,1,0}, {2,4,0,1}, {0,2,4,0}};
	int M9b5[5][4] = {{1,1,1,4}, {0,1,1,1}, {4,0,1,1}, {1,4,0,1}, {1,1,4,0}};
	int D9b5[5][4] = {{1,1,1,3}, {1,1,1,1}, {3,1,1,1}, {1,3,1,1}, {1,1,3,1}};
	int mM91[5][4] = {{1,0,0,6}, {0,1,0,0}, {6,0,1,0}, {0,6,0,1}, {0,0,6,0}};
	int M7b9[5][4] = {{0,2,2,3}, {0,0,2,2}, {3,0,0,2}, {2,3,0,0}, {2,2,3,0}};
	int M5b9[5][4] = {{0,2,3,2}, {0,0,2,3}, {2,0,0,2}, {3,2,0,0}, {2,3,2,0}};
	int D7b9[5][4] = {{0,2,2,2}, {1,0,2,2}, {2,1,0,2}, {2,2,1,0}, {2,2,2,1}};
	int m7b9[5][4] = {{0,1,3,2}, {1,0,1,3}, {2,1,0,1}, {3,2,1,0}, {1,3,2,1}};
	int mb51[5][4] = {{0,1,2,0}, {4,0,1,2}, {0,4,0,1}, {2,0,4,0}, {1,2,0,4}};
	int d7b9[5][4] = {{0,1,2,3}, {1,0,1,2}, {3,1,0,1}, {2,3,1,0}, {1,2,3,1}};
	int mMb9[5][4] = {{0,1,3,3}, {0,0,1,3}, {3,0,0,1}, {3,3,0,0}, {1,3,3,0}};
	int dMb9[5][4] = {{0,1,2,4}, {0,0,1,2}, {4,0,0,1}, {2,4,0,0}, {1,2,4,0}};
	int dib9[5][4] = {{0,1,2,2}, {2,0,1,2}, {2,2,0,1}, {2,2,2,0}, {1,2,2,2}};
	int M7s9[5][4] = {{2,0,2,3}, {0,2,0,2}, {3,0,2,0}, {2,3,0,2}, {0,2,3,0}};
	int D7s9[5][4] = {{2,0,2,2}, {1,2,0,2}, {2,1,2,0}, {2,2,1,2}, {0,2,2,1}};
	int M7s1[5][4] = {{3,1,0,3}, {0,3,1,0}, {3,0,3,1}, {0,3,0,3}, {1,0,3,0}};
	int d9b3[5][4] = {{1,1,2,0}, {3,1,1,2}, {0,3,1,1}, {2,0,3,1}, {1,2,0,3}};
	int M9s3[5][4] = {{1,4,2,0}, {0,1,4,2}, {0,0,1,4}, {2,0,0,1}, {4,2,0,0}};
	int M9st[5][4] = {{1,1,5,0}, {0,1,1,5}, {0,0,1,1}, {5,0,0,1}, {1,5,0,0}};
	int s9s1[5][4] = {{2,0,1,0}, {4,2,0,1}, {0,4,2,0}, {1,0,4,2}, {0,1,0,4}};
	int h7b1[5][4] = {{2,0,1,3}, {1,2,0,1}, {3,1,2,0}, {1,3,1,2}, {0,1,3,1}};
	int M711[5][4] = {{3,0,1,3}, {0,3,0,1}, {3,0,3,0}, {1,3,0,3}, {0,1,3,0}};
	int M115[5][4] = {{1,1,0,5}, {0,1,1,0}, {5,0,1,1}, {0,5,0,1}, {1,0,5,0}};
	int d711[5][4] = {{3,0,1,2}, {1,3,0,1}, {2,1,3,0}, {1,2,1,3}, {0,1,2,1}};
	int d712[5][4] = {{1,1,0,1}, {4,1,1,0}, {1,4,1,1}, {0,1,4,1}, {1,0,1,4}};
	int d713[5][4] = {{1,1,0,4}, {1,1,1,0}, {4,1,1,1}, {0,4,1,1}, {1,0,4,1}};
	int m711[5][4] = {{2,1,1,2}, {1,2,1,1}, {2,1,2,1}, {1,2,1,2}, {1,1,2,1}};
	int m712[5][4] = {{1,0,1,1}, {4,1,0,1}, {1,4,1,0}, {1,1,4,1}, {0,1,1,4}};
	int di11[5][4] = {{1,0,1,0}, {5,1,0,1}, {0,5,1,0}, {1,0,5,1}, {0,1,0,5}};
	int mM11[5][4] = {{2,1,1,3}, {0,2,1,1}, {3,0,2,1}, {1,3,0,2}, {1,1,3,0}};
	int dM11[5][4] = {{2,1,0,4}, {0,2,1,0}, {4,0,2,1}, {0,4,0,2}, {1,0,4,0}};
	int Meb5[5][4] = {{3,0,0,4}, {0,3,0,0}, {4,0,3,0}, {0,4,0,3}, {0,0,4,0}};
	int Mes5[5][4] = {{3,0,2,2}, {0,3,0,2}, {2,0,3,0}, {2,2,0,3}, {0,2,2,0}};
	int Meb9[5][4] = {{0,2,0,5}, {0,0,2,0}, {5,0,0,2}, {0,5,0,0}, {2,0,5,0}};
	int Mes9[5][4] = {{2,0,0,5}, {0,2,0,0}, {5,0,2,0}, {0,5,0,2}, {0,0,5,0}};
	int Deb5[5][4] = {{3,0,0,3}, {1,3,0,0}, {3,1,3,0}, {0,3,1,3}, {0,0,3,1}};
	int Mes3[5][4] = {{3,0,4,0}, {0,3,0,4}, {0,0,3,0}, {4,0,0,3}, {0,4,0,0}};
	int Deb9[5][4] = {{0,2,0,4}, {1,0,2,0}, {4,1,0,2}, {0,4,1,0}, {2,0,4,1}};
	int De91[5][4] = {{0,2,0,1}, {4,0,2,0}, {1,4,0,2}, {0,1,4,0}, {2,0,1,4}};
	int Des9[5][4] = {{2,0,0,4}, {1,2,0,0}, {4,1,2,0}, {0,4,1,2}, {0,0,4,1}};
	int Ds11[5][4] = {{3,1,0,2}, {1,3,1,0}, {2,1,3,1}, {0,2,1,3}, {1,0,2,1}};
	int m7s1[5][4] = {{2,2,0,2}, {1,2,2,0}, {2,1,2,2}, {0,2,1,2}, {2,0,2,1}};
	int D3s1[5][4] = {{5,0,1,0}, {1,5,0,1}, {0,1,5,0}, {1,0,1,5}, {0,1,0,1}};
	int Mb9s[5][4] = {{0,2,5,0}, {0,0,2,5}, {0,0,0,2}, {5,0,0,0}, {2,5,0,0}};
	int D7b3[5][4] = {{3,2,0,1}, {1,3,2,0}, {1,1,3,2}, {0,1,1,3}, {2,0,1,1}};

	if (!initialized) {
		for (i=0; i<8; i++)
			for (j=0; j<8; j++)
				for (k=0; k<8; k++)
					for (l=0; l<8; l++) {
						quintads[i][j][k][l].type		= kNone;
						quintads[i][j][k][l].rootMember = kXX;
					}


		// major ninths
		for (i=0; i<5; i++) {
			st = maj9[i];
			t  = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			t->type		  = kMaj9;
			t->rootMember = i;
		}

		// dominant ninths
		for (i=0; i<5; i++) {
			st = dom9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "dom9");
			t->type		  = kDom9;
			t->rootMember = i;
		}

		// minor ninths
		for (i=0; i<5; i++) {
			st = min9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "min9");
			t->type		  = kMin9;
			t->rootMember = i;
		}

		// half diminished ninths
		for (i=0; i<5; i++) {
			st = had9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "had9");
			t->type		  = kHalfDim9;
			t->rootMember = i;
		}

		// minor/major ninths
		for (i=0; i<5; i++) {
			st = miM9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "miM9");
			t->type		  = kMinMaj9;
			t->rootMember = i;
		}

		// diminished/major ninths
		for (i=0; i<5; i++) {
			st = diM9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "diM9");
			t->type		  = kDimMaj9;
			t->rootMember = i;
		}

		// major ninth flat 5
		for (i=0; i<5; i++) {
			st = M9b5[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M9b5");
			t->type		  = kMaj9b5;
			t->rootMember = i;
		}

		// dominant ninth flat 5
		for (i=0; i<5; i++) {
			st = D9b5[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "D9b5");
			t->type		  = kDom9b5;
			t->rootMember = i;
		}

		// minor/major ninth flat 11
		for (i=0; i<5; i++) {
			st = mM91[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "mM91");
			t->type		  = kmM9b11;
			t->rootMember = i;
		}

		// major seventh flat nine
		for (i=0; i<5; i++) {
			st = M7b9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M7b9");
			t->type		  = kMaj7b9;
			t->rootMember = i;
		}

		// major seventh sharp five flat nine
		for (i=0; i<5; i++) {
			st = M5b9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M5b9");
			t->type		  = kMaj7s5b9;
			t->rootMember = i;
		}

		// dominant seventh flat nine
		for (i=0; i<5; i++) {
			st = D7b9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "D7b9");
			t->type		  = kDom7b9;
			t->rootMember = i;
		}

		// minor seventh flat nine
		for (i=0; i<5; i++) {
			t = &(quintads[m7b9[i][0]][m7b9[i][1]][m7b9[i][2]][m7b9[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "m7b9");
			t->type		  = kMin7b9;
			t->rootMember = i;
		}

		// minor flat nine sharp eleventh
		for (i=0; i<5; i++) {
			st = mb51[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "mb51");
			t->type		  = kMinb9s11;
			t->rootMember = i;
		}

		// half diminished seventh flat nine
		for (i=0; i<5; i++) {
			st = d7b9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "d7b9");
			t->type		  = kHalfDimb9;
			t->rootMember = i;
		}

		// minor/major  seventh flat nine
		for (i=0; i<5; i++) {
			st = mMb9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "mMb9");
			t->type		  = kMinMajb9;
			t->rootMember = i;
		}

		// diminished major seventh flat nine
		for (i=0; i<5; i++) {
			st = dMb9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "dMb9");
			t->type		  = kDimMajb9;
			t->rootMember = i;
		}

		// diminished seventh flat nine
		for (i=0; i<5; i++) {
			t = &(quintads[dib9[i][0]][dib9[i][1]][dib9[i][2]][dib9[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "dib9");
			t->type		  = kDim7b9;
			t->rootMember = i;
		}

		// major seventh sharp nine
		for (i=0; i<5; i++) {
			t = &(quintads[M7s9[i][0]][M7s9[i][1]][M7s9[i][2]][M7s9[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M7s9");
			t->type		  = kMaj7s9;
			t->rootMember = i;
		}

		// dominant seventh sharp nine
		for (i=0; i<5; i++) {
			t = &(quintads[D7s9[i][0]][D7s9[i][1]][D7s9[i][2]][D7s9[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "D7s9");
			t->type		  = kDom7s9;
			t->rootMember = i;
		}

		// major seventh sharp eleventh
		for (i=0; i<5; i++) {
			t = &(quintads[M7s1[i][0]][M7s1[i][1]][M7s1[i][2]][M7s1[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M7s1");
			t->type		  = kMaj7s11;
			t->rootMember = i;
		}

		// dominant ninth flat thirteenth
		for (i=0; i<5; i++) {
			st = d9b3[i];
			t  = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "d9b3");
			t->type		  = kDom9b13;
			t->rootMember = i;
		}

		// major ninth sharp thirteenth
		for (i=0; i<5; i++) {
			st = M9s3[i];
			t  = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M9s3");
			t->type		  = kMaj9s13;
			t->rootMember = i;
		}

		// major ninth sharp thirteenth
		for (i=0; i<5; i++) {
			t = &(quintads[M9st[i][0]][M9st[i][1]][M9st[i][2]][M9st[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M9st");
			t->type		  = kMaj9s13;
			t->rootMember = i;
		}

		// major chord sharp ninth sharp eleventh
		for (i=0; i<5; i++) {
			st = s9s1[i];
			t  = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "s9s1");
			t->type		  = kMs9s11;
			t->rootMember = i;
		}

		// half diminished seven flat 11
		for (i=0; i<5; i++) {
			st = h7b1[i];
			t  = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "h7b1");
			t->type		  = kHDimb11;
			t->rootMember = i;
		}

		// major eleventh
		for (i=0; i<5; i++) {
			t = &(quintads[M711[i][0]][M711[i][1]][M711[i][2]][M711[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M711");
			t->type		  = kMaj11;
			t->rootMember = i;
		}

		// major eleventh
		for (i=0; i<5; i++) {
			t = &(quintads[M115[i][0]][M115[i][1]][M115[i][2]][M115[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M711");
			t->type		  = kMaj11;
			t->rootMember = i;
		}

		// dominant eleventh
		for (i=0; i<5; i++) {
			t = &(quintads[d711[i][0]][d711[i][1]][d711[i][2]][d711[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "d711");
			t->type		  = kDom11;
			t->rootMember = i;
		}

		// dominant eleventh
		for (i=0; i<5; i++) {
			t = &(quintads[d712[i][0]][d712[i][1]][d712[i][2]][d712[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "d712");
			t->type		  = kDom11;
			t->rootMember = i;
		}

		// dominant eleventh
		for (i=0; i<5; i++) {
			st = d713[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "d713");
			t->type		  = kDom11;
			t->rootMember = i;
		}

		// minor eleventh
		for (i=0; i<5; i++) {
			t = &(quintads[m711[i][0]][m711[i][1]][m711[i][2]][m711[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "m711");
			t->type		  = kMin11;
			t->rootMember = i;
		}

		// minor eleventh
		for (i=0; i<5; i++) {
			t = &(quintads[m712[i][0]][m712[i][1]][m712[i][2]][m712[i][3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "m712");
			t->type		  = kMin11;
			t->rootMember = i;
		}

		// diminished eleventh
		for (i=0; i<5; i++) {
			st = di11[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "di11");
			t->type		  = kDim11;
			t->rootMember = i;
		}

		// minor/major eleventh
		for (i=0; i<5; i++) {
			st = mM11[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "mM11");
			t->type		  = kMinMaj11;
			t->rootMember = i;
		}

		// diminished major eleventh
		for (i=0; i<5; i++) {
			st = dM11[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "dM11");
			t->type		  = kDimMaj11;
			t->rootMember = i;
		}

		// major eleventh flat fifth
		for (i=0; i<5; i++) {
			st = Meb5[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "Meb5");
			t->type		  = kMaj11b5;
			t->rootMember = i;
		}

		// major eleventh sharp fifth
		for (i=0; i<5; i++) {
			st = Mes5[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "Mes5");
			t->type		  = kMaj11s5;
			t->rootMember = i;
		}

		// major eleventh flat ninth
		for (i=0; i<5; i++) {
			st = Meb9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "Meb9");
			t->type		  = kMaj11b9;
			t->rootMember = i;
		}

		// major eleventh sharp ninth
		for (i=0; i<5; i++) {
			st = Mes9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "Mes9");
			t->type		  = kMaj11s9;
			t->rootMember = i;
		}

		// major eleventh sharp thirteenth
		for (i=0; i<5; i++) {
			st = Mes3[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "Mes3");
			t->type		  = kMaj11s13;
			t->rootMember = i;
		}

		// dominant eleventh flat fifth
		for (i=0; i<5; i++) {
			st = Deb5[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "Deb5");
			t->type		  = kDom11b5;
			t->rootMember = i;
		}

		// dominant eleventh flat ninth
		for (i=0; i<5; i++) {
			st = Deb9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "Deb9");
			t->type		  = kDom11b9;
			t->rootMember = i;
		}

		// dominant eleventh flat ninth
		for (i=0; i<5; i++) {
			st = De91[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "De91");
			t->type		  = kDom11b9;
			t->rootMember = i;
		}

		// dominant eleventh sharp ninth
		for (i=0; i<5; i++) {
			st = Des9[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "Des9");
			t->type		  = kDom11s9;
			t->rootMember = i;
		}

		// dominant seventh sharp eleventh
		for (i=0; i<5; i++) {
			st = Ds11[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "Ds11");
			t->type		  = kDom7s11;
			t->rootMember = i;
		}

		// minor seventh sharp eleventh
		for (i=0; i<5; i++) {
			st = m7s1[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "m7s1");
			t->type		  = kMin7s11;
			t->rootMember = i;
		}

		// dominant thirteenth sharp eleventh
		for (i=0; i<5; i++) {
			st = D3s1[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "D3s1");
			t->type		  = kDom13s11;
			t->rootMember = i;
		}

		// major seventh flat ninth sharp thirteenth
		for (i=0; i<5; i++) {
			st = Mb9s[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "Mb9s");
			t->type		  = kM7b9s13;
			t->rootMember = i;
		}

		// dominant seventh flat thirteenth
		for (i=0; i<5; i++) {
			st = D7b3[i];
			t = &(quintads[st[0]][st[1]][st[2]][st[3]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "D7b3");
			t->type		  = kDom7b13;
			t->rootMember = i;
		}

		initialized = 1;
		return;
	}

	j = 0;
	for (i=0; i<12; i++)
		if (x->x_pc[i]) members[j++] = i;		/* load members array with chord pitch classes */
	interval1 = members[1] - members[0];		/* calculate interval between first two members */
	interval2 = members[2] - members[0];		/* calculate interval between first and third */
	interval3 = members[3] - members[0];		/* calculate interval between first and third */
	interval4 = members[4] - members[0];		/* calculate interval between first and fourth */
	interval4 = interval4 - interval3 - 1;		/* reduce interval4 to start at zero */
	interval3 = interval3 - interval2 - 1;		/* reduce interval3 to start at zero */
	interval2 = interval2 - interval1 - 1;		/* reduce interval2 to start at zero */
	interval1 = interval1 - 1;					/* reduce interval1 to start at zero */

	// find TypeRoot struct for this interval set
	t = &(quintads[interval1][interval2][interval3][interval4]);
	if (t->rootMember != kXX)
	{
		x->x_chord_type = t->type;
		x->x_chord_root = members[t->rootMember];
		switch(t->rootMember) {						/* get state of inversion */
			case 0: 
				x->x_chord_inversion = 0;
				break;
			case 1: 
				x->x_chord_inversion = 2;
				break;
			case 2: 
				x->x_chord_inversion = 2;
				break;
			case 3: 
				x->x_chord_inversion = 2;
				break;
			case 4: 
				x->x_chord_inversion = 1;
		}
		chord_draw_chord_type(x, 5);				/* output result */
	} else
		chord_kick_out_member(x, 5, members);
}

static void chord_sextad(t_chord *x)
{
	static int initialized = 0;
	static t_type_root sextads[7][7][7][7][7];
	register int i, j, k, l, m;
	register t_type_root *t;
	register int* st;
	t_int members[6];
	int interval1, interval2, interval3, interval4, interval5;

	int D9b3[6][5] =
		{{1,1,2,0,1}, {1,1,1,2,0}, {1,1,1,1,2}, {0,1,1,1,1}, {2,0,1,1,1}, {1,2,0,1,1}};
	int m9s1[6][5] =
		{{1,0,2,0,2}, {1,1,0,2,0}, {2,1,1,0,2}, {0,2,1,1,0}, {2,0,2,1,1}, {0,2,0,2,1}};
	int M711[6][5] =
		{{1,1,0,1,3}, {0,1,1,0,1}, {3,0,1,1,0}, {1,3,0,1,1}, {0,1,3,0,1}, {1,0,1,3,0}};
	int D711[6][5] =
		{{1,1,0,1,2}, {1,1,1,0,1}, {2,1,1,1,0}, {1,2,1,1,1}, {0,1,2,1,1}, {1,0,1,2,1}};
	int hd11[6][5] =
		{{1,0,1,0,3}, {1,1,0,1,0}, {3,1,1,0,1}, {0,3,1,1,0}, {1,0,3,1,1}, {0,1,0,3,1}};
	int M1b5[6][5] =
		{{1,1,0,0,4}, {0,1,1,0,0}, {4,0,1,1,0}, {0,4,0,1,1}, {0,0,4,0,1}, {1,0,0,4,0}};
	int M159[6][5] =
		{{0,2,0,0,4}, {0,0,2,0,0}, {4,0,0,2,0}, {0,4,0,0,2}, {0,0,4,0,0}, {2,0,0,4,0}};
	int M1s3[6][5] =
		{{1,1,0,4,0}, {0,1,1,0,4}, {0,0,1,1,0}, {4,0,0,1,1}, {0,4,0,0,1}, {1,0,4,0,0}};
	int hd19[6][5] =
		{{0,1,1,0,3}, {1,0,1,1,0}, {3,1,0,1,1}, {0,3,1,0,1}, {1,0,3,1,0}, {1,1,0,3,1}};
	int M1b3[6][5] =
		{{3,0,1,0,2}, {0,3,0,1,0}, {2,0,3,0,1}, {0,2,0,3,0}, {1,0,2,0,3}, {0,1,0,2,0}};
	int D1b5[6][5] =
		{{1,1,0,0,3}, {1,1,1,0,0}, {3,1,1,1,0}, {0,3,1,1,1}, {0,0,3,1,1}, {1,0,0,3,1}};
	int D1s9[6][5] =
		{{2,0,0,1,2}, {1,2,0,0,1}, {2,1,2,0,0}, {1,2,1,2,0}, {0,1,2,1,2}, {0,0,1,2,1}};
	int m791[6][5] =
		{{0,1,2,0,2}, {1,0,1,2,0}, {2,1,0,1,2}, {0,2,1,0,1}, {2,0,2,1,0}, {1,2,0,2,1}};
	int d7s1[6][5] =
		{{1,1,1,0,2}, {1,1,1,1,0}, {2,1,1,1,1}, {0,2,1,1,1}, {1,0,2,1,1}, {1,1,0,2,1}};
	int d3s1[6][5] =
		{{3,1,0,1,0}, {1,3,1,0,1}, {0,1,3,1,0}, {1,0,1,3,1}, {0,1,0,1,3}, {1,0,1,0,1}};


	if (!initialized) {
		for (i=0; i<7; i++)
			for (j=0; j<7; j++)
				for (k=0; k<7; k++)
					for (l=0; l<7; l++) 
						for (m=0; m<7; m++) {
							sextads[i][j][k][l][m].type		= kNone;
							sextads[i][j][k][l][m].rootMember = kXX;
						}

		// dominant ninth flat thirteen
		for (i=0; i<6; i++) {
			st = D9b3[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "D9b3");
			t->type		  = kDom9b13;
			t->rootMember = i;
		}

		// minor ninth sharp eleventh
		for (i=0; i<6; i++) {
			st = m9s1[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "m9s1");
			t->type		  = kMin9s11;
			t->rootMember = i;
		}

		// major eleventh
		for (i=0; i<6; i++) {
			st = M711[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M711");
			t->type		  = kMaj11;
			t->rootMember = i;
		}

		// dominant eleventh
		for (i=0; i<6; i++) {
			st = D711[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "D711");
			t->type		  = kDom11;
			t->rootMember = i;
		}

		// half diminished eleventh
		for (i=0; i<6; i++) {
			st = hd11[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "hd11");
			t->type		  = kHalfDim11;
			t->rootMember = i;
		}

		// major eleventh flat 5
		for (i=0; i<6; i++) {
			st = M1b5[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M1b5");
			t->type		  = kMaj11b5;
			t->rootMember = i;
		}

		// major eleventh flat 5 flat 9
		for (i=0; i<6; i++) {
			st = M159[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M159");
			t->type		  = kM11b5b9;
			t->rootMember = i;
		}

		// major eleventh sharp 13
		for (i=0; i<6; i++) {
			st = M1s3[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M1s3");
			t->type		  = kMaj11s13;
			t->rootMember = i;
		}

		// half diminished eleventh flat 9
		for (i=0; i<6; i++) {
			st = hd19[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "hd19");
			t->type		  = kHalfDim11b9;
			t->rootMember = i;
		}

		// major eleventh flat 13
		for (i=0; i<6; i++) {
			st = M1b3[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "M1b3");
			t->type		  = kMaj11b13;
			t->rootMember = i;
		}

		// dominant eleventh flat five
		for (i=0; i<6; i++) {
			st = D1b5[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "D1b5");
			t->type		  = kDom11b5;
			t->rootMember = i;
		}

		// dominant eleventh sharp nine
		for (i=0; i<6; i++) {
			st = D1s9[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "D1s9");
			t->type		  = kDom11s9;
			t->rootMember = i;
		}

		// minor seventh flat 9 sharp 11
		for (i=0; i<6; i++) {
			st = m791[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "m791");
			t->type		  = kMinb9s11;
			t->rootMember = i;
		}

		// dominant seventh sharp 11
		for (i=0; i<6; i++) {
			st = d7s1[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "d7s1");
			t->type		  = kDom7s11;
			t->rootMember = i;
		}

		// dominant thirteenth sharp 11
		for (i=0; i<6; i++) {
			st = d3s1[i];
			t = &(sextads[st[0]][st[1]][st[2]][st[3]][st[4]]);
			if (t->type != kNone) chord_fatal_error("redefining chord", "d3s1");
			t->type		  = kDom13s11;
			t->rootMember = i;
		}

		initialized = 1;
		return;
	}

	j = 0;
	for (i=0; i<12; i++)
		if (x->x_pc[i]) members[j++] = i;		// load members array with chord pitch classes
	interval1 = members[1] - members[0];		// calculate interval between first two members
	interval2 = members[2] - members[0];		// calculate interval between first and third
	interval3 = members[3] - members[0];		// calculate interval between first and third
	interval4 = members[4] - members[0];		// calculate interval between first and fourth
	interval5 = members[5] - members[0];		// calculate interval between first and fifth
	interval5 = interval5 - interval4 - 1;		// reduce interval5 to start at zero
	interval4 = interval4 - interval3 - 1;		// reduce interval4 to start at zero
	interval3 = interval3 - interval2 - 1;		// reduce interval3 to start at zero
	interval2 = interval2 - interval1 - 1;		// reduce interval2 to start at zero
	interval1 = interval1 - 1;					// reduce interval1 to start at zero

	// find TypeRoot struct for this interval set
	t = &(sextads[interval1][interval2][interval3][interval4][interval5]);
	if (t->rootMember != kXX) {
		x->x_chord_type = t->type;
		x->x_chord_root = members[t->rootMember];
		switch(t->rootMember) {						/* get state of inversion */
			case 0: 
				x->x_chord_inversion = 0;
				break;
			case 1: 
				x->x_chord_inversion = 2;
				break;
			case 2: 
				x->x_chord_inversion = 2;
				break;
			case 3: 
				x->x_chord_inversion = 2;
				break;
			case 4: 
				x->x_chord_inversion = 2;
				break;
			case 5: x->x_chord_inversion = 1;
		}
		chord_draw_chord_type(x, 6);						// output onto the screen
	} else
		chord_kick_out_member(x, 6, members);
}

static int chord_accidental(t_int pc)
{
	switch (pc) {
		case  0:
		case  2:
		case  4:
		case  5:
		case  7:
		case  9:
		case 11:	return 0;
		case  1:
		case  3:
		case  6:
		case  8:
		case 10:	
		default:	return 1;
	}
}

static int chord_name_third(t_chord *x, char* chord, int c, int rootName)
{
	int third = (x->x_chord_root+4)%12;		// look for major third
	if (x->x_pc[third]) {					// if one is there
		x->x_pc[third] = 0;					// erase from pcs array
		chord[c++] = name_class[(rootName+2)%7];
		if (chord_accidental(third)) {			// if it has an chord_accidental
			// make it a flat if the root also has an chord_accidental
			if (chord_accidental(x->x_chord_root)) 
				chord[c++] = 'b';
			// otherwise make it a sharp
			else					   
				chord[c++] = '#';
		}
		chord[c++] = ' ';
		return c;						// return if major third found
	}

	third = (x->x_chord_root+3)%12;			// no major, look for minor third
	if (x->x_pc[third]) {					// if one is there
		x->x_pc[third] = 0;					// erase from pcs array
		chord[c++] = name_class[(rootName+2)%7];
		if (chord_accidental(third))			// if it has an chord_accidental
			chord[c++] = 'b'; else		// make it a flat
		if (chord_accidental(x->x_chord_root)) {	// if the root has an chord_accidental
			chord[c++] = 'b';			// make the third a flat
			if (chord[0] == 'G')		// if the root is Gb
				chord[c++] = 'b';		// this must be Bbb
		}
		chord[c++] = ' ';
		return c;
	}

	return c;							// if we get here there was no third
}

static int chord_name_fifth(t_chord *x, char* chord, int c, int rootName)
{
	int fifth = (x->x_chord_root+7)%12;
	if (x->x_pc[fifth]) {
		x->x_pc[fifth] = 0;
		chord[c++] = name_class[(rootName+4)%7];
		if (chord_accidental(fifth)) {
			if (chord_accidental(x->x_chord_root)) chord[c++] = 'b';
			else					   chord[c++] = '#';
		}
		chord[c++] = ' ';
		return c;
	}

	fifth = (x->x_chord_root+6)%12;
	if (x->x_pc[fifth]) {
		x->x_pc[fifth] = 0;
		chord[c++] = name_class[(rootName+4)%7];
		if (chord[0] != 'B')	   chord[c++] = 'b';
		if (chord_accidental(x->x_chord_root)) chord[c++] = 'b';
		chord[c++] = ' ';
		return c;
	}
	
	fifth = (x->x_chord_root+8)%12;
	if (x->x_pc[fifth]) {
		x->x_pc[fifth] = 0;
		chord[c++] = name_class[(rootName+4)%7];
		if (chord_accidental(fifth)) chord[c++] = '#'; else
		if (!chord_accidental(x->x_chord_root)) {
			chord[c++] = '#';
			if (chord[0] == 'B')
				chord[c++] = '#';
		}
		chord[c++] = ' ';
		return c;
	}
	
	return c;
}

static int chord_name_seventh(t_chord *x, char* chord, int c, int rootName)
{
	int seventh = (x->x_chord_root+11)%12;
	if (x->x_pc[seventh]) {
		x->x_pc[seventh] = 0;
		chord[c++] = name_class[(rootName+6)%7];
		if (chord_accidental(seventh)) chord[c++] = '#';
		chord[c++] = ' ';
		return c;
	}
	seventh = (x->x_chord_root+10)%12;
	if (x->x_pc[seventh]) {
		x->x_pc[seventh] = 0;
		chord[c++]   = name_class[(rootName+6)%7];
		if (chord_accidental(seventh) || chord_accidental(x->x_chord_root))
			chord[c++] = 'b';
		chord[c++]   = ' ';
		return c;
	}
	seventh = (x->x_chord_root+9)%12;
	if (x->x_pc[seventh]) {
		x->x_pc[seventh] = 0;
		chord[c++] = name_class[(rootName+6)%7];
		chord[c++] = 'b';
		if (chord_accidental(x->x_chord_root))		chord[c++] = 'b'; else
		if (chord_accidental((seventh+1)%12)) chord[c++] = 'b';
		chord[c++] = ' ';
		return c;
	}
	return c;
}

static int chord_name_ninth(t_chord *x, char* chord, int c, int rootName)
{
	int ninth = (x->x_chord_root+2)%12;
	if (x->x_pc[ninth]) {
		x->x_pc[ninth] = 0;
		chord[c++] = name_class[(rootName+1)%7];
		if (chord_accidental(ninth)) {
			if (chord_accidental(x->x_chord_root)) chord[c++] = 'b';
			else					   chord[c++] = '#';
		}
		chord[c++] = ' ';
		return c;
	}

	ninth = (x->x_chord_root+1)%12;
	if (x->x_pc[ninth]) {
		x->x_pc[ninth] = 0;
		chord[c++] = name_class[(rootName+1)%7];
		if (chord_accidental(ninth)) chord[c++] = 'b';
		else {
			if (chord_accidental(x->x_chord_root)) {
				chord[c++] = 'b';
				if ((x->x_chord_root == 1) || (x->x_chord_root == 6) || (x->x_chord_root == 8))
					chord[c++] = 'b';
			}
		}
		chord[c++] = ' ';
		return c;
	}

	ninth = (x->x_chord_root+3)%12;
	if (x->x_pc[ninth]) {
		x->x_pc[ninth] = 0;
		chord[c++] = name_class[(rootName+1)%7];
		if (chord_accidental(ninth)) chord[c++] = '#'; else
		if (!chord_accidental(x->x_chord_root)) {
			chord[c++] = '#';
			if (chord_accidental((x->x_chord_root+2)%12))
				chord[c++] = '#';
		}
		chord[c++] = ' ';
		return c;
	}

	return c;
}

static int chord_name_eleventh(t_chord *x, char* chord, int c, int rootName)
{
	int eleventh = (x->x_chord_root+5)%12;
	if (x->x_pc[eleventh]) {
		x->x_pc[eleventh] = 0;
		chord[c++] = name_class[(rootName+3)%7];
		if (chord_accidental(eleventh))  chord[c++] = 'b'; else
		if (chord_accidental(x->x_chord_root)) chord[c++] = 'b';
		chord[c++] = ' ';
		return c;
	}
	
	eleventh = (x->x_chord_root+6)%12;
	if (x->x_pc[eleventh]) {
		x->x_pc[eleventh] = 0;
		chord[c++] = name_class[(rootName+3)%7];
		if (chord_accidental(eleventh))  chord[c++] = '#'; else
		if ((!chord_accidental(x->x_chord_root)) && (x->x_chord_root == 11))
			chord[c++] = '#';
		chord[c++] = ' ';
		return c;
	}

	return c;
}

static int chord_name_thirteenth(t_chord *x, char* chord, int c, int rootName)
{
	int thirteenth = (x->x_chord_root+9)%12;
	if (x->x_pc[thirteenth]) {
		x->x_pc[thirteenth] = 0;
		chord[c++] = name_class[(rootName+5)%7];
		if (chord_accidental(thirteenth)) {
			if (chord_accidental(x->x_chord_root))
				chord[c++] = 'b'; 
			else
				chord[c++] = '#';
		}
		
		chord[c++] = ' ';
		return c;
	}
	
	thirteenth = (x->x_chord_root+10)%12;
	if (x->x_pc[thirteenth]) {
		x->x_pc[thirteenth] = 0;
		chord[c++] = name_class[(rootName+5)%7];
		if (chord_accidental(thirteenth)) chord[c++] = '#'; else
		if (!chord_accidental(x->x_chord_root)) {
			chord[c++] = '#';
			if (chord_accidental((x->x_chord_root+9)%12))
				chord[c++] = '#';
		}
		chord[c++] = ' ';
		return c;
	}

	thirteenth = (x->x_chord_root+8)%12;
	if (x->x_pc[thirteenth]) {
		x->x_pc[thirteenth] = 0;
		chord[c++] = name_class[(rootName+5)%7];
		if (chord_accidental(thirteenth)) chord[c++] = 'b'; else
		if (chord_accidental(x->x_chord_root)) {
			chord[c++] = 'b';
			if (chord_accidental(x->x_chord_root+9)%12)
				chord[c++] = 'b';
		}
		chord[c++] = ' ';
		return c;
	}

	return c;
}



static void chord_spell_chord(t_chord *x, char *chord, t_int num_pcs)
{
	int rootName = 0;			// keep index of root name class
	int c     = 0;				// pointer to current character
	int named = 0;				// how many members have been named
	int mark;
	int i;

	// use chordRoot to set rootName index and store characters for name
	switch (x->x_chord_root)
	{
		case 0:		chord[c++] = name_class[rootName=0];	break;
		case 1:		chord[c++] = name_class[rootName=1];
				chord[c++] = 'b';			break;
		case 2:		chord[c++] = name_class[rootName=1];	break;
		case 3:		chord[c++] = name_class[rootName=2];
				chord[c++] = 'b';			break;
		case 4:		chord[c++] = name_class[rootName=2];	break;
		case 5:		chord[c++] = name_class[rootName=3];	break;
		case 6:		chord[c++] = name_class[rootName=4];
				chord[c++] = 'b';			break;
		case 7:		chord[c++] = name_class[rootName=4];	break;
		case 8:		chord[c++] = name_class[rootName=5];
				chord[c++] = 'b';			break;
		case 9:		chord[c++] = name_class[rootName=5];	break;
		case 10:	chord[c++] = name_class[rootName=6];
				chord[c++] = 'b';			break;
		case 11:	chord[c++] = name_class[rootName=6];	break;
		default:						break;
	}
	x->x_pc[x->x_chord_root] = 0;					/* set this member to zero */

	chord[c++] = ' ';			// insert space
	if (++named == num_pcs) {	// if everything is named
		chord[c] = '\0';		// terminate the string
		return;					// and return
	}

	mark = c;				// use mark to see if new names are added
	for (i=0; i<6; i++) {
		// advance search by thirds
		switch (i) {
			case 0:	mark = chord_name_third	 (x, chord, c, rootName); break;
			case 1:	mark = chord_name_fifth	 (x, chord, c, rootName); break;
			case 2:	mark = chord_name_seventh	 (x, chord, c, rootName); break;
			case 3:	mark = chord_name_ninth	 (x, chord, c, rootName); break;
			case 4:	mark = chord_name_eleventh	 (x, chord, c, rootName); break;
			case 5:	mark = chord_name_thirteenth(x, chord, c, rootName); break;
		}
		if (mark != c) {		// if new name is added
			++named;			// increment count of named members
			c = mark;			// update character pointer
		}
		if (named == num_pcs) {	// if everything is named
			chord[c] = '\0';	// terminate the string
			return;				// and return
		}
	}

	chord[c] = '\0';
}


static void chord_draw_chord_type(t_chord *x, t_int num_pcs)
{
	char   chord[255];				/* output string */
	int i, j;

		/* get members of chord */
	j = 0;
	for(i = 0; i < 12; i++)
	{
		if(x->x_pc[i])
		{
			SETFLOAT(x->x_chordlist+j, x->x_abs_pc[i]);
			j++;
		}
	}

	if (x->x_chord_type != kNone)
	{
		chord_spell_chord(x, chord, num_pcs);	/* spell chord members */
	}
	else
	{
		post("going...");
		chord[0] = '\0';
		for(i = 0; i < 12; i++)
			if (x->x_pc[i]) 
				strcat(chord, pitch_class[i]);	/* output single notes */
		post("did it");
	}

	strcat(chord, ": ");
	strcat(chord, pitch_class[x->x_chord_root]);
	
		/* append name of chord type */
	switch (x->x_chord_type) {
		case kUnison:	strcat(chord, "unison"); 			  break;
		case kMaj:		strcat(chord, "major"); 			  break;
		case kMin:		strcat(chord, "minor"); 			  break;
		case kDim:		strcat(chord, "diminished"); 		  break;
		case kAug:		strcat(chord, "augmented"); 		  break;

		case kMaj7:		strcat(chord, "major 7th"); 		  break;
		case kDom7:		strcat(chord, "dominant 7th"); 		  break;
		case kMin7: 	strcat(chord, "minor 7th"); 		  break;
		case kHalfDim7:	strcat(chord, "half diminished 7th"); break;
		case kDim7:		strcat(chord, "diminished 7th");	  break;
		case kMinMaj7:	strcat(chord, "minor/major 7th");	  break;

		case kMaj7s5:	strcat(chord, "major 7th #5");		  break;
		case kMaj7b5:	strcat(chord, "major 7th b5");		  break;
		case kDom7s5:	strcat(chord, "dominant 7th #5"); 	  break;
		case kDom7b5:	strcat(chord, "dominant 7th b5"); 	  break;
		case kDomb9:	strcat(chord, "dominant b9");		  break;

		case kMaj9:		strcat(chord, "major 9th");			  break;
		case kDom9:		strcat(chord, "dominant 9th");		  break;
		case kMin9:		strcat(chord, "minor 9th");			  break;
		case kHalfDim9:	strcat(chord, "half diminished 9th"); break;
		case kMinMaj9:	strcat(chord, "minor major 9th");	  break;
		case kDimMaj9:	strcat(chord, "diminished major 9th");break;
		case kMaj9b5:	strcat(chord, "major 9th b5");		  break;
		case kDom9b5:	strcat(chord, "dominant 9th b5");	  break;
		case kDom9b13:	strcat(chord, "dominant 9th b13");	  break;
		case kMin9s11:	strcat(chord, "minor 9th #11");		  break;
		case kmM9b11:	strcat(chord, "minor/maj 9th b11");	  break;

		case kMaj7b9:	strcat(chord, "major 7th b9");		  break;
		case kMaj7s5b9:	strcat(chord, "major 7th #5 b9");	  break;
		case kDom7b9:	strcat(chord, "dominant 7th b9");	  break;
		case kMin7b9:	strcat(chord, "minor 7th b9");		  break;
		case kMinb9s11:	strcat(chord, "minor b9 #11");		  break;
		case kHalfDimb9:strcat(chord, "half diminished b9");  break;
		case kDim7b9:	strcat(chord, "diminished b9");		  break;
		case kMinMajb9: strcat(chord, "minor/major b9");	  break;
		case kDimMajb9:	strcat(chord, "diminished M7 b9");	  break;

		case kMaj7s9:	strcat(chord, "major 7th #9");		  break;
		case kDom7s9:	strcat(chord, "dominant #9");		  break;
		case kMaj7s11:	strcat(chord, "major 7th #11");		  break;
		case kMaj9s13:	strcat(chord, "major 9th #13");		  break;
		case kMs9s11:	strcat(chord, "major #9 #11");		  break;
		case kHDimb11:	strcat(chord, "half diminished b11"); break;

		case kMaj11:	strcat(chord, "major 11th");		  break;
		case kDom11:	strcat(chord, "dominant 11th");		  break;
		case kMin11:	strcat(chord, "minor 11th");		  break;
		case kHalfDim11:strcat(chord, "half diminished 11th");break;
		case kDim11:	strcat(chord, "diminished 11th");	  break;
		case kMinMaj11:	strcat(chord, "minor/major 11th");	  break;
		case kDimMaj11: strcat(chord, "diminished maj 11th"); break;

		case kMaj11b5:	strcat(chord, "major 11th b5");		  break;
		case kMaj11s5:	strcat(chord, "major 11th #5");		  break;
		case kMaj11b9:	strcat(chord, "major 11th b9");		  break;
		case kMaj11s9:	strcat(chord, "major 11th #9");		  break;
		case kMaj11b13:	strcat(chord, "major 11th b13");	  break;
		case kMaj11s13:	strcat(chord, "major 11th #13");	  break;
		case kM11b5b9:	strcat(chord, "major 11th b5 b9");	  break;
		case kDom11b5:	strcat(chord, "dominant 11th b5");	  break;
		case kDom11b9:	strcat(chord, "dominant 11th b9");	  break;
		case kDom11s9:	strcat(chord, "dominant 11th #9");	  break;
		case kHalfDim11b9:strcat(chord, "half dim 11th b9");  break;
		case kDom7s11:	strcat(chord, "dominant #11");		  break;
		case kMin7s11:	strcat(chord, "minor 7th #11");		  break;

		case kDom13s11:	strcat(chord, "dominant 13th #11");	  break;
		case kM7b913:	strcat(chord, "major 7 b9 13");		  break;
		case kMaj7s13:	strcat(chord, "major 7th #13");		  break;
		case kM7b9s13:	strcat(chord, "major 7 b9 #13");	  break;
		case kDom7b13:	strcat(chord, "dominant 7th b13");	  break;
		case kChrom:	strcat(chord, "chromatic");			  break;
		case kNone:
		default:	 	strcat(chord, "unknown"); 			  break;
	}

	x->x_chord_bass = x->x_abs_pc[x->x_chord_root];	/* get MIDI note number of bass */

		/* output results */
	outlet_list(x->x_outchordnotes, NULL, j, x->x_chordlist);
	outlet_float(x->x_outchordinversion, x->x_chord_inversion);
	outlet_symbol(x->x_outchordname, gensym(chord));
	outlet_float(x->x_outchordclass, x->x_chord_root);
	outlet_float(x->x_outchordval, x->x_chord_bass);
}

static void chord_kick_out_member(t_chord *x, t_int number, t_int *members)
{
	int *distances;
	int minDistance = 1000;
	int badMember   = 0;
	int i, j, interval;

	distances = getbytes(number*sizeof(int));
	
	for (i=0; i<number; i++) {
		// initialize total distance to zero
		distances[i] = 0;
		for (j=0; j<number; j++)
			if (j != i) {
				// get absolute value of interval size
				interval = abs(members[i] - members[j]);
				// make inversions of intervals equivalent
				if (interval > 6) interval = 12 - interval;
				// add absolute interval size to total
				distances[i] += interval;
			}
		
		// if this is the smallest total distance
		if (distances[i] < minDistance) {
			// remember it
			minDistance = distances[i];
			badMember   = i;
		}
	}
	freebytes(distances, number * sizeof(int));
	x->x_pc[members[badMember]] = 0;			// cancel out most dissonant member
	chord_chord_finder(x, number-1);			// call chord finder again without it
	x->x_pc[members[badMember]] = 1;			// replace most dissonant member
}

static void chord_chord_finder(t_chord *x, t_int num_pcs)
{
	int i;
	x->x_chord_type = kNone;
	x->x_chord_root = kXX;	/* none */
	switch (num_pcs) {
		case  1:	chord_unison(x);	break;
		case  2:	chord_dyad(x);		break;
		case  3:	chord_triad(x);		break;
		case  4:	chord_quartad(x);	break;
		case  5:	chord_quintad(x);	break;
		case  6:	chord_sextad(x);	break;
		default:	x->x_chord_type = kChrom;
					for(i = 0; i < 12; i++)   // 12 was num_pcs !?
					{
						if(x->x_pc[i])
						{
							x->x_chord_root = i;
							break;
						}
					}
	}
}

static void chord_float(t_chord *x, t_floatarg f)
{
	t_int velo = x->x_velo;
	t_int allloc = 0;
	t_int num_pc = 0;	/* number of pitch classes present */
	int i, j, k, l;

	x->x_pitch = (t_int)f;

	if(x->x_pitch <= x->x_split)
	{
			/* first we need to put the note into the allocation table */
		if(velo == 0)	/* got note-off: remove from allocation table */
		{
			if(x->x_poly > 0)x->x_poly--; /* polyphony has decreased by one */
			for(i = 0; i < MAX_POLY; i++) /* search for voice allocation number */
			{
					/* search for corresponding alloc number */
				if(x->x_alloctable[i] == x->x_pitch)
				{
					x->x_alloctable[i] = -1;     /* free the alloc number */
					break;
				}
					/* couldn't find it ? */
				if(i == MAX_POLY - 1)
				{
					post("chord: no corresponding note-on found (ignored)");
					return;
				}
			}
			return;		/* no need to look for chord */
		}
		else	/* we got a note-on message */
		{
			if(x->x_poly == MAX_POLY)
			{
				post("chord: too many note-on messages (ignored)");
				return;
			}
			
			x->x_poly++;      /* number of currently playing notes has increased */
				/* assign a voice allocation number */
			for(i = 0; i < MAX_POLY; i++)
			{
					/* search for free alloc number */
				if(x->x_alloctable[i] == -1)
				{
					x->x_alloctable[i] = x->x_pitch;   /* ... and store pitch */
					break;
				}
			}
				/* copy all notes into the pitch class array */
			for(i = 0; i < 12; i++)
			{
				x->x_pc[i] = 0;						/* empty pitch class */
				x->x_abs_pc[i] = -1;				/* empty absolute values */
			}
			for(i = 0; i < MAX_POLY; i++)
			{
					/* check for presence of pitch class */
				if(x->x_alloctable[i] != -1)
				{
					if(!x->x_pc[x->x_alloctable[i]%12])	/* a new pitch class */
					{
						x->x_abs_pc[x->x_alloctable[i]%12] = x->x_alloctable[i];
					}
					else if(x->x_abs_pc[x->x_alloctable[i]%12] > x->x_alloctable[i])	/* remember lowest pitch */
					{
						x->x_abs_pc[x->x_alloctable[i]%12] = x->x_alloctable[i];
					}

					x->x_pc[x->x_alloctable[i]%12] = 1;	/* indicate presence of pc */
				}
			}
				/* count number of pitch classes */
			for(i = 0; i < 12; i++)
			{
				num_pc += x->x_pc[i];
			}
			// post("%d pitch classes", num_pc);
		}
	}

	chord_chord_finder(x, num_pc);
}

static void chord_ft1(t_chord *x, t_floatarg f)
{
	x->x_velo = (t_int)f;
}

static t_class *chord_class;

static void *chord_new(t_floatarg f)
{
	int i;
    t_chord *x = (t_chord *)pd_new(chord_class);
    inlet_new(&x->x_ob, &x->x_ob.ob_pd, gensym("float"), gensym("ft1"));
	x->x_outchordval = outlet_new(&x->x_ob, gensym("float"));
	x->x_outchordclass = outlet_new(&x->x_ob, gensym("float"));
	x->x_outchordname = outlet_new(&x->x_ob, gensym("symbol"));
	x->x_outchordinversion = outlet_new(&x->x_ob, gensym("float"));
	x->x_outchordnotes = outlet_new(&x->x_ob, gensym("float"));

	x->x_split = (t_int)f;
	if(x->x_split == 0)x->x_split = 128;
	for(i = 0; i < MAX_POLY; i++)x->x_alloctable[i] = -1;
    
    return (void *)x;
}

#ifndef MAXLIB
void chord_setup(void)
{
    chord_class = class_new(gensym("chord"), (t_newmethod)chord_new,
    	0, sizeof(t_chord), 0, A_DEFFLOAT, 0);
#else
void maxlib_chord_setup(void)
{
    chord_class = class_new(gensym("maxlib_chord"), (t_newmethod)chord_new,
    	0, sizeof(t_chord), 0, A_DEFFLOAT, 0);
#endif
    class_addfloat(chord_class, chord_float);
    class_addmethod(chord_class, (t_method)chord_ft1, gensym("ft1"), A_FLOAT, 0);
#ifndef MAXLIB
    
    logpost(NULL, 4, version);
#else
	class_addcreator((t_newmethod)chord_new, gensym("chord"), A_DEFFLOAT, 0);
    class_sethelpsymbol(chord_class, gensym("maxlib/chord-help.pd"));
#endif
}

