[PD-cvs] externals/frankenstein themes_memory.c, NONE, 1.1 themes_memory.sln, NONE, 1.1 themes_memory.suo, NONE, 1.1 themes_memory.vcproj, NONE, 1.1

dmorelli morellid at users.sourceforge.net
Thu Jan 5 00:33:35 CET 2006


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

Added Files:
	themes_memory.c themes_memory.sln themes_memory.suo 
	themes_memory.vcproj 
Log Message:
checking in the themes_memory skeleton, just a copy of rhythms_memory

--- NEW FILE: themes_memory.sln ---
Microsoft Visual Studio Solution File, Format Version 7.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "themes_memory", "themes_memory.vcproj", "{DBC75D2A-816A-4C0A-8FE7-2016518D2D19}"
EndProject
Global
	GlobalSection(SolutionConfiguration) = preSolution
		ConfigName.0 = Debug
		ConfigName.1 = Release
	EndGlobalSection
	GlobalSection(ProjectDependencies) = postSolution
	EndGlobalSection
	GlobalSection(ProjectConfiguration) = postSolution
		{DBC75D2A-816A-4C0A-8FE7-2016518D2D19}.Debug.ActiveCfg = Debug|Win32
		{DBC75D2A-816A-4C0A-8FE7-2016518D2D19}.Debug.Build.0 = Debug|Win32
		{DBC75D2A-816A-4C0A-8FE7-2016518D2D19}.Release.ActiveCfg = Release|Win32
		{DBC75D2A-816A-4C0A-8FE7-2016518D2D19}.Release.Build.0 = Release|Win32
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
	EndGlobalSection
	GlobalSection(ExtensibilityAddIns) = postSolution
	EndGlobalSection
EndGlobal

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

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

Authors:
Davide Morelli http://www.davidemorelli.it
David Plans Casal http://www.studios.uea.ac.uk/people/staff/casal

uses graphs to store melodies

it is just like rhythms_memory but works on the more complex world of themes

TODO:
  * memory save/load to file (?)
  * output rhythms in the form of list of floats (easy)
  * add velo (?)
  * input rhythms from a list (second inlet) (easy)
  * let it create variations on known rhythms (?)
  * let it merge rhythms (?)

*/

#include "m_pd.h"

#include "common.h"
#include <time.h>
#include <math.h>
#include <stdlib.h>

static t_class *themes_memory_class;

typedef struct event event;
typedef struct event
{
	unsigned short int voice;
	double when;
	event *next;
};

typedef struct _themes_memory
{
    t_object x_obj; // myself
	// 3 outlets:
	// bangs_out plays the wanted rhythmsin realtime
	// list_out outputs the wanted rhythm as a list of floats
	// info_out outputs info on the last recognized rhythm
	t_outlet *bangs_out, *list_out, *info_out;
	t_rhythm_event *curr_seq;
	int seq_initialized;
	// the memory
	t_rhythm_memory_representation *themes_memory;
	// measure length
	double measure_start_time;
	double measure_length;
	// input rhythm's events
	event *events;
	// output rhythm's events
	unsigned short int next_main_rhythm_out;
	unsigned short int next_sub_rhythm_out;
	event *events_out;
	t_clock *x_clock;
    double x_deltime;
	double last_event_out_time;
	
} t_themes_memory;

void themes_memory_free(t_themes_memory *x)
{
	if (x->curr_seq)
		freeBeats(x->curr_seq);	
	if (x->themes_memory)
		rhythm_memory_free(x->themes_memory);

	clock_free(x->x_clock);
}

// called when a new measure starts
void start_measure(t_themes_memory *x)
{
	// I call the pd functions to get a representation
	// of this very moment
	x->measure_start_time = clock_getlogicaltime();
	x->last_event_out_time = 0;
}

// called when a new event occours
void add_event(t_themes_memory *x, unsigned short int voice)
{
	event *newEvent, *currEvent, *lastEvent;
	double when;
	when = clock_gettimesince(x->measure_start_time);
	newEvent = (event *) malloc(sizeof(event));
	newEvent->when = when;
	newEvent->voice = voice;
	newEvent->next = 0;
	currEvent = x->events;
	if (currEvent)
	{
		// this is not the first event
		while(currEvent)
		{
			lastEvent = currEvent;
			currEvent = currEvent->next;
		}
		lastEvent->next = newEvent;
	} else
	{
		// this is the first event
		x->events = newEvent;
	}
	post("event added");
}

