b = Buffer.read(s, "/home/lcoogan/snd/samples/freesound/vocals/ymaaela/attribution/330909__ymaaela__discordant-clip.mono.wav"); b = Buffer.read(s, "/home/lcoogan/snd/samples/freesound/vocals/ymaaela/333264__ymaaela__female-vocal-cut-ups-collage.mono.wav"); // with this b = Buffer.read(s, "/home/lcoogan/snd/releases/desolation-mountain/daven.stems/raoeu.wav"); w = Wavesets.from("/home/lcoogan/snd/releases/desolation-mountain/daven.stems/raoeu.wav"); b.play; s.boot // make a wavesets from a soundfile w = Wavesets.from("/home/lcoogan/snd/samples/freesound/vocals/ymaaela/attribution/330909__ymaaela__discordant-clip.mono.wav"); w = Wavesets.from("/home/lcoogan/snd/samples/freesound/vocals/ymaaela/333264__ymaaela__female-vocal-cut-ups-collage.mono.wav"); w = Wavesets.from("/home/lcoogan/.local/share/SuperCollider/Recordings/SC_250525_194956.wav"); w.dump; // contains mainly analysis data w.plot(200, 1); // plot a single waveset w.signal.copyRange(w.xings[600], w.xings[601]).plot; w.plot(600, 1); // a single w.plot(600, 5); // a group of five contiguous wavesets w.buffer; w.buffer.play; // build and add the SynthDefs Wavesets.prepareSynthDefs; // eventFor returns an event that can be played directly w.eventFor(startWs: 600, length: 5, repeats: 2).postln.play; w.eventFor(startWs: 600, length: 2, playRate: 1, repeats: 5).postln.play; w.eventFor(startWs: 600, length: 2, playRate: 0.5, repeats: 5).postln.play; w.eventFor(700, 20, 5, 1).play; ( fork { 666.do { |i| var ev = w.eventFor(i * 5, 2, 5, exprand(0.5, 1.0)); ev.put(\pan, 1.0.rand2).play; ev.sustain.wait; } }; ) ( b = w.buffer; Wavesets.prepareSynthDefs; ) ( var start, length, sustain, repeats = 20; #start, length, sustain = w.frameFor(150, 5); ( instrument: \wvst0, bufnum: b.bufnum, amp:1, start: start, length: length, sustain: sustain * repeats ).play; ) ) Quarks.directory; w.lengths.do({ |len, i| ("Waveset %" ++ i ++ ": length = " ++ len ++ ", amp = " ++ w.amps[i]).postln; }); w.plot(0, 1); // arg[0] = waveset index, arg[1] = waveset n ( // Normalize ~lens = w.lengths.normalize; ~amps = w.amps.normalize; // Combine into 2D array of feature vectors ~features = Array.fill(w.lengths.size, { |i| [~lens[i] * 5, ~amps[i]] }); // Very basic binning approach ~k = 10; ~clusters = Dictionary.new; ~features.do { |vec, i| var clusterID = ((vec[0] + vec[1]) * 0.5 * ~k).floor; ~clusters[clusterID] = (~clusters[clusterID] ?? { [] }) ++ [i]; }; ~clusters.keysValuesDo { |k, vals| ("Cluster " ++ k ++ ": " ++ vals).postln; }; ) ( // Play one representative from each cluster ~clusters.keysDo { |k| var wsIndex = ~clusters[k][0]; // First waveset in the cluster var ev = w.eventFor(startWs: wsIndex, length: 1, repeats: 1); ev.put(\pan, 1.0.rand2); // Random pan for stereo fun ev.play; }; ) ( // Build a map of representative wavesets for each cluster ~reps = Dictionary.new; ~clusters.keysDo { |k| ~reps[k] = ~clusters[k][0]; // Could improve: use actual centroid distance }; // Replace each waveset with its cluster's representative, but keep order fork { w.lengths.size.do { |i| var vec = [~lens[i] * 5, ~amps[i]]; var clusterID = ((vec[0] + vec[1]) * 0.5 * ~k).floor; var repIndex = ~reps[clusterID] ?? { i }; // fallback: original if rep not found var ev = w.eventFor(repIndex, 1, 1, 1); ev.put(\pan, 0).play; ev.sustain.wait; }; }; ) ( // Subtle morph: vary playback based on cluster fork { w.lengths.size.do { |i| var vec = [~lens[i] * 5, ~amps[i]]; var clusterID = ((vec[0] + vec[1]) * 0.5 * ~k).floor; var ev = w.eventFor(i, 1, 1, 1 + (clusterID * 0.01)); ev.put(\pan, clusterID.linlin(0, ~k, -1, 1)); ev.play; ev.sustain.wait; }; }; ) ///////////////////////// ( // the simplest synthdef as implented in *prepareSynthDefs: SynthDef(\wvst0, { arg out = 0, buf = 0, start = 0, length = 441, playRate = 1, sustain = 1, amp=0.2, pan; var phasor = Phasor.ar(0, BufRateScale.ir(buf) * playRate, 0, length) + start; var env = EnvGen.ar(Env([amp, amp, 0], [sustain, 0]), doneAction: 2); var snd = BufRd.ar(1, buf, phasor) * env; OffsetOut.ar(out, Pan2.ar(snd, pan)); }, \ir.dup(8)).add; ) Synth("wvst0", [\bufnum, b, \start, 0, \length, 600, \sustain, 4, \playRate, -0.4]);