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.

154 lines
3.4 KiB
Markdown

/* ======= 1. Hear the Sound ============
load a part of a sound that has 3 clear components:
- a clear pitch component to start
- a noisy pitchless ending
- DC offset silence on both ends
*/
(
~src = Buffer.read(s,File.realpath(FluidBufPitch.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Tremblay-ASWINE-ScratchySynth-M.wav");//,42250,44100);
)
// listen
~src.play;
// ======= Let's try to extract that frequency from the audio file. ===========
// analyze
~pitches = Buffer(s);
~stats = Buffer(s);
FluidBufPitch.process(s,~src,features: ~pitches);
FluidBufStats.process(s,~pitches,stats:~stats);
(
// get the average freq;
~stats.get(0,{
arg f;
~avgfreq = f;
~avgfreq.postln;
});
)
(
// play a sine tone at the avg freq alongside the soundfile
//average freq
~avgfreq_synth = {SinOsc.ar(~avgfreq,mul: 0.05)}.play;
//compare with the source
~src.play;
)
// hmm... that seems wrong...
/*
what if we weight the average frequency by the loudness
of the analysis frame so that the silences are not considered
as strongly.
*/
// do a loudness analysis
~loud = Buffer(s);
FluidBufLoudness.process(s,~src,features:~loud);
FluidBufStats.process(s,~loud,stats:~stats);
(
// get min and max
~stats.loadToFloatArray(action:{
arg stats;
~min_loudness = stats.clump(2).flop[0][4];
~max_loudness = stats.clump(2).flop[0][6];
~min_loudness.postln;
~max_loudness.postln;
});
)
// scale the loudness analysis from 0 to 1, using the min and max gotten above
~scaled = Buffer(s);
FluidBufScale.process(s,~loud,numChans: 1,destination: ~scaled,inputLow: ~min_loudness,inputHigh: ~max_loudness);
// then use this scaled analysis to weight the statistical analysis
FluidBufStats.process(s,~pitches,numChans:1,stats:~stats,weights:~scaled);
(
// get the average freq (now with the weighted average)
~stats.get(0,{
arg f;
~avgfreq = f;
~avgfreq.postln;
});
)
(
// play a sine tone at the avg freq alongside the soundfile
//average freq
~avgfreq_synth = {SinOsc.ar(~avgfreq,mul: 0.05)}.play;
//compare with the source
~src.play;
)
// hmm... still wrong. too low now.
/*
ok, how about if we weight not by loudness, but by the pitch confidence of the pitch analysis
*/
FluidBufPitch.process(s,~src,features: ~pitches);
~thresh_buf = Buffer(s);
FluidBufThresh.process(s, ~pitches, startChan: 1, numChans: 1, destination: ~thresh_buf, threshold: 0.8)
FluidBufStats.process(s,~pitches,numChans:1,stats:~stats,weights:~thresh_buf);
(
// get the average freq
~stats.get(0,{
arg f;
~avgfreq = f;
~avgfreq.postln;
});
)
(
// play a sine tone at the avg freq alongside the soundfile
//average freq
~avgfreq_synth = {SinOsc.ar(~avgfreq,mul: 0.05)}.play;
//compare with the source
~src.play;
)
// closer!
FluidBufPitch.process(s,~src,features: ~pitches);
(
~pitches.loadToFloatArray(action:{
arg pitches;
defer{pitches.histo(50,1000,20000).plot(discrete:true)};
});
)
// raise the threshold and toss out some outliers
FluidBufPitch.process(s,~src,features: ~pitches);
~pitches.plot(separately:true);
~thresh_buf = Buffer(s);
FluidBufThresh.process(s, ~pitches, startChan: 1, numChans: 1, destination: ~thresh_buf, threshold: 0.9)
FluidBufStats.process(s,~pitches,numChans:1,stats:~stats,weights:~thresh_buf,outliersCutoff:1.5);
(
// get the average freq
~stats.get(0,{
arg f;
~avgfreq = f;
~avgfreq.postln;
});
)
(
// play a sine tone at the avg freq alongside the soundfile
//average freq
~avgfreq_synth = {SinOsc.ar(~avgfreq,mul: 0.05)}.play;
//compare with the source
~src.play;
)