// called when a measure ends
void end_measure(t_themes_memory *x)
{
	float fduration;
	event *currEvent, *lastEvent;
	unsigned short int is_it_a_new_rhythm;
	unsigned short int id, subid;
	float root_closeness, sub_closeness;
	int counter;
	t_atom *lista;
	// these 2 are for output rhythm
	int rhythm_found;
	t_rhythm_event *wanted_rhythm;
	t_rhythm_event *curr_rhythm;
	event *lastOutEvent;

	// I call the pd functions to get a representation
	// of this very moment
	x->measure_length = clock_gettimesince(x->measure_start_time);
	// now that i know the exact length of the current measure
	// i can process the rhythm in the current measure
	// and evaluate it
	currEvent = x->events;
	// this is not the first event
	// now I translate events in rhythm
	counter = 0;
	while(currEvent)
	{
		fduration = (float) (((float) currEvent->when) / ((float) x->measure_length));
		if (x->seq_initialized)
		{
			concatenateBeat(x->curr_seq, currEvent->voice, fduration, 1);
		} else
		{
			setFirstBeat(&(x->curr_seq), currEvent->voice, fduration, 1);
			x->seq_initialized = 1;
		}
		currEvent = currEvent->next;
		counter++;
	}
	
	// delete events after having evaluated them
	currEvent = x->events;
	// this is not the first event
	while(currEvent)
	{
		lastEvent = currEvent;
		currEvent = currEvent->next;
		free(lastEvent);
	}
	x->events = 0;

	if (x->curr_seq)
	{
		// now I evaluate this rhythm with the memory
		rhythm_memory_evaluate(x->themes_memory, x->curr_seq, &is_it_a_new_rhythm,
								&id, &subid, &root_closeness, &sub_closeness);
		// tell out the answer
		// allocate space for the list
		lista = (t_atom *) malloc(sizeof(t_atom) * 5);
		SETFLOAT(lista, (float) is_it_a_new_rhythm);
		SETFLOAT(lista+1, (float) id);
		SETFLOAT(lista+2, (float) subid);
		SETFLOAT(lista+3, (float) root_closeness);
		SETFLOAT(lista+4, (float) sub_closeness);
		outlet_anything(x->info_out,
						gensym("list") ,
						5, 
						lista);
		free(lista);
		// rhythm_memory_evaluate freed the memory for the rhythm if needed
		x->seq_initialized = 0;
		x->curr_seq = 0;
	}

	// I free the list of events_out (if present)
	currEvent = x->events_out;
	// this is not the first event
	while(currEvent)
	{
		lastEvent = currEvent;
		currEvent = currEvent->next;
		free(lastEvent);
	}
	x->events_out = 0;
	// i set up the list of events_out
	// for the wanted rhythm
	if (x->next_main_rhythm_out)
	{
		wanted_rhythm = 0;
		// ask the memory for the wanted rhythm
		rhythm_found = rhythm_memory_get_rhythm(x->themes_memory, // the memory
								&wanted_rhythm, // a pointer to the returned rhythm
								// the id of the main rhythm wanted
								x->next_main_rhythm_out, 
								// the sub-id of the sub-rhythm wanted
								x->next_sub_rhythm_out);
		if (rhythm_found==0)
		{
			post("themes_memory: rhythm %i %i was not found ", x->next_main_rhythm_out, x->next_sub_rhythm_out);
			return 0;
		}

		if (wanted_rhythm==0)
		{
			error("themes_memory: wanted_rhythm should not be null! ");
			return 0;
		}

		// now I setup the events_out list
		// for each event in wanted_rhythm
		// allocate and link an element of elements_out
		curr_rhythm = wanted_rhythm;
		lastOutEvent = 0;
		while (curr_rhythm)
		{
			event *newEvent;
			newEvent = malloc(sizeof(event));
			newEvent->next = 0;
			newEvent->voice = curr_rhythm->voice;
			newEvent->when = (double) (duration2float(curr_rhythm->start) * x->measure_length);
			post("DEBUG: add event in moment: %f", newEvent->when);
			if (x->events_out)
			{
				// this is not the first event
				// assign the next
				lastOutEvent->next = newEvent;
			} else
			{
				// this is the first event
				x->events_out = newEvent;
			}
			// change the last pointer
			lastOutEvent = newEvent;
			curr_rhythm = curr_rhythm->next;
		}

		// also setup the timer for the first event
		if (x->events_out)
		{
			// setup the clock
			clock_delay(x->x_clock, x->events_out->when);
			// remember when next event will occour
			x->last_event_out_time = x->events_out->when;
			// remember the curr event
			lastOutEvent = x->events_out;
			//reassign next event
			x->events_out = x->events_out->next;
			// free old event
			free(lastOutEvent);
		}
		x->next_main_rhythm_out = 0;

	}

	// also start the new measure!
	start_measure(x);

	
}

