I modified the Bases and Activations code to make a kind of vocoder, but I suspect there is probably a better way to do this. I’m still just not feeling like I have a great grasp on the toolkit yet. This seems like a not great choice because I’m splitting the file into 50 components and then using that to filter the sound. I can probably have it focus more on the characteristic frequency bands for speech somehow? And maybe I’m also just going about this the wrong way.
// ====== bases and activations ========
Buffer.freeAll
~drums = Buffer.read(s, FluidFilesPath("Tremblay-AaS-VoiceQC-B2K-M.wav"), 0, -1, {|b| b.play});
// first, let's make two new buffers called...
~bases = Buffer(s);
~activations = Buffer(s);
~n_components = 50;
// and we'll explicitly pass these into the process
FluidBufNMF.processBlocking(s,~drums,bases:~bases,activations:~activations,components:~n_components,action:{"done".postln;});
// now we can plot them (yours may end up in a different order!):
~bases.plot;
// the bases are a like a spectral template that FluidBufNMF has found in the source buffer
~activations.plot;
// the activations are the corresponding loudness envelope of each base above. It will look like an amplitude
// envelope follower of the drum hits in the corresponding bases.
// ========= the activations could also be used as an envelope through time ===========
// we'll use 2 components here since we have just two speakers...
FluidBufNMF.processBlocking(s,~drums,bases:~bases,activations:~activations,components:2,action:{"done".postln;});
(
{
var activation = PlayBuf.ar(2,~activations,BufRateScale.ir(~activations),doneAction:2);
var sig = LFTri.ar([300,400],0,0.2) * activation;
sig;.
}.play;
)
// note that the samplerate of the ~activations buffer is not a usual one...
~activations.sampleRate
(
{
var activation = PlayBuf.ar(2,~activations,BufRateScale.ir(~activations),doneAction:2);
var sig = WhiteNoise.ar(1);
sig = FluidNMFFilter.ar(sig,~bases,2) * activation;
sig.sum!2;
}.play;
)