[PD-cvs] externals/frankenstein GArhythm.c, NONE, 1.1 Makefile, NONE, 1.1 README.txt, NONE, 1.1 SHOWME.pd, NONE, 1.1 bay.orc, NONE, 1.1 chord_melo.c, NONE, 1.1 chord_melo_test3.pd, NONE, 1.1 chords_memory.c, NONE, 1.1 harmonizer.c, NONE, 1.1 makefile.darwin, NONE, 1.1 manager.pd, NONE, 1.1 ritmo1.c, NONE, 1.1 sglib.h, NONE, 1.1 test-chords_graph.pd, NONE, 1.1 test-harmonizer.pd, NONE, 1.1 test-harmonizer2.pd, NONE, 1.1 test.graph, NONE, 1.1

dmorelli morellid at users.sourceforge.net
Wed Oct 19 01:10:55 CEST 2005


Update of /cvsroot/pure-data/externals/frankenstein
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2493

Added Files:
	GArhythm.c Makefile README.txt SHOWME.pd bay.orc chord_melo.c 
	chord_melo_test3.pd chords_memory.c harmonizer.c 
	makefile.darwin manager.pd ritmo1.c sglib.h 
	test-chords_graph.pd test-harmonizer.pd test-harmonizer2.pd 
	test.graph 
Log Message:
initial checkin

--- NEW FILE: SHOWME.pd ---
#N canvas 63 95 785 518 12;
#X obj 513 100 tabwrite src;
#X obj 644 87 tabwrite dest;
#N canvas 0 0 450 300 graph25 0;
#X array src 16 float 1;
#A 0 53 52 55 53 52 50 48 47 48 55 57 59 60 55 52 48;
#X array dest 16 float 1;
#A 0 53 50 52 38 64 46 43 41 48 64 67 67 36 55 53 57;
#X coords 0 127 15 0 400 250 1;
#X restore 75 32 graph;
#X obj 572 38 tgl 15 0 empty empty START 0 -6 0 8 -258699 -1 -1 1 1
;
#X floatatom 550 138 5 0 0 0 - - -;
#X floatatom 596 138 5 0 0 0 - - -;
#X floatatom 648 137 5 0 0 0 - - -;
#X obj 591 279 tgl 15 0 toggleSRC empty src 0 -6 0 8 -262144 -1 -1
0 1;
#X obj 627 279 tgl 15 0 toggleOUT empty out 0 -6 0 8 -262144 -1 -1
1 1;
#X obj 572 56 chord_melo_test3;
#X floatatom 613 213 5 0 0 0 current_melo - -;
#X connect 3 0 9 0;
#X connect 9 0 4 0;
#X connect 9 0 0 0;
#X connect 9 1 1 0;
#X connect 9 1 5 0;
#X connect 9 2 10 0;
#X connect 9 3 0 1;
#X connect 9 3 1 1;
#X connect 9 3 6 0;

--- NEW FILE: manager.pd ---
#N canvas 494 138 557 435 12;
#X obj 136 186 select 0;
#X obj 124 266 random 2;
#X obj 137 211 t a a a;
#X obj 137 235 bang;
#X obj 140 130 inlet;
#X obj 133 304 outlet;
#X msg 250 143 0;
#X connect 0 0 2 0;
#X connect 1 0 5 0;
#X connect 2 0 3 0;
#X connect 3 0 1 0;
#X connect 4 0 0 0;
#X connect 6 0 0 0;

--- NEW FILE: harmonizer.c ---
/* 
harmonizer:
this external build voicing from a chord to another.
takes n voices (midi) as input
you can set the current chord
you can ask for next note of each voice to get to a target chord

usefull to create chorals

voicing is built using traditional GA (not co-evolving GA)

voicing rules are hardcoded and are:
- no parallel 8ths nor 5ths
- better no hidden 8ths nor 5ths
- better if uniform voice spacing (except for the bass)
- better if little intervals
- no all voices same direction
- no voices outside limits
- better complete chords

TODO:
would be nice to be able so set some rule at runtime 
or at least set the importance of rules in realtime..


*/
#include <stdlib.h>
#include <math.h>
#include <time.h>
// for string manipulation
#include <string.h>
#include <ctype.h>
#include "m_pd.h"

// to sort arrays
#include "sglib.h"

#define MAX_POPULATION 100

#define DEF_PROB_MUTATION 0.03f

#define VOICES 5

#define NOTES_RANGE 80 // this should be multiple of 16
#define LOWER_POSSIBLE_NOTE 24 // lower note possible, it should be a C
#define POSSIBLE_NOTES (NOTES_RANGE/12*4) // 4 is the max number of notes in a chord

// testing i noticed that we don't need more than 1 generation..
// this is because we create an initial population that is really good
// we may not need to crossover at all!
#define GENERATIONS 1

#define DEBUG 0 // messaggi di debug
#define DEBUG_VERBOSE 0 // messaggi di debug

static t_class *harmonizer_class;

typedef enum {
			kMaj=0, 
			kMin=1, 
			kDim=2, 
			kAug=3, 
			kDom7=4, 
			kMaj7=5,
			kMin7=6,
			kMinMaj7=7,
			kDim7=8,
			kHalfDim7=9
			} mode_t;

typedef enum {C=0,
			Db=1,
			D=2,
			Eb=3,
			E=4,
			F=5,
			Gb=6,
			G=7,
			Ab=8,
			A=9,
			Bb=10,
			B=11			
			} note_t;



// this defines a chord in a tonality
typedef struct _chord
{
	mode_t mode;
	note_t note;
} chord_t;


typedef struct _harmonizer
{
    t_object x_obj; // myself
	// genotypes
	int population[MAX_POPULATION][VOICES];
	int current_voices[VOICES];
	chord_t current_chord;
	chord_t target_chord;
	int target_notes[POSSIBLE_NOTES];
	t_outlet *l_out;
	
} t_harmonizer;

// I build a table of possible notes
// are the notes (midi)that form target_chord
void build_possible_notes_table(t_harmonizer *x)
{
	int i, octave, basenote;
	int n1, n2, n3, n4;
	n1=n2=n3=n4=0; // there always is the fundamental
	if (DEBUG_VERBOSE)
		post("build_possible_notes_table target_chord.mode=%i target_chord.note=%i", x->target_chord.mode, x->target_chord.note);
	switch (x->target_chord.mode)
	{
		case kMaj:		n2=4; n3=7; n4=0;break;
		case kMin:		n2=3; n3=7; n4=0;break;
		case kDim:		n2=3; n3=6; n4=0;break;
		case kAug:		n2=4; n3=8; n4=0;break;
		case kMaj7:		n2=4; n3=7; n4=11;break;
		case kDom7:		n2=4; n3=7; n4=10;break;
		case kMin7: 	n2=3; n3=7; n4=10;break;
		case kHalfDim7:	n2=3; n3=6; n4=10;break;
		case kDim7:		n2=3; n3=6; n4=9;break;
		case kMinMaj7:	n2=4; n3=7; n4=11;break;
	}
	if (DEBUG_VERBOSE)
		post("build_possible_notes_table n2=%i n3=%i n4=%i", n2, n3, n4);

	basenote=0;
	switch (x->target_chord.note)
	{
		case C:		basenote=0;break;
		case Db:	basenote=1;break;
		case D:		basenote=2;break;
		case Eb:	basenote=3;break;
		case E:		basenote=4;break;
		case F:		basenote=5;break;
		case Gb:	basenote=6;break;
		case G:		basenote=7;break;
		case Ab:	basenote=8;break;
		case A:		basenote=9;break;
		case Bb:	basenote=10;break;
		case B:		basenote=11;break;
	}
	if (DEBUG_VERBOSE)
		post("build_possible_notes_table basenote=%i", basenote);
	i=0;
	octave=0;
	while (i<(POSSIBLE_NOTES-3))
	{
		x->target_notes[i++]=octave*12 + LOWER_POSSIBLE_NOTE + basenote + n1;
		x->target_notes[i++]=octave*12 + LOWER_POSSIBLE_NOTE + basenote + n2;
		x->target_notes[i++]=octave*12 + LOWER_POSSIBLE_NOTE + basenote + n3;
		x->target_notes[i++]=octave*12 + LOWER_POSSIBLE_NOTE + basenote + n4;
		octave++;
	}
	if (DEBUG_VERBOSE)
	{
		i=0;
		while (i<(POSSIBLE_NOTES))
		{
			post("x->target_notes[%i]=%i", i, x->target_notes[i++]);
		}
	}
}

// tries to find out absolute tones names in this string
note_t string2note(const char *substr)
{
	if (strstr(substr, "C"))
		return C;
	if (strstr(substr, "Db"))
		return Db;
	if (strstr(substr, "D"))
		return D;
	if (strstr(substr, "Eb"))
		return Eb;
	if (strstr(substr, "E"))
		return E;
	if (strstr(substr, "F"))
		return F;
	if (strstr(substr, "Gb"))
		return Gb;
	if (strstr(substr, "G"))
		return G;
	if (strstr(substr, "Ab"))
		return Ab;
	if (strstr(substr, "A"))
		return A;
	if (strstr(substr, "Bb"))
		return Bb;
	if (strstr(substr, "B"))
		return B;
	return C;
}

mode_t string2mode(const char *substr)
{
	if (strstr(substr, "minor/major 7th"))
		return kMinMaj7;
	if (strstr(substr, "major 7th"))
		return kMaj7;
	if (strstr(substr, "major"))
		return kMaj;
	if (strstr(substr, "minor 7th"))
		return kMin7;
	if (strstr(substr, "minor"))
		return kMin;
	if (strstr(substr, "half diminished 7th"))
		return kHalfDim7;
	if (strstr(substr, "diminished 7th"))
		return kDim7;
	if (strstr(substr, "diminished"))
		return kDim;
	if (strstr(substr, "augmented"))
		return kAug;
	if (strstr(substr, "dominant 7th"))
		return kDom7;
	// TODO: other chords
	// beware when adding new chords
	// put shorter names at end of this function!
	return C;
}

// -----------------  normal external code ...

void harmonizer_init_pop(t_harmonizer *x)
{
	int i, j, tmp, tmp2, k, steps, note, insertpoint;
	double rnd;
	for (i=0; i<MAX_POPULATION; i++)
	{
		for (j=0; j<VOICES; j++)
		{
			/*
			// totally randome version
			rnd = rand()/((double)RAND_MAX + 1);
			tmp = rnd * POSSIBLE_NOTES;
			x->population[i][j] = x->target_notes[tmp];
			*/

			// not totally random: i start from currend chord's notes
			// and randomly go up or down
			insertpoint = 0;
			while ((insertpoint < POSSIBLE_NOTES) && (x->target_notes[insertpoint] < x->current_voices[j]))
				insertpoint++;
			if (insertpoint >= POSSIBLE_NOTES)
			{ 
				// i didn't find my insert point, possible?
				// i pick a random one
				rnd = rand()/((double)RAND_MAX + 1);
				tmp = rnd * POSSIBLE_NOTES;
				x->population[i][j] = x->target_notes[tmp];
			} else
			{
				// insert point found
				rnd = rand()/((double)RAND_MAX + 1);
				if (rnd < 0.5)
				{
					// i go up
					rnd = rand()/((double)RAND_MAX + 1);
					steps = rnd * 5; // how many step (good notes) will I ignore?
					note = insertpoint + steps;
					if (note >= POSSIBLE_NOTES)
						note = POSSIBLE_NOTES-1;
					
				} else
				{
					// i go down
					rnd = rand()/((double)RAND_MAX + 1);
					steps = rnd * 5; // how many step (good notes) will I ignore?
					note = insertpoint - steps;
					if (note < 0)
						note = 0;
				}
				// finally assign the note
				x->population[i][j] = x->target_notes[note];
			}
		}
	}
}


void harmonizer_free(t_harmonizer *x)
{
//	freebytes(x->buf_strum1, sizeof(x->buf_strum1));
//	freebytes(x->buf_strum2, sizeof(x->buf_strum2));
}