// this function is called  by pd
// when the timer bangs
static void rhythms_tick(t_themes_memory *x)
{
	event *lastOutEvent;
    // here i must:
	// take the next element in x->events_out
	// and compute when I'll need to schedule next event
	// (next_event - curr_event)
	// set the next element as the current one
	// and free the memory allocated for the old curr event
	// set up the timer	
	post("DEBUG: eveng bang");
	// first of all trigger the bang!
	outlet_bang(x->bangs_out);
	//then do the stuff
	if (x->events_out)
	{
		// setup the clock
		clock_delay(x->x_clock, x->events_out->when - x->last_event_out_time);
		// remember when next event will occour
		x->last_event_out_time = x->events_out->when ;
		// remember the curr event
		lastOutEvent = x->events_out;
		//reassign next event
		x->events_out = x->events_out->next;
		// free old event
		free(lastOutEvent);
	}
}

// the user wants me to play a rhythm in the next measure
// the user MUST pass 2 args: main_rhythm and sub_rhythm wanted
static void ask_rhythm(t_themes_memory *x, t_symbol *s, int argc, t_atom *argv)
{
	if (argc<2)
	{
		error("this method needs at least 2 floats: main_rhythm and sub_rhythm wanted");
		return;
	}
	//argv++;
	x->next_main_rhythm_out = atom_getfloat(argv++);
	x->next_sub_rhythm_out = atom_getfloat(argv);
	post("DEBUG: asked rhythm %i %i", x->next_main_rhythm_out, x->next_sub_rhythm_out); 
	// i have nothing left to do:
	// when this measure will end a list of events_out will be set
	// from the current values of x->next_main_rhythm_out and x->next_sub_rhythm_out
}

// add this rhythm to the memory
static void add_rhythm(t_themes_memory *x, t_symbol *s, int argc, t_atom *argv)
{
 // TODO
	post("TODO");
}

// creates a variation of a given rhythm (in memory)
// with a given degree of closeness
static void variation(t_themes_memory *x, t_symbol *s, int argc, t_atom *argv)
{
 // TODO
	post("TODO");

	// get the rhythm

	// using the transitions table create a new one

	// add it to the memory?

	// output to the list outlet?

	// set it as the next played rhythm
}

static void themes_memory_bang(t_themes_memory *x) {

	// generate a random value
	float rnd;
	t_rhythm_event *events;
	t_duration dur;

	rnd = rand()/((double)RAND_MAX + 1);
	dur = float2duration(rnd);

	post("random value=%f duration.numerator=%i duration.denominator=%i", rnd, dur.numerator, dur.denominator);

	if (x->seq_initialized)
	{
		concatenateBeat(x->curr_seq, 0, rnd, 1);
	} else
	{
		setFirstBeat(&(x->curr_seq), 0, rnd, 1);
		x->seq_initialized = 1;
	}

	// print the sequence
	events = x->curr_seq;
	while(events)
	{
		post("event: numerator=%i, denominator=%i", events->duration.numerator, events->duration.denominator);
		events=events->next;
	}
	
}

void *themes_memory_new(t_symbol *s, int argc, t_atom *argv)
{
	int i;
	time_t a;
    t_themes_memory *x = (t_themes_memory *)pd_new(themes_memory_class);
	// first is for bangs (to let this external play in realtime
	//x->l_out = outlet_new(&x->x_obj, &s_list);
	x->bangs_out = outlet_new(&x->x_obj, gensym("bang"));
	// this outputs lists of events
	x->list_out = outlet_new(&x->x_obj, "symbol");
	// this outputs info on the last detected rhythm
	x->info_out = outlet_new(&x->x_obj, "symbol");

	// inlet for rhythms in the form of lists
	inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("list"), gensym("rhythm_in"));

	x->x_clock = clock_new(x, (t_method)rhythms_tick);
	x->seq_initialized = 0;

	rhythm_memory_create(&(x->themes_memory));
	start_measure(x);

    return (x);
}

// debugging function
void crash(t_themes_memory *x)
{
	int *a;
	a = malloc(sizeof(int));
	a[9999999999999999999] = 1;
}

