Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/UMAP.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

:control numNeighbours:

The number of neighbours considered by the algorithm to balance local vs global structures to conserve. Low values will prioritise preservation of the local structure while high values will prioritise preservation of the global structure.
The number of neighbours considered by the algorithm to balance local vs global structures to conserve. Low values will prioritise preserving local structure, high values will help preserve the global structure.

:control minDist:

Expand Down
71 changes: 54 additions & 17 deletions example-code/sc/AudioTransport.scd
Original file line number Diff line number Diff line change
@@ -1,27 +1,64 @@

code::
//didactic - the mouse X axis interpolates between the two sinewaves
{FluidAudioTransport.ar(SinOsc.ar(220,mul: 0.1),SinOsc.ar(440,mul: 0.02),MouseX.kr())}.play;

//notice how the interpolation quantizes to the FFT bins. Like most spectral processes, it benefits from oversampling the fft... at the cost of CPU power, obviously.
{FluidAudioTransport.ar(SinOsc.ar(220,mul: 0.1),SinOsc.ar(440,mul: 0.02),MouseX.kr(),fftSize: 8192)}.play;
(
~srcA = Buffer.readChannel(s,FluidFilesPath("Tremblay-CEL-GlitchyMusicBoxMelo.wav"),channels:[0]);
~srcB = Buffer.readChannel(s,FluidFilesPath("Nicol-LoopE-M.wav"),channels:[0]);
)

// when the signal is steady, larger hopSize can be accommodated to save back on the CPU
{FluidAudioTransport.ar(SinOsc.ar(220,mul: 0.1),SinOsc.ar(440,mul: 0.02),MouseX.kr(),windowSize: 8192)}.play; // here we get a default hop of half the window so 8 times less than above.
(
{
var srcA = PlayBuf.ar(1,~srcA,BufRateScale.ir(~srcA),loop:1);
var srcB = PlayBuf.ar(1,~srcB,BufRateScale.ir(~srcB),loop:1);
FluidAudioTransport.ar(srcA,srcB,MouseX.kr,1024,64,2048).dup;
}.play
)

//if you CPU can cope, try this setting, almost smooth, but attacks would smear (the Y axis mixes some in to hear the effect)
{var attacks = Impulse.ar(1,mul: MouseY.kr(-40,10).dbamp); FluidAudioTransport.ar(SinOsc.ar(220,mul: 0.1,add: attacks),SinOsc.ar(440,mul: 0.02,add: attacks),MouseX.kr(),windowSize: 16000)}.play;
::
strong::The impact of FFT Settings::
The larger the FFT size the better it blends the spectral qualities at the expense of smearing attacks. This will have a drastic impact on the characteristic of the interpolation.
code::

(
~srcA = Buffer.readChannel(s,FluidFilesPath("Tremblay-CEL-GlitchyMusicBoxMelo.wav"),channels:[0]);
~srcB = Buffer.readChannel(s,FluidFilesPath("Nicol-LoopE-M.wav"),channels:[0]);
)

//richer with complex spectra
//load 2 files
(
b = Buffer.read(s,FluidFilesPath("Tremblay-CEL-GlitchyMusicBoxMelo.wav"));
c = Buffer.read(s,FluidFilesPath("Tremblay-CF-ChurchBells.wav"));
~synth = {
arg windowSize = 1024, hopSize = 64, fftSize = 2048;
var srcA = PlayBuf.ar(1,~srcA,BufRateScale.ir(~srcA),loop:1);
var srcB = PlayBuf.ar(1,~srcB,BufRateScale.ir(~srcB),loop:1);
FluidAudioTransport.ar(srcA,srcB,MouseX.kr,windowSize,hopSize,fftSize,16384).dup;
}.play
)
//listen to them
b.play
c.play
//stereo cross!
{FluidAudioTransport.ar(PlayBuf.ar(2,b,loop: 1),PlayBuf.ar(2,c,loop: 1),MouseX.kr())}.play;

// Try these different FFT settings to see how they affect the results of the audio transport algorithm

~synth.set(\windowSize,256,\hopSize,16,\fftSize,256);
~synth.set(\windowSize,1024,\hopSize,16,\fftSize,1024);
~synth.set(\windowSize,1024,\hopSize,-1,\fftSize,-1);
~synth.set(\windowSize,2048,\hopSize,-1,\fftSize,-1);
~synth.set(\windowSize,4096,\hopSize,-1,\fftSize,-1);
~synth.set(\windowSize,16384,\hopSize,-1,\fftSize,-1);

::
Creative Modulation
code::

(
~srcA = Buffer.readChannel(s,FluidFilesPath("Tremblay-CEL-GlitchyMusicBoxMelo.wav"),channels:[0]);
~srcB = Buffer.readChannel(s,FluidFilesPath("Nicol-LoopE-M.wav"),channels:[0]);
)

(
{
var srcA = PlayBuf.ar(1,~srcA,BufRateScale.ir(~srcA),loop:1);
var srcB = PlayBuf.ar(1,~srcB,BufRateScale.ir(~srcB),loop:1);
var amp = Amplitude.kr(srcB);
var interp = LFDNoise3.kr(100 * amp).range(0,1).poll;
var sig = FluidAudioTransport.ar(srcA,srcB,interp,2048).dup;
sig + (srcB * -20.dbamp);
}.play
)
::
43 changes: 17 additions & 26 deletions example-code/sc/BufAudioTransport.scd
Original file line number Diff line number Diff line change
@@ -1,36 +1,27 @@