// here i evaluate this voicing
int fitness(t_harmonizer *x, int *candidate)
{
	int i, j, tmp, res, last, avgHI, avgLOW;
	short int transitions[VOICES];
	short int directions[VOICES];
	// intervals between voices
	// for parallel and hidden 5ths
	// voices spacing etc..
	short int intervals[VOICES][VOICES]; 
	short int notes[VOICES];
	res=50; // starting fitness

	if (DEBUG_VERBOSE)
		post("evaluating fitness of %i %i %i %i", candidate[0], candidate[1], candidate[2], candidate[3]);

 	// shared objects
	for (i=0; i<VOICES; i++)
	{
		notes[i]=candidate[i];
		transitions[i] = candidate[i] - x->current_voices[i];
		if (transitions[i]!=0)
			directions[i] = transitions[i]/abs(transitions[i]);
		else
			directions[i] = 0;
		if (DEBUG_VERBOSE)
			post("directions[%i]=%i", i, directions[i]);

	}
	for (i=0; i<VOICES; i++)
	{
		for (j=i+1; j<VOICES; j++)
		{
			intervals[i][j] = (candidate[i]-candidate[j])%12 ;
			if (DEBUG_VERBOSE)
				post("intervals[%i][%i]=%i", i, j, intervals[i][j]);
		}
	}
	SGLIB_ARRAY_SINGLE_QUICK_SORT(short int, notes, VOICES, SGLIB_NUMERIC_COMPARATOR)

	// all same direction? 
	if ( directions[0]==directions[1] &&
	directions[1]==directions[2] &&
	directions[2]==directions[3])
	{
		// bad!
		res -= 10;
		if (DEBUG_VERBOSE)
			post("same direction!");
	}
	
	// parallel 5ths or octaves? (if yes return 0)
	// how?
	// hidden 8ths nor 5ths ?
	for (i=0; i<VOICES; i++)
	{
		for (j=i+1; j<VOICES; j++)
		{
			if (intervals[i][j]==7 || intervals[i][j]==0)
			{
				// hidden or parallel 5th,octave or unison
				// bad!
				if (directions[i]==directions[j])
				{
					res -= 10;
					if (DEBUG_VERBOSE)
						post("hidden or parallel consonance!");
				}
			}
		}
	}

	// is voice spacing uniform ?(except for the bass)
	// TODO: use notes[]
	// are voices average centered?
	tmp=0;
	for (i=1; i<VOICES; i++)
	{
		tmp+=notes[i];
		if (DEBUG_VERBOSE)
			post("average note is %i at passage %i", tmp, i);
	}
	// this is the average note
	tmp = tmp/(VOICES-1);
	if (DEBUG_VERBOSE)
		post("average note is %i after division by (VOICES-1)", tmp);
	tmp = abs((LOWER_POSSIBLE_NOTE + NOTES_RANGE)*2/3 - tmp); // how much average is far from 72
	res += 30; 
	res -= tmp;
	
	if (DEBUG_VERBOSE)
		post("average note is %i far from 2/3 of notes range", tmp);

	tmp=0;
	/*
	// are voices average centered?
	for (i=0; i<VOICES; i++)
	{
		tmp+=notes[i];
	}
	// this is the average note
	tmp = tmp/VOICES;
	tmp = abs(72-tmp); // how much average is far from 72
	res += 30; 
	res -= tmp;
	*/

	// are intervals small?
	//res+=50;
	if (DEBUG_VERBOSE)
		post("res before transitions %i", res);
	for (i=0; i<VOICES; i++)
	{
		if (DEBUG_VERBOSE)
			post("transitions[%i] = %i",i, transitions[i]);
		res-=abs(transitions[i]);
		// give an incentive for semitones etc..
		if (transitions[i]==0)
			res += 5;
		if (abs(transitions[i]==1))
			res += 5;
		if (abs(transitions[i]==2))
			res += 5;
		if (abs(transitions[i]==3))
			res += 2;
		if (abs(transitions[i]==4))
			res += 2;
		if (abs(transitions[i]==5))
			res += 1;
		if (abs(transitions[i]==6))
			res += 1;
		if (abs(transitions[i]>11))
			res -= 2;
		if (abs(transitions[i]>15))
			res -= 5;

	}
	if (DEBUG_VERBOSE)
		post("res after transitions %i", res);

	// TODO: too many near limits?
	
	// TODO: is a complete chord?

	// penalize too many basses
	tmp = 0;
	for (i=0; i<VOICES; i++)
	{
		if (notes[i]<48)
			tmp++;
	}
	switch (tmp)
	{
	case 0: res -= 5; break;
	case 1: res += 10; break;
	case 2: res -= 10; break;
	case 3: res -= 20; break;
	case 4: res -= 30; break;
	}

	if (DEBUG_VERBOSE)
		post("fitness is %i", res);

	return res;
}

void new_genotype(t_harmonizer *x, int *mammy, int *daddy, int *kid)
{
	int i, split;
	double rnd;
	// crossover
	rnd = rand()/((double)RAND_MAX + 1);
	split = rnd * VOICES;
	for (i=0; i<split; i++)
	{
		kid[i]=mammy[i];
	}
	for (i=split; i<VOICES; i++)
	{
		kid[i]=daddy[i];
	}

	//  mutation
	for (i=0; i<VOICES; i++)
	{
		rnd = rand()/((double)RAND_MAX + 1);
		if (rnd < DEF_PROB_MUTATION)
		{
			rnd = rand()/((double)RAND_MAX + 1) * POSSIBLE_NOTES;
			kid[i]=x->target_notes[(int)rnd];
		}
	}
}

typedef struct fitness_list_element_t 
{
	int index;
	int fitness;
} fitness_list_element;

#define FITNESS_LIST_COMPARATOR(e1, e2) (e1.fitness - e2.fitness)

void generate_voicing(t_harmonizer *x)
{
	fitness_list_element fitness_evaluations[MAX_POPULATION];
	int i, generation, mum, dad, winner;
	double rnd;
	t_atom lista[VOICES];
	// inizialize tables of notes
	build_possible_notes_table(x);
	// inizialize population
	harmonizer_init_pop(x);
	// GA code
	for (generation=0; generation<GENERATIONS; generation++)
	{
		// i compute all the fitness
		for (i=0; i<MAX_POPULATION; i++)
		{
			fitness_evaluations[i].index=i;
			fitness_evaluations[i].fitness = fitness(x, x->population[i]);
		}
		// i sort the array
		SGLIB_ARRAY_SINGLE_QUICK_SORT(fitness_list_element, fitness_evaluations, MAX_POPULATION, FITNESS_LIST_COMPARATOR)

		// i kill half population
		// and use the survivors to create new genotypes
		for (i=0; i<(MAX_POPULATION/2); i++)
		{
			// create a new genotype
			// parents chosen randomly
			rnd = rand()/((double)RAND_MAX + 1);
			mum = MAX_POPULATION/2 + rnd*MAX_POPULATION/2;
			rnd = rand()/((double)RAND_MAX + 1);
			dad = MAX_POPULATION/2 + rnd*MAX_POPULATION/2;
			new_genotype(x, x->population[mum], x->population[dad], x->population[i]);
		}
		// repeat the process
	}
	// finally look for the winner
	// i compute all the fitness
	for (i=0; i<MAX_POPULATION; i++)
	{
		fitness_evaluations[i].index=i;
		fitness_evaluations[i].fitness = fitness(x, x->population[i]);
	}
	// i sort the array
	SGLIB_ARRAY_SINGLE_QUICK_SORT(fitness_list_element, fitness_evaluations, MAX_POPULATION, FITNESS_LIST_COMPARATOR)
	
	winner = fitness_evaluations[MAX_POPULATION-1].index;

	if (DEBUG)
		post("winner fitness = %i", fitness_evaluations[MAX_POPULATION-1].fitness);

	for (i=0;i<VOICES;i++)
	{
		SETFLOAT(lista+i, x->population[winner][i]);
	}

	// send output array to outlet
	outlet_anything(x->l_out,
                     gensym("list") ,
					 VOICES, 
					 lista);
}

// if i want another voicing i can send a bang
static void harmonizer_bang(t_harmonizer *x) {
	generate_voicing(x);
}

// called when i send a list (with midi values)
void set_current_voices(t_harmonizer *x, t_symbol *sl, int argc, t_atom *argv)
{
	int i=0;	
	
	if (argc<VOICES)
	{
		error("insufficient notes sent!");
		return;
	}
	// fill input array with actual data sent to inlet
	for (i=0;i<VOICES;i++)
	{
		x->current_voices[i] = atom_getint(argv++);
	}

	generate_voicing(x);


}
// set current chord
void set_current(t_harmonizer *x, t_symbol *s) {
	x->current_chord.mode = string2mode(s->s_name);
	x->current_chord.note = string2note(s->s_name);
	if (DEBUG)
		post("harmonizer: set_current %s",s->s_name); 
}

// set target chord
void set_target(t_harmonizer *x, t_symbol *s) {
	x->target_chord.mode = string2mode(s->s_name);
	x->target_chord.note = string2note(s->s_name);
	if (DEBUG)
		post("harmonizer: set_target %s",s->s_name); 
}


void *harmonizer_new(t_symbol *s, int argc, t_atom *argv)
{
	int i;
	time_t a;
    t_harmonizer *x = (t_harmonizer *)pd_new(harmonizer_class);
	x->l_out = outlet_new(&x->x_obj, &s_list);
/*
	for (i=0; i<BUFFER_LENGHT; i++)
	{
		x->last[i] = harmonizer_note2gene(1,0,0,1);
	}
	*/
	srand(time(&a));

    return (x);
}

void harmonizer_setup(void)
{
    harmonizer_class = class_new(gensym("harmonizer"), (t_newmethod)harmonizer_new,
        (t_method)harmonizer_free, sizeof(t_harmonizer), CLASS_DEFAULT, A_GIMME, 0);
    class_addbang(harmonizer_class, (t_method)harmonizer_bang);
	class_addmethod(harmonizer_class, (t_method)set_current, gensym("current"),A_SYMBOL, 0);
	class_addmethod(harmonizer_class, (t_method)set_target, gensym("target"),A_SYMBOL, 0);
//	class_addmethod(harmonizer_class, (t_method)harmonizer_fitness1_set, gensym("fitness1"), A_DEFFLOAT, 0);
	class_addlist(harmonizer_class, (t_method)set_current_voices);


}

--- NEW FILE: Makefile ---
# customize here !
#VC="C:\Programmi\Microsoft Visual Studio .NET\Vc7"
VC="C:\Programmi\Microsoft Visual Studio .NET\Vc7"
PDPATH="H:\PureData\pd-0.38-3.msw\pd"
#PDPATH="C:\Documents and Settings\Davide\Documenti\personali\pd-0.38-3.msw\pd"


current: pd_nt distclean

pd_nt: chord_melo.dll chords_memory.dll harmonizer.dll GArhythm.dll ritmo1.dll

.SUFFIXES: .dll

PDNTCFLAGS = /W3 /WX /O2 /G6 /DNT /DPD /nologo

PDNTINCLUDE = /I. /I$(PDPATH)\tcl\include /I$(PDPATH)\src /I$(VC)\include /Iinclude

PDNTLDIR = $(VC)\Lib
PDNTLIB = $(PDNTLDIR)\libc.lib \
	$(PDNTLDIR)\oldnames.lib \
	$(PDNTLDIR)\kernel32.lib \
	$(PDPATH)\bin\pd.lib 

.c.dll:
	cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
	link /dll /export:$*_setup $*.obj $(PDNTLIB) 



clean:
	-del link.stamp
	-del *.obj
	-del *.lib
	-del *.exp
	-del *.dll

distclean:
	-del *.obj
	-del *.lib
	-del *.exp

--- NEW FILE: bay.orc ---
; ================================================================
; Header
; ================================================================
sr=44100
kr=882
ksmps=50
nchnls=2

; ================================================================
; Globals
; ================================================================
zakinit 10,10

; Global variable for the reverb unit
ga1 init 0

; ================================================================
; Tables
; ================================================================
; Waveform for the string-pad
iwave ftgen 1, 0, 4096, 10, 1, .5, .33, .25,  .0, .1,  .1, .1

; Senoid required by chorus
isine ftgen 2, 0, 4096, 10, 1


; ================================================================
; Instruments
; ================================================================


instr 1	;String pad
; String-pad borrwoed from the piece "Dorian Gray",
; http://akozar.spymac.net/music/ Modified to fit my needs

;  ihz  = p4
;  idb  = p5/127 * 70    ; rescale MIDI velocity to 70db
;  ipos = p6
;  iamp = ampdb(idb)

; modified by dmorelli
khz	invalue	"hz1"
kpos invalue "pos1"
kamp  invalue "amp1"
kctrl = kamp*70
kctrl =	ampdb(kctrl)
  ; Slow attack and release
;  kctrl   linseg  0, p3/4, iamp, p3/2, 0  
  ; Slight chorus effect
  afund   oscil   kctrl, khz, 1            ; audio oscillator
  acel1   oscil   kctrl, khz - .1, 1       ; audio oscillator - flat
  acel2   oscil   kctrl, khz + .1, 1       ; audio oscillator - sharp
  asig    =   afund + acel1 + acel2

  ; Cut-off high frequencies depending on midi-velocity
  ; (larger velocity implies more brighter sound)
  asig butterlp asig, (p5-60)*40+900
 
  ; Panning
  kppan =       kpos*1.570796325  ; half of PI (radians of 90o angle)
  kpleft        =       cos(kppan)        ; half sign "down"
  kpright       =       sin(kppan)        ; half sign "up"
  asig1 = asig*kpleft;
  asig2 = asig*kpright;
  ; To the chorus effect, through zak channels 1 and 2
  zawm asig1, 1
  zawm asig2, 2
endin


instr 2	;String pad
; String-pad borrwoed from the piece "Dorian Gray",
; http://akozar.spymac.net/music/ Modified to fit my needs

;  ihz  = p4
;  idb  = p5/127 * 70    ; rescale MIDI velocity to 70db
;  ipos = p6
;  iamp = ampdb(idb)

; modified by dmorelli
khz	invalue	"hz2"
kpos invalue "pos2"
kamp  invalue "amp2"
kctrl = kamp*70
kctrl =	ampdb(kctrl)
  ; Slow attack and release
;  kctrl   linseg  0, p3/4, iamp, p3/2, 0  
  ; Slight chorus effect
  afund   oscil   kctrl, khz, 1            ; audio oscillator
  acel1   oscil   kctrl, khz - .1, 1       ; audio oscillator - flat
  acel2   oscil   kctrl, khz + .1, 1       ; audio oscillator - sharp
  asig    =   afund + acel1 + acel2

  ; Cut-off high frequencies depending on midi-velocity
  ; (larger velocity implies more brighter sound)
  asig butterlp asig, (p5-60)*40+900
 
  ; Panning
  kppan =       kpos*1.570796325  ; half of PI (radians of 90o angle)
  kpleft        =       cos(kppan)        ; half sign "down"
  kpright       =       sin(kppan)        ; half sign "up"
  asig1 = asig*kpleft;
  asig2 = asig*kpright;
  ; To the chorus effect, through zak channels 1 and 2
  zawm asig1, 1
  zawm asig2, 2
endin

instr 3	;String pad
; String-pad borrwoed from the piece "Dorian Gray",
; http://akozar.spymac.net/music/ Modified to fit my needs

 ; ihz  = p4
;  idb  = p5/127 * 70    ; rescale MIDI velocity to 70db
;  ipos = p6
;  iamp = ampdb(idb)

; modified by dmorelli
khz	invalue	"hz3"
kpos invalue "pos3"
kamp  invalue "amp3"
kctrl = kamp*70
kctrl =	ampdb(kctrl)
  ; Slow attack and release
;  kctrl   linseg  0, p3/4, iamp, p3/2, 0  
  ; Slight chorus effect
  afund   oscil   kctrl, khz, 1            ; audio oscillator
  acel1   oscil   kctrl, khz - .1, 1       ; audio oscillator - flat
  acel2   oscil   kctrl, khz + .1, 1       ; audio oscillator - sharp
  asig    =   afund + acel1 + acel2

  ; Cut-off high frequencies depending on midi-velocity
  ; (larger velocity implies more brighter sound)
  asig butterlp asig, (p5-60)*40+900
 
  ; Panning
  kppan =       kpos*1.570796325  ; half of PI (radians of 90o angle)
  kpleft        =       cos(kppan)        ; half sign "down"
  kpright       =       sin(kppan)        ; half sign "up"
  asig1 = asig*kpleft;
  asig2 = asig*kpright;
  ; To the chorus effect, through zak channels 1 and 2
  zawm asig1, 1
  zawm asig2, 2