void themes_memory_setup(void)
{
    themes_memory_class = class_new(gensym("themes_memory"), (t_newmethod)themes_memory_new,
        (t_method)themes_memory_free, sizeof(t_themes_memory), CLASS_DEFAULT, A_GIMME, 0);
    class_addbang(themes_memory_class, (t_method)themes_memory_bang);
	class_addmethod(themes_memory_class, (t_method)end_measure, gensym("measure"), 0);
	class_doaddfloat(themes_memory_class, (t_method)add_event);
	class_addmethod(themes_memory_class, (t_method)crash, gensym("crash"), 0);
	// the user asks for a rhythm
	class_addmethod(themes_memory_class, (t_method)ask_rhythm, gensym("rhythm_out"),
        A_GIMME, 0);
	// adds a rhythm passing it as a list of floats
	class_addmethod(themes_memory_class, (t_method)add_rhythm, gensym("rhythm_in"),
        A_GIMME, 0);
	// builds a variation of a given rhythm
	class_addmethod(themes_memory_class, (t_method)variation, gensym("variation"),
        A_GIMME, 0);
}



--- NEW FILE: themes_memory.vcproj ---
<?xml version="1.0" encoding = "Windows-1252"?>
<VisualStudioProject
	ProjectType="Visual C++"
	Version="7.00"
	Name="themes_memory"
	ProjectGUID="{DBC75D2A-816A-4C0A-8FE7-2016518D2D19}"
	Keyword="Win32Proj">
	<Platforms>
		<Platform
			Name="Win32"/>
	</Platforms>
	<Configurations>
		<Configuration
			Name="Debug|Win32"
			OutputDirectory="Debug"
			IntermediateDirectory="Debug"
			ConfigurationType="1"
			CharacterSet="2">
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="../"
				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
				MinimalRebuild="TRUE"
				BasicRuntimeChecks="3"
				RuntimeLibrary="5"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				Detect64BitPortabilityProblems="TRUE"
				DebugInformationFormat="4"/>
			<Tool
				Name="VCCustomBuildTool"/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="/export:themes_memory_setup /dll"
				AdditionalDependencies="pd.lib"
				OutputFile="$(OutDir)/themes_memory.dll"
				LinkIncremental="2"
				AdditionalLibraryDirectories="../"
				GenerateDebugInformation="TRUE"
				ProgramDatabaseFile="$(OutDir)/frankenstein.pdb"
				SubSystem="0"
				TargetMachine="1"/>
			<Tool
				Name="VCMIDLTool"/>
			<Tool
				Name="VCPostBuildEventTool"/>
			<Tool
				Name="VCPreBuildEventTool"/>
			<Tool
				Name="VCPreLinkEventTool"/>
			<Tool
				Name="VCResourceCompilerTool"/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"/>
			<Tool
				Name="VCWebDeploymentTool"/>
		</Configuration>
		<Configuration
			Name="Release|Win32"
			OutputDirectory="Release"
			IntermediateDirectory="Release"
			ConfigurationType="1"
			CharacterSet="2">
			<Tool
				Name="VCCLCompilerTool"
				Optimization="2"
				InlineFunctionExpansion="1"
				OmitFramePointers="TRUE"
				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
				StringPooling="TRUE"
				RuntimeLibrary="4"
				EnableFunctionLevelLinking="TRUE"
				UsePrecompiledHeader="3"
				WarningLevel="3"
				Detect64BitPortabilityProblems="TRUE"
				DebugInformationFormat="3"/>
			<Tool
				Name="VCCustomBuildTool"/>
			<Tool
				Name="VCLinkerTool"
				OutputFile="$(OutDir)/frankenstein.exe"
				LinkIncremental="1"
				GenerateDebugInformation="TRUE"
				SubSystem="2"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				TargetMachine="1"/>
			<Tool
				Name="VCMIDLTool"/>
			<Tool
				Name="VCPostBuildEventTool"/>
			<Tool
				Name="VCPreBuildEventTool"/>
			<Tool
				Name="VCPreLinkEventTool"/>
			<Tool
				Name="VCResourceCompilerTool"/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"/>
			<Tool
				Name="VCWebDeploymentTool"/>
		</Configuration>
	</Configurations>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
			<File
				RelativePath="common.c">
			</File>
			<File
				RelativePath="themes_memory.c">
			</File>
		</Filter>
		<Filter
			Name="Header Files"
			Filter="h;hpp;hxx;hm;inl;inc">
			<File
				RelativePath="common.h">
			</File>
		</Filter>
		<Filter
			Name="Resource Files"
			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
		</Filter>
	</Files>
	<Globals>
	</Globals>
</VisualStudioProject>





More information about the Pd-cvs mailing list