MEAPSoft

The MEAPSoft SuperCollider Object was created to give users a framework for accessing the data provided by MEAPSoft, an open-source program for segmentation, feature extraction, and recomposition, written at Columbia University in a joint collaboration between the Computer Music Center and LabROSA.  For information about MEAPSoft, and to obtain the software, go to: "http://labrosa.ee.columbia.edu/meapsoft/index.php".

see also (for most of this you really should look at):  [MEAPChunk]

Creation:

*new

Creates an empty MEAPSoft Object.

m = MEAPSoft.new;

Loading Data:

loadEDL

Opens a CocoaDialog box that allows the user to specify a MEAPSoft EDL file to be loaded.  The EDL file contains a resorted version of the segmented sound file that has been resorted by the MEAPSoft Composer.

m.loadEDL;

loadFEAT

Opens a CocoaDialog box that allows the user to specify a MEAPSoft FEAT file to be loaded.

m.loadFEAT;

loadSEG

Opens a CocoaDialog box that allows the user to specify a MEAPSoft SEG file to be loaded.

m.loadSEG;

Accessing:

After using MEAPSoft to segment and extract features from a file, you can use the data in SuperCollider in many ways.  Each MEAPSoft Object contains a number of lists that point to MEAPChunk objects, which contain juicy data just waiting for consumption.  Please see the MEAPChunk help file to understand the MEAPChunk Object.	

edlList

Contains a list pointing the MEAPChunks in the order in which they are found in the MEAPSoft EDL file

m = MEAPSoft.new;		//create a new MEAPSoft object
m.loadEDL;			//load a MEAPSoft EDL file (these are the files created by the MEAPSoft composer

m.edlList.size;		//how many elements are in the edlList

//check out how MEAPSoft has reorganized the segmented file
m.edlList.do{arg meapChunk, i;
	(meapChunk.fileName+meapChunk.edlTimes[i].asString+meapChunk.segTime.asString).postln;
};

//or just look at one MEAPChunk
m.edlList[0].edlTimes[0].postln;
m.edlList[0].segTime.postln;

featDict

Contains a Dictionary of sorted feature lists.  The current features extracted by MEAPSoft are:

AvgChroma - currently not sorted
AvgChromaScalar
AvgChunkPower 
AvgFreqSimple 
AvgMelSpec - currently not sorted
AvgMFCC - currently not sorted
AvgPitchSimple
AvgSpec - currently not sorted
AvgSpecCentroid
AvgSpecFlatness
ChunkLength
ChunkStartTime
SpectralStability

AvgMelSpec, AvgMFCC, and AvgSpec are currently not sorted because they contain multi-element arrays

m = MEAPSoft.new;		//create a new MEAPSoft object
m.loadFEAT;			//load a MEAPSoft FEATure file (these hold all of the features extracted from the sound file)

//check out how the chunks have been reorder so that they are in the order of AveChunkPower
m.featDict[\AvgChunkPower].do{arg meapChunk, i; (meapChunk.segTime.asString+meapChunk.featDict[\AvgChunkPower].asString).postln;};

//only list chunks that have a value < -30 in the 10th bin of the AvgSpec
m.segList.do{arg meapChunk, i; 
	if(meapChunk.featDict[\AvgSpec][10]<(30.neg), {meapChunk.segTime.postln})
};

segList

Contains the MEAPChunk segments in their original order.  A segList is created when an EDL file or FEAT file are loaded, but one can also simply load the segmented file

m = MEAPSoft.new;		//create a new MEAPSoft object
m.loadSEG;			//load a MEAPSoft SEGmentation file

m.segList.do{arg meapChunk, i; (meapChunk.segTime.asString+meapChunk.segLength.asString).postln};  //list the segTime and segLength for all chunks

fileNames

Contains a list of file names used by the MEAP Object

m = MEAPSoft.new;		//create a new MEAPSoft object
m.loadSEG;			//load a MEAPSoft SEGmentation file
m.fileNames.postln;	//shows all of the files used in the MEAPSoft Object (usually it is just one)

Some Examples:

//create a MEAPSoft Object and load the data from some MEAP files
m = MEAPSoft.new;
m.loadEDL;
m.loadFEAT;

//load the files used by the MEAP object into a buffer Dictionary
b=Dictionary.new;
m.fileNames.do{arg name;
	b.add(name -> Buffer.read(s, name));
}

//load the SynthDef to play back the stuff
SynthDef("playMEAP", { arg out=0,bufnum=0,startTime,length;
	var env;
	
	env = EnvGen.kr(Env([0,1,1,0],[0.01,length-0.02,0.01]),doneAction:2);
	Out.ar(out,
		PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum), 1, startTime*BufSampleRate.kr(bufnum))*env
	)
}).load(s);

//upward motion by pitch - this is especially scary with voices

Routine({
	m.featDict[\AvgPitchSimple].do{arg meapChunk; 
		meapChunk.featDict[\AvgPitchSimple].postln;
		Synth("playMEAP",[\out, 0, \bufnum, b[meapChunk.fileName], \startTime, meapChunk.segTime, \length, meapChunk.segLength]);
		meapChunk.segLength.wait; 
	};
}).play;

//do the same thing but have the grains overlapping

Routine({
	m.featDict[\AvgPitchSimple].do{arg meapChunk; 
		meapChunk.featDict[\AvgPitchSimple].postln;
		Synth("playMEAP",[\out, 0, \bufnum, b[meapChunk.fileName], \startTime, meapChunk.segTime, \length, meapChunk.segLength]);
		(meapChunk.segLength/(rrand(4.0,8.0))).wait; 
	};
}).play;

//arpeggios - well kind of
(
	var meapChunk;
	
	Routine({
		4.do{
			(10..13).do{arg i1;
				4.do{arg i2;
					meapChunk=m.featDict[\AvgPitchSimple][(i1+((m.featDict[\AvgPitchSimple].size)*(i2/4))).floor.asInteger];
					meapChunk.featDict[\AvgPitchSimple].postln;
					Synth("playMEAP",[\out, 0, \bufnum, b[meapChunk.fileName], \startTime, meapChunk.segTime, \length, meapChunk.segLength]);
					meapChunk.segLength.wait; 
				}
			}
		}
	}).play;
)

//play through an EDL file

Routine({
	m.edlList.do{arg meapChunk; 
		Synth("playMEAP",[\out, 0, \bufnum, b[meapChunk.fileName], \startTime, meapChunk.segTime, \length, meapChunk.segLength]);
		meapChunk.segLength.wait; 
	};
}).play;

//ChunkLength gets smaller
Routine({
	m.featDict[\ChunkLength].reverseDo{arg meapChunk; 
		meapChunk.featDict[\ChunkLength].postln;
		Synth("playMEAP",[\out, 0, \bufnum, b[meapChunk.fileName], \startTime, meapChunk.segTime, \length, meapChunk.segLength]);
		meapChunk.segLength.wait; 
	};
}).play;

//scramble a segment file and play it back

a=m.segList.scramble;

Routine({
	a.do{arg meapChunk;
		Synth("playMEAP",[\out, 0, \bufnum, b[meapChunk.fileName], \startTime, meapChunk.segTime, \length, meapChunk.segLength]);
		meapChunk.segLength.wait; 
	};
}).play;