endin
instr 4	;String pad
; String-pad borrwoed from the piece "Dorian Gray",
; http://akozar.spymac.net/music/ Modified to fit my needs

;  ihz  = p4
;  idb  = p5/127 * 70    ; rescale MIDI velocity to 70db
;  ipos = p6
;  iamp = ampdb(idb)

; modified by dmorelli
khz	invalue	"hz4"
kpos invalue "pos4"
kamp  invalue "amp4"
kctrl = kamp*70
kctrl =	ampdb(kctrl)
  ; Slow attack and release
;  kctrl   linseg  0, p3/4, iamp, p3/2, 0  
  ; Slight chorus effect
  afund   oscil   kctrl, khz, 1            ; audio oscillator
  acel1   oscil   kctrl, khz - .1, 1       ; audio oscillator - flat
  acel2   oscil   kctrl, khz + .1, 1       ; audio oscillator - sharp
  asig    =   afund + acel1 + acel2

  ; Cut-off high frequencies depending on midi-velocity
  ; (larger velocity implies more brighter sound)
  asig butterlp asig, (p5-60)*40+900
 
  ; Panning
  kppan =       kpos*1.570796325  ; half of PI (radians of 90o angle)
  kpleft        =       cos(kppan)        ; half sign "down"
  kpright       =       sin(kppan)        ; half sign "up"
  asig1 = asig*kpleft;
  asig2 = asig*kpright;
  ; To the chorus effect, through zak channels 1 and 2
  zawm asig1, 1
  zawm asig2, 2
endin





; strumento senza invalue

instr 9	;String pad
; String-pad borrwoed from the piece "Dorian Gray",
; http://akozar.spymac.net/music/ Modified to fit my needs

  ihz  = p4
  idb  = p5/127 * 70    ; rescale MIDI velocity to 70db
  ipos = p6
  iamp = ampdb(idb)

; modified by dmorelli

;kpos invalue "pos1"
;kamp  invalue "amp1"
;kctrl = kamp*70
;kctrl =	ampdb(kctrl)
  ; Slow attack and release
  kctrl   linseg  0, p3/4, iamp, p3/2, 0  
  ; Slight chorus effect
  afund   oscil   kctrl, ihz, 1            ; audio oscillator
  acel1   oscil   kctrl, ihz - .1, 1       ; audio oscillator - flat
  acel2   oscil   kctrl, ihz + .1, 1       ; audio oscillator - sharp
  asig    =   afund + acel1 + acel2

  ; Cut-off high frequencies depending on midi-velocity
  ; (larger velocity implies more brighter sound)
  asig butterlp asig, (p5-60)*40+900
 
  ; Panning
  ippan =       ipos*1.570796325  ; half of PI (radians of 90o angle)
  ipleft        =       cos(ippan)        ; half sign "down"
  ipright       =       sin(ippan)        ; half sign "up"
  asig1 = asig*ipleft;
  asig2 = asig*ipright;
  ; To the chorus effect, through zak channels 1 and 2
  zawm asig1, 1
  zawm asig2, 2
endin

; ================================================================
; EFFECTS
; ================================================================


; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Chorus effect, borrowed from http://www.jlpublishing.com/Csound.htm
; I made some of its parameters accesible trhough score
instr 10	;Chorus
  ; Read input from zak
  a1     zar     1
  a2     zar     2
  idlyml=p4      ;delay in milliseconds
  k1             oscili          idlyml/p5, 1, 2
  ar1l           vdelay3 a1, idlyml/5+k1, 900    ;delayed sound 1
  ar1r           vdelay3 a2, idlyml/5+k1, 900    ;delayed sound 1
  k2             oscili          idlyml/p5, .995, 2
  ar2l           vdelay3 a1, idlyml/5+k2, 700    ;delayed sound 2
  ar2r           vdelay3 a2, idlyml/5+k2, 700    ;delayed sound 2
  k3             oscili          idlyml/p5, 1.05, 2
  ar3l           vdelay3 a1, idlyml/5+k3, 700    ;delayed sound 3
  ar3r           vdelay3 a2, idlyml/5+k3, 700    ;delayed sound 3
  k4             oscili          idlyml/p5, 1, 2
  ar4l           vdelay3 a1, idlyml/5+k4, 900    ;delayed sound 4
  ar4r           vdelay3 a2, idlyml/5+k4, 900    ;delayed sound 4
  aoutl          =               (a1+ar1l+ar2l+ar3l+ar4l)*.5
  aoutr          =               (a2+ar1r+ar2r+ar3r+ar4r)*.5

  ; To the output mixer
  zawm            aoutl, 5
  zawm            aoutr, 6
  ; and also to the reverb unit
  ga1 = ga1 + (aoutl+aoutr)*.5
endin

; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Reverb
; 8 delay line FDN reverb, with feedback matrix based upon 
; physical modeling scattering junction of 8 lossless waveguides
; of equal characteristic impedance. Based on Julius O. Smith III, 
; "A New Approach to Digital Reverberation using Closed Waveguide
; Networks," Proceedings of the International Computer Music 
; Conference 1985, p. 47-53 (also available as a seperate
; publication from CCRMA), as well as some more recent papers by
; Smith and others.
;
; Coded by Sean Costello, October 1999
instr 25	;Reverb
  ; Note: ga1 is the global input to the reverb.
  afilt1 init 0
  afilt2 init 0
  afilt3 init 0
  afilt4 init 0
  afilt5 init 0
  afilt6 init 0
  afilt7 init 0
  afilt8 init 0
  idel1 = (2473.000/sr)
  idel2 = (2767.000/sr)
  idel3 = (3217.000/sr)
  idel4 = (3557.000/sr)
  idel5 = (3907.000/sr)
  idel6 = (4127.000/sr)
  idel7 = (2143.000/sr)
  idel8 = (1933.000/sr)
  
  
  igain = p4      ; gain of reverb. Adjust empirically
                  ; for desired reverb time. .6 gives
                  ; a good small "live" room sound, .8
                  ; a small hall, .9 a large hall,
                  ; .99 an enormous stone cavern.
  
  ipitchmod = p5  ; amount of random pitch modulation
                  ; for the delay lines. 1 is the "normal"
                  ; amount, but this may be too high for
                  ; held pitches such as piano tones.
                  ; Adjust to taste.
  
  itone = p6      ; Cutoff frequency of lowpass filters
                  ; in feedback loops of delay lines,
                  ; in Hz. Lower cutoff frequencies results
                  ; in a sound with more high-frequency
                  ; damping.
  
  ; k1-k8 are used to add random pitch modulation to the
  ; delay lines. Helps eliminate metallic overtones
  ; in the reverb sound.
  k1      randi   .001, 3.1, .06
  k2      randi   .0011, 3.5, .9
  k3      randi   .0017, 1.11, .7
  k4      randi   .0006, 3.973, .3
  k5      randi   .001, 2.341, .63
  k6      randi   .0011, 1.897, .7
  k7      randi   .0017, 0.891, .9
  k8      randi   .0006, 3.221, .44
  ; apj is used to calculate "resultant junction pressure" for 
  ; the scattering junction of 8 lossless waveguides
  ; of equal characteristic impedance. If you wish to
  ; add more delay lines, simply add them to the following 
  ; equation, and replace the .25 by 2/N, where N is the 
  ; number of delay lines.
  apj = .25 * (afilt1 + afilt2 + afilt3 + afilt4 + afilt5 + afilt6 + afilt7 + afilt8)
  
  
  adum1   delayr  1
  adel1   deltapi idel1 + k1 * ipitchmod
          delayw  ga1 + apj - afilt1
  
  adum2   delayr  1
  adel2   deltapi idel2 + k2 * ipitchmod
          delayw  ga1 + apj - afilt2
  
  adum3   delayr  1
  adel3   deltapi idel3 + k3 * ipitchmod
          delayw  ga1 + apj - afilt3
  
  adum4   delayr  1
  adel4   deltapi idel4 + k4 * ipitchmod
          delayw  ga1 + apj - afilt4
  
  adum5   delayr  1
  adel5   deltapi idel5 + k5 * ipitchmod
          delayw  ga1 + apj - afilt5
  
  adum6   delayr  1
  adel6   deltapi idel6 + k6 * ipitchmod
          delayw  ga1 + apj - afilt6
  
  adum7   delayr  1
  adel7   deltapi idel7 + k7 * ipitchmod
          delayw  ga1 + apj - afilt7
  
  adum8   delayr  1
  adel8   deltapi idel8 + k8 * ipitchmod
          delayw  ga1 + apj - afilt8
  
  ; 1st order lowpass filters in feedback
  ; loops of delay lines.
  afilt1  tone    adel1 * igain, itone
  afilt2  tone    adel2 * igain, itone
  afilt3  tone    adel3 * igain, itone
  afilt4  tone    adel4 * igain, itone
  afilt5  tone    adel5 * igain, itone
  afilt6  tone    adel6 * igain, itone
  afilt7  tone    adel7 * igain, itone
  afilt8  tone    adel8 * igain, itone
  
  ; The outputs of the delay lines are summed
  ; and sent to the stereo outputs. This could
  ; easily be modified for a 4 or 8-channel 
  ; sound system.
  aout1 = (afilt1 + afilt3 + afilt5 + afilt7)
  aout2 = (afilt2 + afilt4 + afilt6 + afilt8)
  ;outs    aout1, aout2
  ; To the output mixer
  zawm aout1, 5
  zawm aout2, 6
  ga1 = 0
endin


; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Output mixer
; It applies a bass enhancement, compression and fadeout
; to the whole piece,
instr 30	;Mixer
  ; Read input from zak
  a1  zar 5
  a2  zar 6
  ; Bass enhancement
  al1 butterlp a1, 100
  al2 butterlp a2, 100
  a1 = al1*1.5 +a1
  a2 = al2*1.5 +a2 

  ; Global amplitude shape
  ; It applies a gain of p4 to the whole piece, and creates a
  ; fadeout the last p5 seconds
  kenv   linseg  p4, p3-p5, p4, p5, 0 
  a1=a1*kenv
  a2=a2*kenv 
  
  ; Compression
  a1 dam a1, 5000, 0.5, 1, 0.2, 0.1  
  a2 dam a2, 5000, 0.5, 1, 0.2, 0.1  
  
  outs a1, a2
  zacl 0, 10
endin


--- NEW FILE: makefile.darwin ---
current: pd_darwin

clean: ; rm -f *.pd_linux *.o *.pd_darwin


# ----------------------- Mac OSX -----------------------

pd_darwin: chord_melo.pd_darwin 

.SUFFIXES: .pd_darwin


# where are the PD header files?
# leave it blank if it is a system directory (like /usr/local/include), 
# 	since gcc 3.2 complains about it
PDPATH=/Users/Development/music/puredatacvs/devel_0_39/src
#PDPATH=/Users/davidemorelli/Desktop/robaDavide/Pd-0.38-3.app/Contents/Resources/src/

# where is the PD executable?
PD=/Applications/PdOLD.app/Contents/Resources/bin/pd
#PD=/usr/local/lib/pd/bin/pd
#PD=/Users/davidemorelli/Desktop/robaDavide/Pd-0.38-3.app/Contents/Resources/bin/pd
#PD=/Users/davidemorelli/Desktop/robaDavide/Pd-0.38-3.app/Contents/Resources/src/


DARWININCLUDE =  -I../../src -I$(PDPATH)

DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
    -Wno-unused -Wno-parentheses -Wno-switch

.c.pd_darwin:
	cc $(DARWINCFLAGS) $(DARWININCLUDE) -o $*.o -c $*.c
	cc -bundle  -bundle_loader $(PD) -flat_namespace -o $*.pd_darwin *.o
#	cc -bundle -undefined suppress -flat_namespace -o $*.pd_darwin
#	rm -f $*.o

# $(FANNLIB)

--- NEW FILE: ritmo1.c ---
/* 
ritmo1
try to extract the current pattern
*/
#include "m_pd.h"

#define BUFFER_LENGHT 16

static t_class *ritmo1_class;

typedef struct _ritmo1
{
    t_object x_obj; // myself
    t_symbol *x_arrayname_src; // where i read the current pattern
    t_symbol *x_arrayname_dest; // where i put the computed pattern
	t_float *buf1;
	t_float *buf2;
	t_float *buf3;
} t_ritmo1;

void ritmo1_allocate_buffers(t_ritmo1 *x)
{
	x->buf1 = (t_float *)getbytes(BUFFER_LENGHT * sizeof(t_float));
	x->buf2 = (t_float *)getbytes(BUFFER_LENGHT * sizeof(t_float));
	x->buf3 =  (t_float *)getbytes(BUFFER_LENGHT * sizeof(t_float));
}

void ritmo1_free(t_ritmo1 *x)
{
	freebytes(x->buf1, sizeof(x->buf1));
	freebytes(x->buf2, sizeof(x->buf2));	
	freebytes(x->buf3, sizeof(x->buf3));}

static void ritmo1_bang(t_ritmo1 *x) {

	int i, vecsize;
	t_garray *arysrc;
	t_garray *arydest;
	t_float *vecsrc;
	t_float *vecdest;

	if (!(arysrc = (t_garray *)pd_findbyclass(x->x_arrayname_src, garray_class)))
	{
        pd_error(x, "%s: no such array", x->x_arrayname_src->s_name);
	}
    else if (!garray_getfloatarray(arysrc, &vecsize, &vecsrc))
	{
		pd_error(x, "%s: bad template for tabwrite", x->x_arrayname_src->s_name);
	}
	  else 	if (!(arydest = (t_garray *)pd_findbyclass(x->x_arrayname_dest, garray_class)))
	{
        pd_error(x, "%s: no such array", x->x_arrayname_dest->s_name);
	}
    else if (!garray_getfloatarray(arydest, &vecsize, &vecdest))
	{
		pd_error(x, "%s: bad template for tabwrite", x->x_arrayname_dest->s_name);
	}
	else // I got arrays and data
	{
		// step 1: compute the pattern
		// and write it in vecdest
		for (i=0; i<16; i++)
		{
			vecdest[i] = (x->buf1[i] + x->buf2[i] + x->buf3[i] + vecsrc[i])/4;
		}
		// redraw the arrays
		garray_redraw(arysrc);
		garray_redraw(arydest);

		// step 2: cycle buffers
		x->buf3 = x->buf2;
		x->buf2 = x->buf1;
		x->buf1 = x->buf3;
		// fill the first buffer with src data
		for (i=0; i<16; i++)
		{
			x->buf1[i] = vecsrc[i];
			vecsrc[i]=0;
		}
	}
}