code::
//Didactic:
//Make 2 sinewave sources to be interpolated
(
b = Buffer.loadCollection(s, FloatArray.fill(44100, {|a|(a / pi).sin * 0.1}));
c = Buffer.loadCollection(s, FloatArray.fill(44100, {|a|(a / pi / 2).sin * 0.02}));
d = Buffer.new
~srcA = Buffer.readChannel(s,FluidFilesPath("Tremblay-CEL-GlitchyMusicBoxMelo.wav"),channels:[0]);
~srcB = Buffer.readChannel(s,FluidFilesPath("Nicol-LoopE-M.wav"),channels:[0]);
)

//make an sound interpolating their spectrum
FluidBufAudioTransport.process(s,b,source2:c,destination:d,interpolation:0.5,action:{"Ding".postln})

// listen to the source and the result
b.play
c.play
d.play

// note that the process is quantized by the spectral bins. For an example of the pros and cons of these settings on this given process, please see the realtime FluidAudioTransport helpfile.

// more interesting sources: two cardboard bowing gestures
// fft settings have a large impact on the results. play around with them to hear how.
// and/or see the (real time) FluidAudioTransport example code
(
b = Buffer.read(s,FluidFilesPath("Green-Box641.wav"));
c = Buffer.read(s,FluidFilesPath("Green-Box639.wav"));
d = Buffer.new
~result = Buffer(s);
FluidBufAudioTransport.processBlocking(s,
sourceA:~srcA,
sourceB:~srcB,
destination:~result,
interpolation:0.5,
windowSize:1024, // this is the default
hopSize:512, // this is the default
fftSize:1024, // this is the default
action:{"done".postln;}
);
)

// listen to the source
b.play
c.play
// the output will be the same length as the shorter source buffer
~result.play;

// process and listen
FluidBufAudioTransport.process(s,b,source2:c,destination:d,interpolation:0.5,action:{"Ding".postln})
d.play
// try various interpolation factors (0.1 and 0.9 are quite good
::
100 changes: 66 additions & 34 deletions example-code/sc/BufChroma.scd
Original file line number Diff line number Diff line change
@@ -1,50 +1,82 @@

code::
// create some buffers
(
b = Buffer.read(s,FluidFilesPath("Tremblay-SlideChoirAdd-M.wav"));
c = Buffer.new(s);
)

// run the process with basic parameters
~src = Buffer.read(s,FluidFilesPath("Harker-DS-TenOboeMultiphonics-M.wav"));

// listen if you want
~src.play;

(
Routine{
t = Main.elapsedTime;
FluidBufChroma.process(s, b, features: c, windowSize: 4096).wait;
(Main.elapsedTime - t).postln;
}.play
fork({
var win, synth;
var chroma = Buffer(s);

FluidBufChroma.processBlocking(s,~src,features:chroma);

s.sync;

synth = {
arg index = 0;
var chromaVector = BufRd.kr(12,chroma,index,1,1);
var freqs = 440 * 12.collect{arg i; 2.pow(i/12)};
var sig = SinOsc.ar(freqs,0,chromaVector);
Splay.ar(sig);
}.play;

win = Window("FluidChroma: click me to hear sines of the chroma analysis",Rect(0,0,1600,400));

FluidWaveform(~src,featuresBuffer:chroma,parent:win,bounds:win.bounds,stackFeatures:true,standalone:false);

UserView(win,win.bounds).mouseDownAction_{
arg view, x, y;
var index = x.linlin(0,view.bounds.width,0,chroma.numFrames-1).asInteger;
synth.set(\index,index);
};

win.front;
},AppClock)
)

// listen to the source and look at the buffer
b.play;
c.plot
::
strong::Dividing the octave into more than 12 divisions::
code::

// doing a chroma analysis dividing the octvae into 19 equal divisions:

STRONG::A stereo buffer example.::
CODE::
~src = Buffer.read(s,FluidFilesPath("Harker-DS-TenOboeMultiphonics-M.wav"));

// listen if you want
~src.play;

// load two very different files
(
b = Buffer.read(s,FluidFilesPath("Tremblay-SA-UprightPianoPedalWide.wav"));
c = Buffer.read(s,FluidFilesPath("Tremblay-AaS-AcousticStrums-M.wav"));
)
fork({
var win, synth;
var chroma = Buffer(s);

// composite one on left one on right as test signals
FluidBufCompose.process(s, c, numFrames:b.numFrames, startFrame:555000,destStartChan:1, destination:b)
b.play
FluidBufChroma.processBlocking(s,~src,features:chroma,numChroma:19);

// create a buffer as destinations
c = Buffer.new(s);
s.sync;

//run the process on them
(
Routine{
t = Main.elapsedTime;
FluidBufChroma.process(s, b, features: c, windowSize: 4096).wait;
(Main.elapsedTime - t).postln;
}.play
synth = {
arg index = 0;
var chromaVector = BufRd.kr(chroma.numChannels,chroma,index,1,1);
var freqs = 440 * chroma.numChannels.collect{arg i; 2.pow(i/chroma.numChannels)};
var sig = SinOsc.ar(freqs,0,chromaVector);
Splay.ar(sig);
}.play;

win = Window("FluidChroma: click me to hear sines of the chroma analysis",Rect(0,0,1600,400));

FluidWaveform(~src,featuresBuffer:chroma,parent:win,bounds:win.bounds,stackFeatures:true,standalone:false);

UserView(win,win.bounds).mouseDownAction_{
arg view, x, y;
var index = x.linlin(0,view.bounds.width,0,chroma.numFrames-1).asInteger;
synth.set(\index,index);
};

win.front;
},AppClock)
)

// look at the buffer: 12 chroma bins for left, then 12 chroma bins for right
c.plot(separately:true)
::
Loading