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.
110 lines
3.6 KiB
Plaintext
110 lines
3.6 KiB
Plaintext
TITLE:: FluidBufSTFT
|
|
summary:: Perform a Short-Time Fourier Transform on one channel of a buffer
|
|
categories:: FluidCorpusManipulation
|
|
related:: Classes/Buffer
|
|
|
|
DESCRIPTION::
|
|
Performs either a forward or inverse Short-Time Fourier Transform (STFT) on a single channel source buffer~. In the forward case, resulting magnitudes and phases can be written to output buffers. In the inverse case, these buffers can be used to reconstruct the original source into a new buffer.
|
|
|
|
The magntude and phase buffers are laid out as (number of hops, number of bins). The number of hops is a function of the source length and the hop size. The number of bins is (1 + (fft size / 2)).
|
|
|
|
The object is restricted to analysing a single source channel, because the channel counts of the magntude and phase buffers would quickly get out of hand otherwise.
|
|
|
|
CLASSMETHODS::
|
|
|
|
private::new1
|
|
|
|
METHOD:: process, processBlocking
|
|
Run the process on the given sever, and perfrom code::action:: when done
|
|
|
|
ARGUMENT:: server
|
|
The link::Classes/Server:: on which to run
|
|
|
|
ARGUMENT:: source
|
|
The link::Classes/Buffer:: to use for the forward STFT
|
|
|
|
ARGUMENT:: startFrame
|
|
The starting point for analysis in the source (in samples)
|
|
|
|
ARGUMENT:: numFrames
|
|
The duration (in samples) to analyse
|
|
|
|
ARGUMENT:: startChan
|
|
The channel to analyse
|
|
|
|
ARGUMENT:: magnitude
|
|
The link::Classes/Buffer:: to write magnitudes to in the forward case, or read from in the inverse case. This is optional for the forward transform, mandatory for the inverse.
|
|
|
|
ARGUMENT:: phase
|
|
The link::Classes/Buffer:: to write phases to in the forward case, or read from in the inverse case. This is optional for the forward transform, mandatory for the inverse.
|
|
|
|
ARGUMENT:: resynthesis
|
|
The link::Classes/Buffer:: to write re-synthesised data to in the inverse case. Ignored for the forward transform. Mandatory in the inverse case.
|
|
|
|
ARGUMENT:: inverse
|
|
When set to 1, an inverse STFT is performed, and the resynthesised data is written to the resynthesis buffer using overlap-add.
|
|
|
|
ARGUMENT:: windowSize
|
|
The number of source samples that are analysed at once.
|
|
|
|
ARGUMENT:: hopSize
|
|
How many samples there are in-between analysis windows. The -1 default value will default to half of windowSize (overlap of 2).
|
|
|
|
ARGUMENT:: fftSize
|
|
The FFT/IFFT size. It should be at least 4 samples long, at least the size of the window, and a power of 2. Making it larger allows an oversampling of the spectral precision. The -1 default value will use the next power of 2 equal or above the windowSize. For this object it is effectively capped at 65536.
|
|
|
|
ARGUMENT:: freeWhenDone
|
|
Free the server instance when processing complete. Default true
|
|
|
|
ARGUMENT:: action
|
|
Runs when processing is complete
|
|
|
|
INSTANCEMETHODS::
|
|
|
|
|
|
EXAMPLES::
|
|
|
|
code::
|
|
s.reboot
|
|
(
|
|
b = Buffer.read(s,File.realpath(FluidBufSTFT.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Nicol-LoopE-M.wav");
|
|
m = Buffer.new;
|
|
p = Buffer.new;
|
|
r = Buffer.new;
|
|
)
|
|
|
|
(
|
|
fork{
|
|
FluidBufSTFT.process(s,source:b,magnitude:m,phase:p).wait;
|
|
FluidBufSTFT.process(s,magnitude:m,phase:p,resynthesis:r,inverse:1).wait;
|
|
"Done".postln;
|
|
}
|
|
)
|
|
|
|
FluidBufSTFT.process(s,source:b,magnitude:m,phase:p)
|
|
m.getn(4444,10,{|x|x.postln;})
|
|
|
|
{ PlayBuf.ar(1,r); }.play
|
|
|
|
//nullsum
|
|
{ PlayBuf.ar(1,r) - PlayBuf(1,b); }.play
|
|
|
|
//draw the magnitudes as a greyscale spectrogram
|
|
// make the image
|
|
i = Image.new(m.numFrames, m.numChannels)
|
|
|
|
//retreive the image and assign to pixels
|
|
(
|
|
m.loadToFloatArray(action: {|x|
|
|
var mod = m.numChannels;
|
|
{
|
|
x.do{
|
|
|val, index|
|
|
i.setColor(Color.gray(val), index.div(mod), mod - 1 - index.mod(mod));
|
|
};
|
|
i.plot("spectrogram", showInfo: false);
|
|
}.fork(AppClock)
|
|
});
|
|
)
|
|
::
|