static void ritmo1_src(t_ritmo1 *x, t_symbol *s) {
    x->x_arrayname_src = s;
}

static void ritmo1_dest(t_ritmo1 *x, t_symbol *s) {
    x->x_arrayname_dest = s;
}

static void *ritmo1_new(t_symbol *s, int argc, t_atom *argv)
{
    t_ritmo1 *x = (t_ritmo1 *)pd_new(ritmo1_class);
	ritmo1_allocate_buffers(x);
	if (argc>0) 
	{
		x->x_arrayname_src = atom_getsymbolarg(0, argc, argv);
	} 
	if (argc>1) 
	{
		x->x_arrayname_dest = atom_getsymbolarg(1, argc, argv);
	}
    return (x);
}

void ritmo1_setup(void)
{
    ritmo1_class = class_new(gensym("ritmo1"), (t_newmethod)ritmo1_new,
        (t_method)ritmo1_free, sizeof(t_ritmo1), CLASS_DEFAULT, A_GIMME, 0);
    class_addbang(ritmo1_class, (t_method)ritmo1_bang);
    class_addmethod(ritmo1_class, (t_method)ritmo1_src, gensym("src"),A_SYMBOL, 0);
    class_addmethod(ritmo1_class, (t_method)ritmo1_dest, gensym("dest"),A_SYMBOL, 0);
}



--- NEW FILE: test-chords_graph.pd ---
#N canvas 241 61 710 346 12;
#X msg 63 130 write test.graph;
#X msg 93 158 read test.graph;
#X obj 389 33 notein;
#X obj 389 68 chord 59;
#X msg 293 151 add \$1;
#X obj 71 255 chords_graph;
#X obj 293 123 symbol;
#X obj 294 96 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X msg 285 234 next 1;
#X obj 366 165 symbol;
#X obj 367 138 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X msg 366 193 set \$1;
#X msg 123 188 init 1;
#X symbolatom 71 281 20 0 0 0 - - -;
#X symbolatom 429 103 25 0 0 0 - - -;
#N canvas 39 349 531 328 readme 0;
#X text 59 31 howto populate the graph: play the chord \, when the
output of [chord] is ok bang the "add" message. bang it each time you
change chord \, it will store the transitions;
#X text 56 120 howto ask for the next chord: play the chord \, bang
the "set" message \, this will set the current chord without adding
it to the graph's memory \, now bang the next 1 message. this chord_graph
will respond with the chord you played most of the times after the
current chord. you can send "next x" where x is from 0 to 1 \, 0 =
max novelty \, 1= min novelty;
#X text 56 259 you can save graph state sending the write message;
#X restore 385 252 pd readme;
#X connect 0 0 5 0;
#X connect 1 0 5 0;
#X connect 2 0 3 0;
#X connect 2 1 3 1;
#X connect 3 2 6 1;
#X connect 3 2 9 1;
#X connect 3 2 14 0;
#X connect 4 0 5 0;
#X connect 5 0 13 0;
#X connect 6 0 4 0;
#X connect 7 0 6 0;
#X connect 8 0 5 0;
#X connect 9 0 11 0;
#X connect 10 0 9 0;
#X connect 11 0 5 0;
#X connect 12 0 5 0;

--- NEW FILE: test-harmonizer2.pd ---
#N canvas 72 0 919 691 12;
#X symbolatom 157 205 18 0 0 2 next_chord - -;
#N canvas 39 349 531 328 readme 0;
#X text 59 31 howto populate the graph: play the chord \, when the
output of [chord] is ok bang the "add" message. bang it each time you
change chord \, it will store the transitions;
#X text 56 120 howto ask for the next chord: play the chord \, bang
the "set" message \, this will set the current chord without adding
it to the graph's memory \, now bang the next 1 message. this chord_graph
will respond with the chord you played most of the times after the
current chord. you can send "next x" where x is from 0 to 1 \, 0 =
max novelty \, 1= min novelty;
#X text 56 259 you can save graph state sending the write message;
#X restore 607 47 pd readme;
#X obj 121 329 harmonizer;
#X msg 52 286 current \$1;
#X msg 158 283 target \$1;
#X obj 52 262 symbol;
#X obj 52 242 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 157 261 symbol;
#X obj 289 261 int 36;
#X obj 355 262 int 60;
#X obj 426 260 int 67;
#X obj 494 259 int 76;
#X obj 566 262 int 84;
#X obj 335 289 pack f f f f f;
#X obj 358 233 t b b b b b;
#X obj 246 369 unpack f f f f f;
#X obj 127 108 symbol;
#X obj 98 43 bng 15 250 50 0 empty empty change_chord 0 -6 0 8 -262144
-1 -1;
#X msg 127 132 set \$1;
#N canvas 0 0 714 424 midi 0;
#X obj 141 253 outlet;
#X obj 271 31 notein;
#X obj 271 66 chord 59;
#X msg 175 149 add \$1;
#X obj 175 121 symbol;
#X obj 176 94 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 248 163 symbol;
#X obj 249 136 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X msg 248 191 set \$1;
#X symbolatom 311 101 25 0 0 0 - - -;
#X connect 1 0 2 0;
#X connect 1 1 2 1;
#X connect 2 2 4 1;
#X connect 2 2 6 1;
#X connect 2 2 9 0;
#X connect 3 0 0 0;
#X connect 4 0 3 0;
#X connect 5 0 4 0;
#X connect 6 0 8 0;
#X connect 7 0 6 0;
#X connect 8 0 0 0;
#X restore 512 135 pd midi;
#N canvas 0 0 458 308 fileIO 0;
#X obj 143 225 outlet;
#X msg 115 77 write test.graph;
#X msg 145 105 read test.graph;
#X msg 175 135 init 1;
#X connect 1 0 0 0;
#X connect 2 0 0 0;
#X connect 3 0 0 0;
#X restore 429 134 pd fileIO;
#X obj 100 73 t b b;
#X obj 157 228 t b a;
#X obj 28 404 bang;
#X obj 203 420 mtof;
#X obj 252 419 mtof;
#X obj 337 423 mtof;
#X obj 180 601 dac~;
#X obj 109 431 print;
#X obj 74 111 f 1;
#X msg 59 135 next \$1;
#X obj 63 70 vsl 15 30 0 1 0 0 empty empty empty 0 -8 0 8 -262144 -1
-1 2610 1;
#X floatatom 32 112 5 0 0 0 - - -;
#X obj 178 571 csoundapi~ bay.orc;
#X msg 488 520 event i 10 0 17000 10 30;
#X msg 488 543 event i 30 0 17000 2 30;
#X msg 489 496 event i 25 0 17000 0.98 0.8 20000;
#X obj 482 458 loadbang;
#X msg 196 492 event i 9 0 10 \$1 80 0.5;
#X obj 295 422 mtof;
#X obj 381 424 mtof;
#X obj 462 22 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
;
#X obj 462 41 metro 7000;
#X obj 13 32 r novelty;
#X obj 599 121 int 0;
#X obj 646 120 + 1;
#X obj 600 171 tabread tab-novelty;
#X obj 600 194 s novelty;
#X obj 685 119 table tab-novelty;
#X obj 600 147 % 10;
#X obj 462 63 t b b;
#X msg 467 377 \; tab-novelty 0 1 1 0.8 0.7 0.3 0.5 0.9 0.1 0 0.2;
#X obj 203 97 symbol;
#X msg 203 125 tonality \$1;
#X obj 203 73 bng 15 250 50 0 empty empty change 0 -6 0 8 -262144 -1
-1;
#X obj 19 160 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X symbolatom 305 204 15 0 0 2 tonality - -;
#X obj 83 169 chords_memory test.graph;
#X obj 307 94 symbol;
#X obj 307 70 bng 15 250 50 0 empty empty change 0 -6 0 8 -262144 -1
-1;
#X msg 307 122 modulation \$1;
#X obj 445 189 print sequence;
#X msg 235 15 search 9 1 5 0.9;
#X connect 2 0 15 0;
#X connect 2 0 28 0;
#X connect 3 0 2 0;
#X connect 4 0 2 0;
#X connect 5 0 3 0;
#X connect 6 0 5 0;
#X connect 7 0 4 0;
#X connect 8 0 13 0;
#X connect 9 0 13 1;
#X connect 10 0 13 2;
#X connect 11 0 13 3;
#X connect 12 0 13 4;
#X connect 13 0 2 0;
#X connect 14 0 8 0;
#X connect 14 1 9 0;
#X connect 14 2 10 0;
#X connect 14 3 11 0;
#X connect 14 4 12 0;
#X connect 15 0 8 1;
#X connect 15 0 23 0;
#X connect 15 0 24 0;
#X connect 15 1 9 1;
#X connect 15 1 25 0;
#X connect 15 2 10 1;
#X connect 15 2 39 0;
#X connect 15 3 11 1;
#X connect 15 3 26 0;
#X connect 15 4 12 1;
#X connect 15 4 40 0;
#X connect 16 0 18 0;
#X connect 17 0 21 0;
#X connect 18 0 57 0;
#X connect 19 0 57 0;
#X connect 20 0 57 0;
#X connect 21 0 29 0;
#X connect 22 0 14 0;
#X connect 22 1 7 0;
#X connect 23 0 5 0;
#X connect 24 0 38 0;
#X connect 25 0 38 0;
#X connect 26 0 38 0;
#X connect 29 0 30 0;
#X connect 30 0 57 0;
#X connect 31 0 29 1;
#X connect 31 0 32 0;
#X connect 33 0 27 0;
#X connect 33 1 27 1;
#X connect 34 0 33 0;
#X connect 35 0 33 0;
#X connect 36 0 33 0;
#X connect 37 0 36 0;
#X connect 37 0 34 0;
#X connect 37 0 35 0;
#X connect 37 0 51 0;
#X connect 38 0 33 0;
#X connect 39 0 38 0;
#X connect 40 0 38 0;
#X connect 41 0 42 0;
#X connect 42 0 50 0;
#X connect 43 0 31 0;
#X connect 44 0 45 0;
#X connect 44 0 49 0;
#X connect 45 0 44 1;
#X connect 46 0 47 0;
#X connect 49 0 46 0;
#X connect 50 0 21 0;
#X connect 50 1 44 0;
#X connect 52 0 53 0;
#X connect 53 0 57 0;
#X connect 54 0 52 0;
#X connect 55 0 57 0;
#X connect 57 0 0 0;
#X connect 57 0 5 1;
#X connect 57 0 22 0;
#X connect 57 0 52 1;
#X connect 57 0 16 0;
#X connect 57 0 58 1;
#X connect 57 1 56 0;
#X connect 57 2 61 0;
#X connect 58 0 60 0;
#X connect 59 0 58 0;
#X connect 60 0 57 0;
#X connect 62 0 57 0;

