You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
4.2 KiB
Plaintext

TITLE:: FluidSliceCorpus
summary:: A utility for batch slicing of a corpus
categories:: Libraries>FluidCorpusManipulation
related:: Classes/FluidLoadFolder, Classes/FluidProcessSlices, Classes/FluidBufOnsetSlice, Classes/FluidBufNoveltySlice, Classes/FluidBufTransientSlice
DESCRIPTION::
A utility class that abstracts the boiler plate code involved with batch slicing a buffer containing distinct chunks of audio (a 'corpus' for these purposes).
Whilst this class is designed to be used most easily in conjunction with link::Classes/FluidLoadFolder::, it doesn't have to be. However, it does expect to be passed an link::Classes/IdentityDictionary:: of a particular format (see link::#indexFormat#description below::).
The actual mechanism for doing the slicing is provided by the user, in the form of a function that will form part of a larger link::Classes/Synth:: (see link::#sliceFuncDescription#below::).
CLASSMETHODS::
METHOD:: new
Create a new instance with the specified slicing and labelling behaviour.
ARGUMENT:: sliceFunc
ANCHOR::sliceFuncDescription::
A function that does the slicing, returning a link::Classes/UGen::. This function is passed the following arguments:
definitionlist::
## src
|| The source link::Classes/Buffer:: for slicing
## start
|| The frame to start slicing from, in samples
## num
|| The number of frames to slice, in samples
## dst
|| The destination link::Classes/Buffer:: into which to write slice indices
::
This configuration assumes that you are using one of the link::Guides/FluidCorpusManipulation:: buffer-based slicing objects, or at least following their conventions, notably:
list::
## slice points are written into a buffer as sample positions.
## If no slices are found, then a single value of -1 is written instead
::
warning::
This function strong::must:: return a link::Classes/UGen:: that sets a code::done:: flag (see link::Classes/Done::), in order for the iteration and housekeeping to work. All code::FluidBuf*:: objects do this.
::
A concrete example of a code::sliceFunc:: could be:
code::
~sliceFn = { |src,start,num,dest|
FluidBufOnsetSlice.kr(src,start,num,indices:dest)
});
::
ARGUMENT:: idFunc
ANCHOR::labelling::
warning::Not yet implemented::
Override the default labelling behaviour for slices. The default is to append the original identifier with code::-<slice number>:: counting from 1.
INSTANCEMETHODS::
METHOD:: sliceFunc
Retreive the link::#sliceFuncDescription#slicing function:: used by this instance.
METHOD:: play
Run the slicing function over each entry in the supplied link::#indexformat#index dictionary::
ARGUMENT:: server
The link::Classes/Server:: on which to execute
ARGUMENT:: sourceBuffer
The link::Classes/Buffer:: containing the audio to slice
ARGUMENT:: bufIdx
ANCHOR::indexformat::
An link::Classes/IdentityDictionary:: that details identifiers and start-end positions for each chunk in the source buffer. See link::Classes/FluidLoadFolder#index::
ARGUMENT:: action
A function that runs on complettion, will be passed the link::Classes/IdentityDictionary:: from link::#index:: as an argument.
ARGUMENT:: tasks
ANCHOR::ntasks::
The number of parallel processing tasks to run on the server. Default 4. This should probably never be greater than the number of available CPU cores.
METHOD:: index
A link::Classes/IdentityDictionary:: containing information about the position of each discovered slice, using identifiers based on those passed into link::#play:: (see link::#labelling::). This dictionary copies all other entries from the source dictionary on a per-key basis (so you can store arbitary stuff in there should you wish, and it will remain assciated with its original source chunk).
EXAMPLES::
code::
s.reboot
(
~path = FluidFilesPath();
~loader = FluidLoadFolder(~path);
~loader.play(s,action:{ |dataDictionary| "Done loading".postln});
)
(
~slicer = FluidSliceCorpus({ |src,start,num,dest|
FluidBufOnsetSlice.kr(src,start,num,indices:dest, threshold:0.7)
});
)
(
~slicer.play(s,~loader.buffer,~loader.index,{|dataDictionary|
"Slicing done".postln;
//we get passed an IdentityDictionary of slice data, let's look at it
dataDictionary.pairsDo{|identifier,data|
//data is also a dictionary
(identifier ++ '(').post;
data.pairsDo{|k,v| (k ++ ':' + v + ' ').post };
')'.postln;
}
});
)
::