--- NEW FILE: test-harmonizer.pd ---
#N canvas 328 37 702 643 12;
#X symbolatom 179 191 20 0 0 0 - - -;
#N canvas 39 349 531 328 readme 0;
#X text 59 31 howto populate the graph: play the chord \, when the
output of [chord] is ok bang the "add" message. bang it each time you
change chord \, it will store the transitions;
#X text 56 120 howto ask for the next chord: play the chord \, bang
the "set" message \, this will set the current chord without adding
it to the graph's memory \, now bang the next 1 message. this chord_graph
will respond with the chord you played most of the times after the
current chord. you can send "next x" where x is from 0 to 1 \, 0 =
max novelty \, 1= min novelty;
#X text 56 259 you can save graph state sending the write message;
#X restore 496 48 pd readme;
#X obj 121 316 harmonizer;
#X msg 52 273 current \$1;
#X msg 158 270 target \$1;
#X obj 52 249 symbol;
#X obj 52 229 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 157 248 symbol;
#X obj 289 248 int 36;
#X obj 355 249 int 60;
#X obj 426 247 int 67;
#X obj 494 246 int 76;
#X obj 566 249 int 84;
#X obj 335 276 pack f f f f f;
#X obj 358 220 t b b b b b;
#X obj 246 356 unpack f f f f f;
#X obj 135 105 symbol;
#X obj 98 43 bng 15 250 50 0 empty empty change_chord 0 -6 0 8 -262144
-1 -1;
#X msg 135 133 set \$1;
#N canvas 0 0 706 416 midi 0;
#X obj 141 253 outlet;
#X obj 271 31 notein;
#X obj 271 66 chord 59;
#X msg 175 149 add \$1;
#X obj 175 121 symbol;
#X obj 176 94 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 248 163 symbol;
#X obj 249 136 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X msg 248 191 set \$1;
#X symbolatom 311 101 25 0 0 0 - - -;
#X connect 1 0 2 0;
#X connect 1 1 2 1;
#X connect 2 2 4 1;
#X connect 2 2 6 1;
#X connect 2 2 9 0;
#X connect 3 0 0 0;
#X connect 4 0 3 0;
#X connect 5 0 4 0;
#X connect 6 0 8 0;
#X connect 7 0 6 0;
#X connect 8 0 0 0;
#X restore 326 134 pd midi;
#N canvas 0 0 454 304 fileIO 0;
#X obj 143 225 outlet;
#X msg 115 77 write test.graph;
#X msg 145 105 read test.graph;
#X msg 175 135 init 1;
#X connect 1 0 0 0;
#X connect 2 0 0 0;
#X connect 3 0 0 0;
#X restore 243 133 pd fileIO;
#X obj 100 81 t b b;
#X obj 157 215 t b a;
#X obj 28 391 bang;
#X symbolatom 256 35 20 0 0 0 - - -;
#X obj 256 11 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 203 407 mtof;
#X obj 203 431 sig~;
#X obj 204 457 osc~ 440;
#X obj 280 405 mtof;
#X obj 280 429 sig~;
#X obj 281 455 osc~ 440;
#X obj 338 509 mtof;
#X obj 338 533 sig~;
#X obj 339 559 osc~ 440;
#X obj 375 403 mtof;
#X obj 375 427 sig~;
#X obj 376 453 osc~ 440;
#X obj 425 509 mtof;
#X obj 424 532 sig~;
#X obj 425 558 osc~ 440;
#X obj 186 491 throw~ audio;
#X obj 284 482 throw~ audio;
#X obj 391 483 throw~ audio;
#X obj 337 586 throw~ audio;
#X obj 439 588 throw~ audio;
#X obj 99 533 catch~ audio;
#X obj 99 585 dac~;
#X obj 99 558 *~ 0.2;
#X obj 109 418 print;
#X obj 83 169 chords_graph test.graph;
#X obj 74 111 f 1;
#X msg 59 135 next \$1;
#X obj 63 70 vsl 15 30 0 1 0 0 empty empty empty 0 -8 0 8 -262144 -1
-1 2900 1;
#X floatatom 32 112 5 0 0 0 - - -;
#X connect 2 0 15 0;
#X connect 2 0 49 0;
#X connect 3 0 2 0;
#X connect 4 0 2 0;
#X connect 5 0 3 0;
#X connect 6 0 5 0;
#X connect 7 0 4 0;
#X connect 8 0 13 0;
#X connect 9 0 13 1;
#X connect 10 0 13 2;
#X connect 11 0 13 3;
#X connect 12 0 13 4;
#X connect 13 0 2 0;
#X connect 14 0 8 0;
#X connect 14 1 9 0;
#X connect 14 2 10 0;
#X connect 14 3 11 0;
#X connect 14 4 12 0;
#X connect 15 0 8 1;
#X connect 15 0 23 0;
#X connect 15 0 26 0;
#X connect 15 1 9 1;
#X connect 15 1 29 0;
#X connect 15 2 10 1;
#X connect 15 2 32 0;
#X connect 15 3 11 1;
#X connect 15 3 35 0;
#X connect 15 4 12 1;
#X connect 15 4 38 0;
#X connect 16 0 18 0;
#X connect 17 0 21 0;
#X connect 18 0 50 0;
#X connect 19 0 50 0;
#X connect 20 0 50 0;
#X connect 21 0 51 0;
#X connect 21 1 16 0;
#X connect 22 0 14 0;
#X connect 22 1 7 0;
#X connect 23 0 5 0;
#X connect 24 0 5 1;
#X connect 24 0 16 0;
#X connect 24 0 7 0;
#X connect 25 0 24 0;
#X connect 26 0 27 0;
#X connect 27 0 28 0;
#X connect 28 0 41 0;
#X connect 29 0 30 0;
#X connect 30 0 31 0;
#X connect 31 0 42 0;
#X connect 32 0 33 0;
#X connect 33 0 34 0;
#X connect 34 0 44 0;
#X connect 35 0 36 0;
#X connect 36 0 37 0;
#X connect 37 0 43 0;
#X connect 38 0 39 0;
#X connect 39 0 40 0;
#X connect 40 0 45 0;
#X connect 46 0 48 0;
#X connect 48 0 47 0;
#X connect 48 0 47 1;
#X connect 50 0 0 0;
#X connect 50 0 5 1;
#X connect 50 0 16 1;
#X connect 50 0 22 0;
#X connect 51 0 52 0;
#X connect 52 0 50 0;
#X connect 53 0 51 1;
#X connect 53 0 54 0;

--- NEW FILE: chords_memory.c ---
/* 
chords_memory:
an external that using graph
learns the played style 
and reproduces chords sequences 
see
http://en.wikipedia.org/wiki/Graph_%28mathematics%29
for an idea of what graphs are (but we'll use weights also)

idea:

------- NODES

each node of the graph is a chord
each node has a name like "Imin Imaj ... IImin IImaj .... etc"
We'll cover each possible grade and form, each grade can be
maj
min
dim
[...1098 lines suppressed...]
    chords_memory_class = class_new(gensym("chords_memory"), (t_newmethod)chords_memory_new,
        (t_method)chords_memory_free, sizeof(t_chords_memory), CLASS_DEFAULT, A_GIMME, 0);
class_addbang(chords_memory_class, (t_method)chords_memory_bang);
    // file I/O
	class_addmethod(chords_memory_class, (t_method)chords_memory_write_to_file, gensym("write"),A_SYMBOL, 0);
    class_addmethod(chords_memory_class, (t_method)chords_memory_read_from_file, gensym("read"),A_SYMBOL, 0);
 	// ask for the best choice form here
	class_addmethod(chords_memory_class, (t_method)chords_memory_next, gensym("next"), A_DEFFLOAT, 0);
    // ask for a path from here to desired destination
	class_addmethod(chords_memory_class, (t_method)chords_memory_search, gensym("search"), A_GIMME, 0);
    // add or set chord
	class_addmethod(chords_memory_class, (t_method)chords_memory_add_chord, gensym("add"),A_SYMBOL, 0);
    class_addmethod(chords_memory_class, (t_method)chords_memory_set_chord, gensym("set"),A_SYMBOL, 0);
	// change current tonality
	class_addmethod(chords_memory_class, (t_method)chords_memory_set_tonality, gensym("tonality"),A_SYMBOL, 0);
	class_addmethod(chords_memory_class, (t_method)chords_memory_add_modulation, gensym("modulation"),A_SYMBOL, 0);
 	// reinit memory
	class_addmethod(chords_memory_class, (t_method)chords_memory_init, gensym("init"), A_DEFFLOAT, 0);

}

--- NEW FILE: test.graph ---
(This appears to be a binary file; contents omitted.)

--- NEW FILE: sglib.h ---
/* 

  This is SGLIB version 1.0.3

  (C) by Marian Vittek, Bratislava, http://www.xref-tech.com/sglib, 2003-5

  License Conditions: You can use a verbatim copy (including this
  copyright notice) of sglib freely in any project, commercial or not.
  You can also use derivative forms freely under terms of Open Source
  Software license or under terms of GNU Public License.  If you need
  to use a derivative form in a commercial project, or you need sglib
  under any other license conditions, contact the author.

*/


#ifndef _SGLIB__h_
#define _SGLIB__h_

[...1908 lines suppressed...]


#define SGLIB___GET_VALUE(x) (x)
#define SGLIB___SET_VALUE(x, value) {(x) = (value);}
#define SGLIB_ARRAY_ELEMENTS_EXCHANGER(type, a, i, j) {type _sgl_aee_tmp_; _sgl_aee_tmp_=(a)[(i)]; (a)[(i)]=(a)[(j)]; (a)[(j)]= _sgl_aee_tmp_;}


#define SGLIB_NUMERIC_COMPARATOR(x, y) ((int)((x) - (y)))
#define SGLIB_REVERSE_NUMERIC_COMPARATOR(x, y) ((int)((y) - (x)))

#ifndef SGLIB_MAX_TREE_DEEP
#define SGLIB_MAX_TREE_DEEP 128
#endif

#ifndef SGLIB_HASH_TAB_SHIFT_CONSTANT
#define SGLIB_HASH_TAB_SHIFT_CONSTANT 16381   /* should be a prime */
/* #define SGLIB_HASH_TAB_SHIFT_CONSTANT 536870912  for large tables */
#endif

#endif /* _SGLIB__h_ */

--- NEW FILE: chord_melo_test3.pd ---
#N canvas 204 24 1015 713 12;
#X obj 620 131 metro;
#N canvas 1 23 466 316 msecs 0;
#X obj 58 19 inlet;
#X obj 61 209 outlet;
#X obj 57 147 /;
#X obj 57 100 bang;
#X obj 73 79 t f f;
#X obj 57 174 / 4;
#X msg 57 122 60000;
#X connect 0 0 4 0;
#X connect 2 0 5 0;
#X connect 3 0 6 0;
#X connect 4 0 3 0;
#X connect 4 1 2 1;
#X connect 5 0 1 0;
#X connect 6 0 2 0;
#X restore 684 102 pd msecs;
#X obj 683 28 loadbang;
#X obj 620 108 tgl 15 0 empty empty empty 0 -6 0 8 -258699 -1 -1 0
1;
#N canvas 0 22 498 348 graph2 0;
#X obj 122 9 inlet;
#X obj 362 255 outlet;
#X obj 171 33 int;
#X obj 204 31 + 1;
#X obj 185 57 % 4;
#X obj 168 78 sel 0;
#X obj 168 105 bng 15 250 50 0 empty empty beat 0 -6 0 8 -262144 -1
-1;
#X obj 263 86 sel 0;
#X obj 264 108 bng 15 250 50 0 empty empty bar 0 -6 0 8 -262144 -1
-1;
#X obj 262 63 % 16;
#X obj 69 278 hradio 10 1 0 16 empty empty empty 0 -6 0 8 -262144 -1
-1 0;
#X obj 70 64 / 2;
#X obj 71 87 int;
#X obj 72 111 hradio 10 1 0 2 empty empty 1/8 0 -6 0 8 -262144 -1 -1
0;
#X obj 342 78 int;
#X obj 73 220 hradio 10 1 0 4 empty empty 1/4 0 -6 0 8 -262144 -1 -1
0;
#X obj 341 55 / 4;
#X obj 70 167 hradio 10 1 0 4 empty empty 1/16 0 -6 0 8 -262144 -1
-1 0;
#X connect 0 0 2 0;
#X connect 2 0 3 0;
#X connect 3 0 2 1;
#X connect 3 0 4 0;
#X connect 3 0 9 0;
#X connect 4 0 5 0;
#X connect 4 0 17 0;
#X connect 4 0 11 0;
#X connect 5 0 6 0;
#X connect 7 0 8 0;
#X connect 9 0 7 0;
#X connect 9 0 10 0;
#X connect 9 0 16 0;
#X connect 9 0 1 0;
#X connect 11 0 12 0;
#X connect 12 0 13 0;
#X connect 14 0 15 0;
#X connect 16 0 14 0;
#X coords 0 1 100 -1 200 140 1;
#X restore 379 92 graph;
#X floatatom 706 127 5 0 0 0 - - -;
#X obj 632 169 delay;
#X obj 667 148 / 2;
#X text 296 172 this delay is to center the quantization;
#X obj 685 78 nbx 5 14 30 1000 0 0 empty empty empty 0 -6 0 10 -258699
-1 -1 120 256;
#X text 29 30 test1: detect rhythmic pattern and proposes a counterpoint
;
#N canvas 0 22 458 308 valori 0;
#X obj 57 40 inlet;
#X obj 136 42 inlet;
#X obj 229 42 inlet;
#X obj 58 215 outlet;
#X msg 60 112 fitness1 \$1;
#X msg 136 74 fitness2 \$1;
#X msg 231 133 fitness3 \$1;
#X connect 0 0 4 0;
#X connect 1 0 5 0;
#X connect 2 0 6 0;
#X connect 4 0 3 0;
#X connect 5 0 3 0;
#X connect 6 0 3 0;
#X restore 713 532 pd valori;
#X obj 713 378 vsl 15 128 0 1 0 0 empty empty 1st 0 -8 0 8 -262144
-1 -1 12700 1;
#X obj 760 380 vsl 15 128 0 1 0 0 empty empty 2nd 0 -8 0 8 -262144
-1 -1 12700 1;
#X obj 800 383 vsl 15 128 0 1 0 0 empty empty 3rd 0 -8 0 8 -262144
-1 -1 12700 1;
#X floatatom 700 515 5 0 0 0 - - -;
#X floatatom 750 513 5 0 0 0 - - -;
#X floatatom 800 522 5 0 0 0 - - -;
#X obj 719 49 s sampleinit;
#X obj 726 294 loadbang;
#N canvas 105 213 716 372 initMelody 0;
#X obj 79 28 loadbang;
#X msg 18 132 \; src_played const 1 \;;
#X msg 29 261 \; src_passing const 0 \;;
#X msg 260 69 \; src_note 0 0 1 2 2 1 1 0 0 0 2 2 2 0 2 1 0 \;;
#X msg 235 143 \; src_passing 0 0 0 0 -2 0 -2 0 -1 0 0 2 4 0 0 0 0
\;;
#X msg 247 107 \; src_octave 0 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 \;;
#X connect 0 0 3 0;
#X connect 0 0 1 0;
#X connect 0 0 5 0;
#X connect 0 0 4 0;
#X restore 57 108 pd initMelody;
#X obj 153 586 noteout;
#X obj 153 562 makenote;
#X msg 238 539 60;
#X msg 270 539 100;
#X obj 244 517 loadbang;
#X msg 684 49 120;
#X msg 712 328 1;
#X obj 770 119 table src_octave;
#X obj 769 96 table src_note;
#X obj 770 141 table src_passing;
#X obj 770 165 table src_played;
#N canvas 14 41 980 629 play_melody 0;
#X obj 58 50 t f f f f;
#X obj 58 116 tabread dest_note;
#X obj 225 79 tabread dest_octave;
#X obj 186 153 tabread dest_passing;
#X obj 2 290 tabread dest_played;
#X obj 1 315 select 1;
#X obj 259 -4 inlet;
#X obj 659 8 inlet;
#X floatatom 710 68 5 0 0 0 - - -;
#X text 729 52 base midi note;
#X obj 225 103 * 12;
#X obj 57 144 select 0 1 2;
#X msg 57 186 0;
#X msg 103 184 4;
#X msg 150 185 7;
#X obj 159 266 +;
#X obj 170 303 +;
#X obj 180 344 + 36;
#X text 245 344 default C;
#X obj 275 535 outlet;
#X floatatom 204 390 5 0 0 0 - - -;
#X obj 95 451 int 0;
#X obj 2 339 bang;
#X obj 435 50 t f f f f;
#X obj 372 332 select 1;
#X obj 596 120 * 12;
#X obj 428 161 select 0 1 2;
#X msg 428 203 0;
#X msg 474 201 4;
#X msg 521 202 7;
#X obj 530 283 +;
#X obj 541 320 +;
#X obj 551 361 + 36;
#X text 616 361 default C;
#X floatatom 575 407 5 0 0 0 - - -;
#X obj 466 468 int 0;
#X obj 373 356 bang;
#X obj 373 307 tabread dest_played2;
#X obj 429 133 tabread dest_note2;
#X obj 596 96 tabread dest_octave2;
#X obj 557 170 tabread dest_passing2;
#X obj 883 242 inlet;
#X obj 235 491 spigot;
#X msg 221 455 1;
#X msg 256 456 0;
#X obj 318 492 spigot;
#X msg 297 455 1;
#X msg 332 456 0;
#X obj 258 19 t f f;
#X obj 247 430 select 0 1;
#X floatatom 373 533 5 0 0 0 - - -;
#X floatatom 195 539 5 0 0 0 - - -;
#X connect 0 0 4 0;
#X connect 0 1 1 0;
#X connect 0 2 3 0;
#X connect 0 3 2 0;
#X connect 1 0 11 0;
#X connect 2 0 10 0;
#X connect 3 0 15 1;
#X connect 4 0 5 0;
#X connect 5 0 22 0;
#X connect 6 0 48 0;
#X connect 7 0 8 0;
#X connect 7 0 17 1;
#X connect 7 0 32 1;
#X connect 10 0 16 1;
#X connect 11 0 12 0;
#X connect 11 1 13 0;
#X connect 11 2 14 0;
#X connect 12 0 15 0;
#X connect 13 0 15 0;
#X connect 14 0 15 0;
#X connect 15 0 16 0;
#X connect 16 0 17 0;
#X connect 17 0 20 0;
#X connect 17 0 21 1;
#X connect 21 0 42 0;
#X connect 22 0 21 0;
#X connect 23 0 37 0;
#X connect 23 1 38 0;
#X connect 23 2 40 0;
#X connect 23 3 39 0;
#X connect 24 0 36 0;
#X connect 25 0 31 1;
#X connect 26 0 27 0;
#X connect 26 1 28 0;
#X connect 26 2 29 0;
#X connect 27 0 30 0;
#X connect 28 0 30 0;
#X connect 29 0 30 0;
#X connect 30 0 31 0;
#X connect 31 0 32 0;
#X connect 32 0 34 0;
#X connect 32 0 35 1;
#X connect 35 0 45 0;
#X connect 36 0 35 0;
#X connect 37 0 24 0;
#X connect 38 0 26 0;
#X connect 39 0 25 0;
#X connect 40 0 30 1;
#X connect 41 0 49 0;
#X connect 42 0 19 0;
#X connect 42 0 51 0;
#X connect 43 0 42 1;
#X connect 44 0 45 1;
#X connect 45 0 19 0;
#X connect 45 0 50 0;
#X connect 46 0 45 1;
#X connect 47 0 42 1;
#X connect 48 0 0 0;
#X connect 48 1 23 0;
#X connect 49 0 43 0;
#X connect 49 0 44 0;
#X connect 49 1 46 0;
#X connect 49 1 47 0;
#X restore 153 432 pd play_melody;
#X floatatom 264 313 5 0 0 0 base_midi_note - -;
#N canvas 80 41 790 533 test_src_melody 0;
#X obj 64 33 t f f f f;
#X obj -17 299 select 1;
#X obj 67 3 inlet;
#X obj 418 160 inlet;
#X floatatom 442 209 5 0 0 0 - - -;
#X text 461 193 base midi note;
#X obj 268 125 * 12;
#X obj 57 144 select 0 1 2;
#X msg 57 186 0;
#X msg 103 184 4;
#X msg 150 185 7;
#X obj 159 266 +;
#X obj 170 303 +;
#X obj 180 344 + 36;
#X text 245 344 default C;
#X obj 120 482 outlet;
#X floatatom 204 390 5 0 0 0 - - -;
#X obj 116 450 int 0;
#X obj -16 323 bang;
#X obj -16 274 tabread src_played;
#X obj 58 116 tabread src_note;
#X obj 267 102 tabread src_octave;
#X obj 186 153 tabread src_passing;
#X connect 0 0 19 0;
#X connect 0 1 20 0;
#X connect 0 2 22 0;
#X connect 0 3 21 0;
#X connect 1 0 18 0;
#X connect 2 0 0 0;
#X connect 3 0 4 0;
#X connect 3 0 13 1;
#X connect 6 0 12 1;
#X connect 7 0 8 0;
#X connect 7 1 9 0;
#X connect 7 2 10 0;
#X connect 8 0 11 0;
#X connect 9 0 11 0;
#X connect 10 0 11 0;
#X connect 11 0 12 0;
#X connect 12 0 13 0;
#X connect 13 0 16 0;
#X connect 13 0 17 1;
#X connect 17 0 15 0;
#X connect 18 0 17 0;
#X connect 19 0 1 0;
#X connect 20 0 7 0;
#X connect 21 0 6 0;
#X connect 22 0 11 1;
#X restore 26 383 pd test_src_melody;
#N canvas 0 22 462 312 chords 0;
#X obj 146 45 select 0;
#X obj 147 17 inlet;
#X obj 150 255 outlet;
#X msg 123 193 36;
#X msg 177 193 41;
#X msg 232 191 36;
#X msg 286 191 43;
#X obj 142 96 int 0;
#X obj 144 69 bang;
#X obj 202 99 + 1;
#X obj 141 122 % 4;
#X obj 137 147 select 0 1 2 3;
#X connect 0 0 8 0;
#X connect 1 0 0 0;
#X connect 3 0 2 0;
#X connect 4 0 2 0;
#X connect 5 0 2 0;
#X connect 6 0 2 0;
#X connect 7 0 9 0;
#X connect 7 0 10 0;
#X connect 8 0 7 0;
#X connect 9 0 7 1;
#X connect 10 0 11 0;
#X connect 11 0 3 0;
#X connect 11 1 4 0;
#X connect 11 2 5 0;
#X connect 11 3 6 0;
#X restore 265 290 pd chords;
#X obj 102 619 outlet;
#X obj 14 619 outlet;
#X obj 569 246 outlet;
#X obj 379 233 t a a a a;
#X obj 607 56 inlet;
#X obj 80 181 tgl 15 0 toggleSRC empty src 0 -6 0 8 -262144 -1 -1 0
1;
#X obj 78 215 tgl 15 0 toggleOUT empty out 0 -6 0 8 -262144 -1 -1 0
1;
#N canvas 0 22 650 510 toggle 0;
#X obj 170 119 r toggleSRC;
#X obj 136 144 int 0;
#X obj 136 168 select 1;
#X obj 137 192 bang;
#X obj 154 20 inlet;
#X obj 197 270 outlet;
#X obj 203 231 int 0;
#X obj 86 104 bang;
#X obj 201 60 t a a;
#X connect 0 0 1 1;
#X connect 1 0 2 0;
#X connect 2 0 3 0;
#X connect 3 0 6 0;
#X connect 4 0 8 0;
#X connect 6 0 5 0;
#X connect 7 0 1 0;
#X connect 8 0 7 0;
#X connect 8 1 6 1;
#X restore 33 414 pd toggle;
#N canvas 0 22 662 522 toggle 0;
#X obj 136 144 int 0;
#X obj 136 168 select 1;
#X obj 137 192 bang;
#X obj 154 20 inlet;
#X obj 197 270 outlet;
#X obj 203 231 int 0;
#X obj 86 104 bang;
#X obj 201 60 t a a;
#X obj 170 119 r toggleOUT;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
#X connect 2 0 5 0;
#X connect 3 0 7 0;
#X connect 5 0 4 0;
#X connect 6 0 0 0;
#X connect 7 0 6 0;
#X connect 7 1 5 1;
#X connect 8 0 0 1;
#X restore 155 495 pd toggle;
#N canvas 0 22 778 359 read-tables 0;
#X obj 93 110 tabread dest_note;
#X floatatom 96 147 5 0 0 0 - - -;
#X floatatom 341 44 5 0 0 0 - - -;
#X floatatom 244 147 5 0 0 0 - - -;
#X floatatom 388 146 5 0 0 0 - - -;
#X floatatom 532 143 5 0 0 0 - - -;
#X obj 243 91 tabread dest_octave;
#X obj 386 109 tabread dest_passing;
#X obj 529 89 tabread dest_played;
#X obj 514 175 print;
#X connect 0 0 1 0;
#X connect 2 0 0 0;
#X connect 2 0 6 0;
#X connect 2 0 7 0;
#X connect 2 0 8 0;
#X connect 6 0 3 0;
#X connect 7 0 4 0;
#X connect 8 0 5 0;
#X connect 8 0 9 0;
#X restore 847 310 pd read-tables;
#X msg 866 529 mutation \$1;
#X msg 883 549 crossover \$1;
#X obj 865 373 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144
-1 -1 0 1;
#X obj 899 371 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144
-1 -1 0 1;
#X floatatom 845 507 5 0 0 0 - - -;
#X floatatom 900 505 5 0 0 0 - - -;
#X msg 791 327 1;
#N canvas 0 22 923 490 chord_melo1 0;
#X obj 94 49 inlet;
#X obj 349 58 inlet;
#X obj 123 264 bang;
#X obj 140 116 select 0;
#X obj 185 256 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 191 187 int 0;
#X obj 240 188 + 1;
#X floatatom 191 211 5 0 0 0 generation - -;
#X obj 191 164 bang;
#X msg 23 270 init a;
#X obj 22 227 select 1;
#X obj 23 248 bang;
#X obj 222 344 chord_melo src_note src_octave src_passing src_played
dest_note dest_octave dest_passing dest_played;
#X obj 415 139 table dest_note;
#X obj 416 162 table dest_octave;
#X obj 415 184 table dest_passing;
#X obj 415 208 table dest_played;
#X connect 0 0 3 0;
#X connect 1 0 12 0;
#X connect 2 0 12 0;
#X connect 3 0 2 0;
#X connect 3 0 8 0;
#X connect 4 0 12 0;
#X connect 5 0 6 0;
#X connect 5 0 7 0;
#X connect 5 0 10 0;
#X connect 6 0 5 1;
#X connect 8 0 5 0;
#X connect 9 0 12 0;
#X connect 10 0 11 0;
#X connect 11 0 9 0;
#X restore 667 589 pd chord_melo1;
#N canvas 0 22 923 490 chord_melo2 0;
#X obj 94 49 inlet;
#X obj 349 58 inlet;
#X obj 123 264 bang;
#X obj 140 116 select 0;
#X obj 185 256 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 191 187 int 0;
#X obj 240 188 + 1;
#X floatatom 191 211 5 0 0 0 generation - -;
#X obj 191 164 bang;
#X msg 23 270 init a;
#X obj 22 227 select 1;
#X obj 23 248 bang;
#X obj 415 139 table dest_note2;
#X obj 416 162 table dest_octave2;
#X obj 415 184 table dest_passing2;
#X obj 415 208 table dest_played2;
#X obj 222 344 chord_melo src_note src_octave src_passing src_played
dest_note2 dest_octave2 dest_passing2 dest_played2;
#X connect 0 0 3 0;
#X connect 1 0 16 0;
#X connect 2 0 16 0;
#X connect 3 0 2 0;
#X connect 3 0 8 0;
#X connect 4 0 16 0;
#X connect 5 0 6 0;
#X connect 5 0 7 0;
#X connect 5 0 10 0;
#X connect 6 0 5 1;
#X connect 8 0 5 0;
#X connect 9 0 16 0;
#X connect 10 0 11 0;
#X connect 11 0 9 0;
#X restore 473 628 pd chord_melo2;
#X obj 339 336 manager;
#N canvas 0 22 698 589 sum 0;
#X obj 116 64 inlet;
#X obj 150 338 outlet;
#X obj 278 36 inlet;
#X obj 265 72 select 0;
#X obj 264 124 int 0;
#X obj 312 123 + 1;
#X obj 266 96 bang;
#X obj 86 202 spigot;
#X obj 147 203 int;
#X obj 104 236 + 0;
#X obj 124 99 t f f;
#X obj 211 126 bang;
#X text 383 222 not working yet;
#X text 337 254 it should join the two statements;
#X text 326 277 join means make the first interval small;
#X text 400 192 TODO;
#X obj 204 295 spigot;
#X obj 251 201 bang;
#X msg 246 223 1;
#X obj 257 247 -;
#X obj 253 177 t a a;
#X obj 254 147 % 2;
#X connect 0 0 10 0;
#X connect 2 0 3 0;
#X connect 3 0 6 0;
#X connect 3 0 11 0;
#X connect 4 0 5 0;
#X connect 4 0 21 0;
#X connect 5 0 4 1;
#X connect 6 0 4 0;
#X connect 7 0 9 0;
#X connect 8 0 9 1;
#X connect 9 0 1 0;
#X connect 10 0 8 1;
#X connect 10 0 7 0;
#X connect 10 1 16 0;
#X connect 11 0 8 0;
#X connect 16 0 1 0;
#X connect 17 0 18 0;
#X connect 18 0 19 0;
#X connect 19 0 16 1;
#X connect 20 0 17 0;
#X connect 20 1 19 1;
#X connect 21 0 20 0;
#X connect 21 0 7 1;
#X restore 224 468 pd sum;
#N canvas 0 22 458 308 valori 0;
#X obj 57 40 inlet;
#X obj 136 42 inlet;
#X obj 229 42 inlet;
#X obj 58 215 outlet;
#X msg 60 112 fitness1 \$1;
#X msg 136 74 fitness2 \$1;
#X msg 231 133 fitness3 \$1;
#X connect 0 0 4 0;
#X connect 1 0 5 0;
#X connect 2 0 6 0;
#X connect 4 0 3 0;
#X connect 5 0 3 0;
#X connect 6 0 3 0;
#X restore 511 539 pd valori;
#X obj 511 385 vsl 15 128 0 1 0 0 empty empty 1st 0 -8 0 8 -262144
-1 -1 12700 1;
#X obj 558 387 vsl 15 128 0 1 0 0 empty empty 2nd 0 -8 0 8 -262144
-1 -1 12700 1;
#X obj 598 390 vsl 15 128 0 1 0 0 empty empty 3rd 0 -8 0 8 -262144
-1 -1 12700 1;
#X floatatom 498 522 5 0 0 0 - - -;
#X floatatom 548 520 5 0 0 0 - - -;
#X floatatom 598 529 5 0 0 0 - - -;
#X obj 524 301 loadbang;
#X msg 510 335 1;
#X msg 589 334 1;
#X msg 423 568 mutation \$1;
#X msg 440 588 crossover \$1;
#X obj 422 412 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144
-1 -1 0 1;
#X obj 456 410 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144
-1 -1 0 1;
#X floatatom 402 546 5 0 0 0 - - -;
#X floatatom 457 544 5 0 0 0 - - -;
#X floatatom 344 439 5 0 0 0 - - -;
#X obj 304 614 outlet;
#X connect 0 0 6 0;
#X connect 1 0 0 1;
#X connect 1 0 5 0;
#X connect 1 0 7 0;
#X connect 2 0 26 0;
#X connect 2 0 18 0;
#X connect 3 0 0 0;
#X connect 4 0 39 0;
#X connect 6 0 4 0;
#X connect 7 0 6 1;
#X connect 9 0 1 0;
#X connect 11 0 53 1;
#X connect 12 0 11 0;
#X connect 12 0 15 0;
#X connect 13 0 11 1;
#X connect 13 0 16 0;
#X connect 14 0 11 2;
#X connect 14 0 17 0;
#X connect 19 0 27 0;
#X connect 19 0 52 0;
#X connect 22 0 21 0;
#X connect 22 1 21 1;
#X connect 23 0 22 1;
#X connect 24 0 22 2;
#X connect 25 0 24 0;
#X connect 25 0 23 0;
#X connect 26 0 9 0;
#X connect 27 0 12 0;
#X connect 27 0 13 0;
#X connect 32 0 36 0;
#X connect 32 0 44 0;
#X connect 33 0 34 1;
#X connect 33 0 32 1;
#X connect 34 0 37 0;
#X connect 34 0 43 0;
#X connect 35 0 33 0;
#X connect 39 1 32 0;
#X connect 39 1 34 0;
#X connect 39 2 35 0;
#X connect 39 2 53 0;
#X connect 39 2 54 0;
#X connect 39 3 38 0;
#X connect 39 3 55 0;
#X connect 39 3 56 1;
#X connect 40 0 3 0;
#X connect 43 0 22 0;
#X connect 44 0 22 0;
#X connect 46 0 53 1;
#X connect 47 0 53 1;
#X connect 48 0 46 0;
#X connect 48 0 50 0;
#X connect 49 0 47 0;
#X connect 49 0 51 0;
#X connect 52 0 14 0;
#X connect 55 0 32 2;
#X connect 55 0 73 0;
#X connect 55 0 74 0;
#X connect 57 0 54 1;
#X connect 58 0 57 0;
#X connect 58 0 61 0;
#X connect 59 0 57 1;
#X connect 59 0 62 0;
#X connect 60 0 57 2;
#X connect 60 0 63 0;
#X connect 64 0 65 0;
#X connect 64 0 66 0;
#X connect 65 0 58 0;
#X connect 65 0 59 0;
#X connect 66 0 60 0;
#X connect 67 0 54 1;
#X connect 68 0 54 1;
#X connect 69 0 67 0;
#X connect 69 0 71 0;
#X connect 70 0 68 0;
#X connect 70 0 72 0;

--- NEW FILE: chord_melo.c ---
/* 
BUGS:
- I had to comment out arrays re-display because it crashed my pd
- sometimes dest_played gets filled with junk

TODO:
- now rests can't be used! change chord_melo_seq_max_min
*/
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "m_pd.h"

#define BUFFER_LENGHT 16 // lunghezza dei buffers (quanti elementi nel pattern)
#define MAX_POPULATION 500
#define CHOIR 20
#define NOTES 128 // how many notes can I use ? MIDI !
#define MAX_OCTAVES 3

#define DEF_PROB_CROSSOVER 0.9f
[...1098 lines suppressed...]
{
    chord_melo_class = class_new(gensym("chord_melo"), (t_newmethod)chord_melo_new,
        (t_method)chord_melo_free, sizeof(t_chord_melo), CLASS_DEFAULT, A_GIMME, 0);
    class_addbang(chord_melo_class, (t_method)chord_melo_bang);
    class_addmethod(chord_melo_class, (t_method)chord_melo_src_note, gensym("src_note"),A_SYMBOL, 0);
    class_addmethod(chord_melo_class, (t_method)chord_melo_src_octave, gensym("src_octave"),A_SYMBOL, 0);
    class_addmethod(chord_melo_class, (t_method)chord_melo_src_passing, gensym("src_passing"),A_SYMBOL, 0);
	class_addmethod(chord_melo_class, (t_method)chord_melo_src_played, gensym("src_played"),A_SYMBOL, 0);
    class_addmethod(chord_melo_class, (t_method)chord_melo_dest_note, gensym("dest_note"),A_SYMBOL, 0);
    class_addmethod(chord_melo_class, (t_method)chord_melo_dest_octave, gensym("dest_octave"),A_SYMBOL, 0);
	class_addmethod(chord_melo_class, (t_method)chord_melo_dest_passing, gensym("dest_passing"),A_SYMBOL, 0);
	class_addmethod(chord_melo_class, (t_method)chord_melo_dest_played, gensym("dest_played"),A_SYMBOL, 0);
	class_addmethod(chord_melo_class, (t_method)chord_melo_fitness1_set, gensym("fitness1"), A_DEFFLOAT, 0);
	class_addmethod(chord_melo_class, (t_method)chord_melo_fitness2_set, gensym("fitness2"), A_DEFFLOAT, 0);
	class_addmethod(chord_melo_class, (t_method)chord_melo_fitness3_set, gensym("fitness3"), A_DEFFLOAT, 0);
    class_addmethod(chord_melo_class, (t_method)chord_melo_init_pop2, gensym("init"),A_SYMBOL, 0);
	class_addmethod(chord_melo_class, (t_method)chord_melo_mutation_set, gensym("mutation"), A_DEFFLOAT, 0);
	class_addmethod(chord_melo_class, (t_method)chord_melo_crossover_set, gensym("crossover"), A_DEFFLOAT, 0);

}

--- NEW FILE: README.txt ---
frankenstein set of externals

authors:
dmorelli: www.davidemorelli.it
pland: www.davidcasal.com
with the help of vatic

last update: 
14-10-2005

------------------- what is this?

this is an attempt to build an intelligent system for realtime 
improvisation, a system that follows a human player and proposes
rhythm, melody, chords sequences, formal structure.
it learns the style in realtime.
it uses various AI techniques: GA, searchs, ANN (maybe)

description of files:

chord_melo.c
a GA melody generator. it takes a melody as input and evolves it over time.
uses co-evolutionary techniques (Todd)

chords_memory.c
it is a directional graph which implements a memory of the played 
chords sequences, you can train it...
and once trained you can ask questions like:
in C major, from a D minor 7h where did I go most if the times?
or
in C major, from a D minor 7h build a chord sequence to bring me
in D major in 4 steps using the chords sequences I used most

harmonizer.c
a GA external that build choir voicing for 5 voices: 
you pass it the midi value of each voice, starting chord, next chord
and it outputs a list with the midi values of each voice.
avoids hidden 8ves and 5ths.


folders:

doc/
implementation documents, notes, logs, ideas, etc..
patches/
example patches, help patches, some used in performances, etc..
aima/
python patches not yes used but interesting for agents
ruby/
gridflow patches not yet used
old/
old not used code
test/
testing code, not to be used
backup/
previous versions


TODO:

gluer/solderer
an external that takes the input of two or more chord_melody,
a chord sequence and glues the melody statemets together
to build a long complete melody.

form_manager
an external that manages the form and structure of the piece:
decide which melody statement to use, the chord sequence to ask for, etc..

various objects to detect played notes

diatonic_melody.c
same as chord_melody but without chord reference, only scale used
(for post-tonal music non based on chords)

chromatic_melo.c
same as diatonic_melo but without any reference (for atonal music)

--- NEW FILE: GArhythm.c ---
/* 

*/
#include <stdlib.h>
#include "m_pd.h"

#define BUFFER_LENGHT 16 // lunghezza dei buffers (quanti elementi nel pattern)
#define MAX_POPULATION 100
#define CHOIR 20
#define NUM_STRUM 4 // quanti strumenti uso , max 8

#define DEF_PROB_CROSSOVER 0.9f
#define DEF_PROB_MUTATION 0.025f
#define REINSERT_SRC 1 // quanti reinserisco ad ogni ciclo usando il ritmo src
#define REINSERT_LAST 0 // quanti reinserisco ad ogni ciclo usando il ritmo src

#define DEBUG 0 // messaggi di debug

static t_class *GArhythm_class;


typedef struct _GArhythm
{
    t_object x_obj; // myself
    t_symbol *x_arrayname_src_strum1; // where i read the current pattern
    t_symbol *x_arrayname_src_strum2; // where i read the current pattern
    t_symbol *x_arrayname_src_strum3; // where i read the current pattern
    t_symbol *x_arrayname_src_strum4; // where i read the current pattern
	t_symbol *x_arrayname_dest_strum1; // where i put the computed pattern
	t_symbol *x_arrayname_dest_strum2; // where i put the computed pattern
    t_symbol *x_arrayname_dest_strum3; // where i put the computed pattern
	t_symbol *x_arrayname_dest_strum4; // where i put the computed pattern
	//t_float *buf_strum1; // buffer strum1o
	//t_float *buf_strum2; //  buffer alto
	// tutti gli indici vanno da 0 a 1;
	float indice_variazione; // quanto cambio dalla battuta precedente
	float indice_riempimento; // quanto voglio fitto il pattern risultante
	float indice_aderenza; // quanto simile al ritmo sorgente devo essere
	// la popolazione array di cromosomi
	char population[MAX_POPULATION][BUFFER_LENGHT];
	float prob_crossover;
	float prob_mutation;
	char last[BUFFER_LENGHT];

} t_GArhythm;

void GArhythm_init_pop(t_GArhythm *x)
{
	int i, j, tmp, k;
	double rnd;
	for (i=0; i<MAX_POPULATION; i++)
	{
		for (j=0; j<BUFFER_LENGHT; j++)
		{
			tmp = 0;
			for (k=0; k<NUM_STRUM; k++)
			{
				rnd = rand()/((double)RAND_MAX + 1);
				if (rnd > 0.5)
				{
					tmp =  tmp + (1<<k); // da 0 a MAX_POPULATION
				} 
			}
			x->population[i][j]=tmp;
		}
		if (DEBUG)
			post("inizializzo population[%i] = %i%i%i%i", 
				i, 
				x->population[i][0],
				x->population[i][1],
				x->population[i][2],
				x->population[i][3]
				); 
	}
}

void GArhythm_init_buf(t_float *buf)
{
	int i;
	for (i=0; i<sizeof(buf); i++)
	{
		buf[i] = 0;
	}
}

void GArhythm_allocate_buffers(t_GArhythm *x)
{
//	x->buf_strum1 = (t_float *)getbytes(BUFFER_LENGHT * sizeof(t_float));
//	x->buf_strum2 = (t_float *)getbytes(BUFFER_LENGHT * sizeof(t_float));
//	GArhythm_init_buf(x->buf_strum1);
//	GArhythm_init_buf(x->buf_strum2);
	
}

void GArhythm_free(t_GArhythm *x)
{
//	freebytes(x->buf_strum1, sizeof(x->buf_strum1));
//	freebytes(x->buf_strum2, sizeof(x->buf_strum2));
}

// returns fitness: how similar are man and woman
static double GArhythm_evaluate_fitness1(char *woman, char *man)
{
	int res=0;
	int max = BUFFER_LENGHT*2;
	int i;
	for (i=0; i<BUFFER_LENGHT; i++)
	{
		if (woman[i] == man[i])
			res++;
	}
	for (i=0; i<BUFFER_LENGHT; i++)
	{
		if ((woman[i]!= 0) && (man[i] != 0))
			res++;
		if ((woman[i]== 0) && (man[i] == 0))
			res++;
	}
	return res/max;
}

// riempimento
static double GArhythm_evaluate_fitness2(char *woman, char *man)
{
	int i, j, max;
	double ris=0;
	max = BUFFER_LENGHT * NUM_STRUM;
	for (i=0; i<BUFFER_LENGHT; i++)
	{
		for (j=0; j<NUM_STRUM; j++)
		{
			if (man[i] & (0x01<<j))
				ris++;
		}
	}
	return ris/max;

}

// similarities TODO
static double GArhythm_evaluate_fitness3(char *woman, char *man)
{
	int i;
	short int global1[BUFFER_LENGHT];
	short int global2[BUFFER_LENGHT];
	for (i=0; i<BUFFER_LENGHT; i++)
	{
		if (woman[i] != 0x00)
			global1[i]=1;
		else
			global1[i]=0;
		if (man[i] != 0x00)
			global2[i]=1;
		else
			global2[i]=0;

	}
	// TODO
	return 0;
}


static void GArhythm_create_child(t_GArhythm *x, char *woman, char *man, char *child)
{
		double rnd;
		int split, i, j, tmp;
		// crossover
		rnd = rand()/((double)RAND_MAX + 1);
		if (rnd < x->prob_crossover)
		{
			split =(int) ( rnd * BUFFER_LENGHT); // da 0 a MAX_POPULATION
			for (i=0; i< split; i++)
			{
				child[i] = woman[i];
			}
			for (i=split; i<BUFFER_LENGHT; i++)
			{
				child[i] = man[i];
			}
			// TODO: vertical split (some instr from mammy, some from daddy)
		}else
		{
			for (i=0; i< BUFFER_LENGHT; i++)
			{
				child[i] = woman[i];
			}
		}
		// mutation
		for (i=0; i< BUFFER_LENGHT; i++)
		{
			// per ogni battito
			for (j=0; j<NUM_STRUM; j++)
			{
				// per ogni strumento
				tmp = child[i] & (0x01<<j); // tmp > 0 se è presente il battito là
				rnd = rand()/((double)RAND_MAX + 1);
				if (rnd < x->prob_mutation)
				{
					if (DEBUG)
						post("mutazione al battito %i allo strumento %i", i, j);
					if (tmp)
					{
						child[i] = child[i] & (~(0x01<<j)); // tolgo il bit
					} else
					{	
						child[i] = child[i] | (0x01<<j); // aggiungo il bit						
					}
				}
			}
		}
		if (DEBUG)
			post("generato figlio %i %i %i %i tra %i %i %i %i e %i %i %i %i, split=%i", 
				child[0], child[1], child[2], child[3],
				woman[0], woman[1], woman[2], woman[3], 
				man[0], man[1], man[2], man[3],
				split);

}

static void GArhythm_bang(t_GArhythm *x) {

	int i, j, vecsize, ntot, tmp, me;
	float prob, variatore;
	t_garray *arysrc_strum1;
	t_garray *arysrc_strum2;
	t_garray *arysrc_strum3;
	t_garray *arysrc_strum4;
	t_garray *arydest_strum1;
	t_garray *arydest_strum2;
	t_garray *arydest_strum3;
	t_garray *arydest_strum4;
	t_float *vecsrc_strum1;
	t_float *vecsrc_strum2;
	t_float *vecsrc_strum3;
	t_float *vecsrc_strum4;
	t_float *vecdest_strum1;
	t_float *vecdest_strum2;
	t_float *vecdest_strum3;
	t_float *vecdest_strum4;
	double rnd;
	int winner;
	double winner_fitness;

	char figli[MAX_POPULATION][BUFFER_LENGHT];

	// load tables

	if (!(arysrc_strum1 = (t_garray *)pd_findbyclass(x->x_arrayname_src_strum1, garray_class)))
	{
        pd_error(x, "%s: no such array", x->x_arrayname_src_strum1->s_name);
	}
    else if (!garray_getfloatarray(arysrc_strum1, &vecsize, &vecsrc_strum1))
	{
		pd_error(x, "%s: bad template for tabwrite", x->x_arrayname_src_strum1->s_name);
	} 
	else if (!(arysrc_strum2 = (t_garray *)pd_findbyclass(x->x_arrayname_src_strum2, garray_class)))
	{
        pd_error(x, "%s: no such array", x->x_arrayname_src_strum2->s_name);
	}
    else if (!garray_getfloatarray(arysrc_strum2, &vecsize, &vecsrc_strum2))
	{
		pd_error(x, "%s: bad template for tabwrite", x->x_arrayname_src_strum2->s_name);
	}
	else if (!(arysrc_strum3 = (t_garray *)pd_findbyclass(x->x_arrayname_src_strum3, garray_class)))
	{
        pd_error(x, "%s: no such array", x->x_arrayname_src_strum3->s_name);
	}
    else if (!garray_getfloatarray(arysrc_strum3, &vecsize, &vecsrc_strum3))
	{
		pd_error(x, "%s: bad template for tabwrite", x->x_arrayname_src_strum3->s_name);
	}
	else if (!(arysrc_strum4 = (t_garray *)pd_findbyclass(x->x_arrayname_src_strum4, garray_class)))
	{
        pd_error(x, "%s: no such array", x->x_arrayname_src_strum4->s_name);
	}
    else if (!garray_getfloatarray(arysrc_strum4, &vecsize, &vecsrc_strum4))
	{
		pd_error(x, "%s: bad template for tabwrite", x->x_arrayname_src_strum4->s_name);
	}
	  else 	if (!(arydest_strum1 = (t_garray *)pd_findbyclass(x->x_arrayname_dest_strum1, garray_class)))
	{
        pd_error(x, "%s: no such array", x->x_arrayname_dest_strum1->s_name);
	}
    else if (!garray_getfloatarray(arydest_strum1, &vecsize, &vecdest_strum1))
	{
		pd_error(x, "%s: bad template for tabwrite", x->x_arrayname_dest_strum1->s_name);
	}
	 else 	if (!(arydest_strum2 = (t_garray *)pd_findbyclass(x->x_arrayname_dest_strum2, garray_class)))
	{
        pd_error(x, "%s: no such array", x->x_arrayname_dest_strum2->s_name);
	}
    else if (!garray_getfloatarray(arydest_strum2, &vecsize, &vecdest_strum2))
	{
		pd_error(x, "%s: bad template for tabwrite", x->x_arrayname_dest_strum2->s_name);
	}
	 else 	if (!(arydest_strum3 = (t_garray *)pd_findbyclass(x->x_arrayname_dest_strum3, garray_class)))
	{
        pd_error(x, "%s: no such array", x->x_arrayname_dest_strum3->s_name);
	}
    else if (!garray_getfloatarray(arydest_strum3, &vecsize, &vecdest_strum3))
	{
		pd_error(x, "%s: bad template for tabwrite", x->x_arrayname_dest_strum3->s_name);
	}
	 else 	if (!(arydest_strum4 = (t_garray *)pd_findbyclass(x->x_arrayname_dest_strum4, garray_class)))
	{
        pd_error(x, "%s: no such array", x->x_arrayname_dest_strum4->s_name);
	}
    else if (!garray_getfloatarray(arydest_strum4, &vecsize, &vecdest_strum4))
	{
		pd_error(x, "%s: bad template for tabwrite", x->x_arrayname_dest_strum4->s_name);
	}
	else // I got arrays and data
	{
		// vecdest_strum2 e _strum1 contengono i valori in float degli array
		if (DEBUG)
			post("--------- starting process");
	
		// uccido a caso REINSERT_SRC elementi e inserisco il ritmo src al loro posto
		for (i=0; i<REINSERT_SRC; i++)
		{
			rnd = rand()/((double)RAND_MAX + 1);
			me = (int) (rnd * MAX_POPULATION);
			for (j=0; j<BUFFER_LENGHT; j++)
			{
				char c = 0x00;
				if (vecsrc_strum1[j])
					c = c | 0x01;
				if (vecsrc_strum2[j])
					c = c | (0x01 << 1);
				if (vecsrc_strum3[j])
					c = c | (0x01 << 2);
				if (vecsrc_strum4[j])
					c = c | (0x01 << 3);
				x->population[me][j]=c;
			}
		}
		// uccido a caso REINSERT_LAST elementi e inserisco il last al loro posto
		for (i=0; i<REINSERT_LAST; i++)
		{
			rnd = rand()/((double)RAND_MAX + 1);
			me = (int) (rnd * MAX_POPULATION);
			for (j=0; j<BUFFER_LENGHT; j++)
			{
				x->population[me][j]=x->last[j];
			}
		}

		// metà sono donne, prese a caso
		for (i=0; i<(MAX_POPULATION/2); i++)
		{
			int winner=CHOIR;
			int winner_value=0;
			int men[CHOIR];
			char figlio[BUFFER_LENGHT];
			double fitness1[CHOIR];
			double fitness2[CHOIR];
			double fitness3[CHOIR];
			double fitnessTOT[CHOIR];
			rnd = rand()/((double)RAND_MAX + 1);
			me =(int) ( rnd * MAX_POPULATION); // da 0 a MAX_POPULATION
			// me è la donna che valuta gli uomini

			if (DEBUG)
				post("woman %i = %i %i %i %i", me, x->population[me][0], x->population[me][1], x->population[me][2], x->population[me][3]);

			for (j=0; j<CHOIR; j++)
			{
				rnd = rand()/((double)RAND_MAX + 1);
				tmp =(int) ( rnd * MAX_POPULATION); // da 0 a MAX_POPULATION
				// tmp è questo uomo
				men[j] = tmp;
				fitness1[j]=GArhythm_evaluate_fitness1(x->population[me], x->population[tmp]);
				fitness2[j]=GArhythm_evaluate_fitness2(x->population[me], x->population[tmp]);
				fitness3[j]=GArhythm_evaluate_fitness3(x->population[me], x->population[tmp]);
				fitnessTOT[j]=fitness1[j] * (x->indice_aderenza) 
					+ fitness2[j] * (x->indice_riempimento) 
					+ (1 - fitness2[j]) * (1-(x->indice_riempimento)) 
					+ fitness3[j] * (x->indice_variazione);
				if (winner_value <= fitnessTOT[j])
				{
					winner = tmp;
					winner_value = fitnessTOT[j];
				}
			}
			// winner è il maschio migliore nel coro
			if (DEBUG)
				post("ho scelto il maschio %i", winner);
			// genero un figlio
			GArhythm_create_child(x, x->population[me], x->population[winner], figlio);
			for (j=0; j<BUFFER_LENGHT; j++)
			{
				figli[i][j] = figlio[j];
			}
		}

		// uccido a caso metà popolazione e ci metto i nuovi nati
		for (i=0; i<(MAX_POPULATION/2); i++)
		{
			rnd = rand()/((double)RAND_MAX + 1);
			me =(int) ( rnd * MAX_POPULATION); // da 0 a MAX_POPULATION
			// me è chi deve morire

			for (j=0; j<BUFFER_LENGHT; j++)
			{
				x->population[me][j] = figli[i][j];
			}
		}

		// prendo il più adatto rispetto all'ultimo ritmo suonato
		winner = 0;
		winner_fitness = 0;
		for(i=0; i<BUFFER_LENGHT; i++)
		{
			double tmp1, tmp2, tmp3, tmpTOT;
			tmp1 = GArhythm_evaluate_fitness1(x->last, x->population[i]);
			tmp2 = GArhythm_evaluate_fitness2(x->last, x->population[i]);
			tmp3 = GArhythm_evaluate_fitness3(x->last, x->population[i]);
			tmpTOT = tmp1 * (x->indice_aderenza) 
					+ tmp2 * (x->indice_riempimento) 
					+ (1-tmp2) * (1-(x->indice_riempimento)) 
					+ tmp3 * (x->indice_variazione);
			if (tmpTOT >= winner_fitness)
			{
				winner_fitness = tmpTOT;
				winner = i;
			}
		}
			
		for (i=0; i<BUFFER_LENGHT; i++)
		{
			// copio il vincitor ein x->last
			x->last[i] = x->population[winner][i];
			// scrivo i buffer in uscita
			vecdest_strum1[i]=((x->population[winner][i] & (0x01<<0)) ? 1 : 0);				
			vecdest_strum2[i]=((x->population[winner][i] & (0x01<<1)) ? 1 : 0);				
			vecdest_strum3[i]=((x->population[winner][i] & (0x01<<2)) ? 1 : 0);				
			vecdest_strum4[i]=((x->population[winner][i] & (0x01<<3)) ? 1 : 0);				
		}

		// redraw the arrays
		//garray_redraw(arysrc);
		garray_redraw(arydest_strum1);
		garray_redraw(arydest_strum2);
		garray_redraw(arydest_strum3);
		garray_redraw(arydest_strum4);


	}
}
/*
static void GArhythm_src(t_GArhythm *x, t_symbol *s) {
    x->x_arrayname_src = s;
}
*/

static void GArhythm_variazione_set(t_GArhythm *x, t_floatarg f)
{
  x->indice_variazione = f;
 }

static void GArhythm_aderenza_set(t_GArhythm *x, t_floatarg f)
{
  x->indice_aderenza = f;
}

static void GArhythm_riempimento_set(t_GArhythm *x, t_floatarg f)
{
  x->indice_riempimento = f;
}

static void GArhythm_crossover_set(t_GArhythm *x, t_floatarg f)
{
  x->prob_crossover = f;
}

static void GArhythm_mutation_set(t_GArhythm *x, t_floatarg f)
{
  x->prob_mutation = f;
}

static void *GArhythm_new(t_symbol *s, int argc, t_atom *argv)
{
    t_GArhythm *x = (t_GArhythm *)pd_new(GArhythm_class);
	GArhythm_allocate_buffers(x);
	GArhythm_init_pop(x);
	// inizializzo gli indici
	x->indice_variazione=0;
	x->indice_riempimento=0;
	x->indice_aderenza=0;
	x->prob_crossover = DEF_PROB_CROSSOVER;
	x->prob_mutation = DEF_PROB_MUTATION;


	if (argc>0) 
	{
		x->x_arrayname_src_strum1 = atom_getsymbolarg(0, argc, argv);
	} 
	if (argc>1) 
	{
		x->x_arrayname_src_strum2 = atom_getsymbolarg(1, argc, argv);
	} 
	if (argc>2) 
	{
		x->x_arrayname_src_strum3 = atom_getsymbolarg(2, argc, argv);
	} 
	if (argc>3) 
	{
		x->x_arrayname_src_strum4 = atom_getsymbolarg(3, argc, argv);
	} 
	if (argc>4) 
	{
		x->x_arrayname_dest_strum1 = atom_getsymbolarg(4, argc, argv);
	}
	if (argc>5) 
	{
		x->x_arrayname_dest_strum2 = atom_getsymbolarg(5, argc, argv);
	}
	if (argc>6) 
	{
		x->x_arrayname_dest_strum3 = atom_getsymbolarg(6, argc, argv);
	}
	if (argc>7) 
	{
		x->x_arrayname_dest_strum4 = atom_getsymbolarg(7, argc, argv);
	}

    return (x);
}

void GArhythm_setup(void)
{
    GArhythm_class = class_new(gensym("GArhythm"), (t_newmethod)GArhythm_new,
        (t_method)GArhythm_free, sizeof(t_GArhythm), CLASS_DEFAULT, A_GIMME, 0);
    class_addbang(GArhythm_class, (t_method)GArhythm_bang);
//    class_addmethod(GArhythm_class, (t_method)GArhythm_src, gensym("src"),A_SYMBOL, 0);
	class_addmethod(GArhythm_class, (t_method)GArhythm_variazione_set, gensym("variazione"), A_DEFFLOAT, 0);
	class_addmethod(GArhythm_class, (t_method)GArhythm_riempimento_set, gensym("riempimento"), A_DEFFLOAT, 0);
	class_addmethod(GArhythm_class, (t_method)GArhythm_aderenza_set, gensym("aderenza"), A_DEFFLOAT, 0);
}





More information about the Pd-cvs mailing list