// this example uses the ConstQ class of Eisenkraut
// to get a logarithmic spectrum of some soundfile.
// i just included it to not loose the code ;-3
// but it's very slow due to the array mangling
// between swingOSC and sclang.
(
~path = "sounds/a11wlk01.wav".absolutePath; // "/Users/rutz/Desktop/FactoryHallWetCut.aif";
~stepSize = 1024;
~minFreq = 50.0;
~maxFreq = 16000.0;
~bandsPerOct = 24; // 12;
)
g.reboot;
// note: change the following URL according to your Eisenkraut installation.
// you need SVN revision 140 or newer!
g.addClasses( "file:///Users/rutz/Documents/workspace/Eisenkraut/Eisenkraut.jar" );
(
~sf = SoundFile.openRead( ~path );
~constQ = JavaObject( "de.sciss.eisenkraut.math.ConstQ" );
~constQ.setSampleRate( ~sf.sampleRate );
~constQ.setMinFreq( ~minFreq );
~constQ.setMaxFreq( ~maxFreq );
//~constQ.setMaxTimeRes( 4.0 );
~constQ.setBandsPerOct( ~bandsPerOct );
~constQ.createKernels;
// (
fork {
~fftSize = ~constQ.getFFTSize_; ~numKernels = ~constQ.getNumKernels_;
~numSteps = (~sf.numFrames - (~fftSize - ~stepSize)).div( ~stepSize );
~coeffs = nil ! ~numSteps;
[ ~fftSize, ~numKernels ].postln;
~numSteps.do({ arg step;
~sf.seek( ~stepSize * step );
~inBuf = FloatArray.newClear( ~fftSize );
~sf.readData( ~inBuf );
~fBuf = ~constQ.castToFloatArray__( ~inBuf );
~outBuf = ~constQ.transform__( ~fBuf, 0, ~fftSize, nil, 0 );
~coeffs[ step ] = Array.fill( ~numKernels, { arg i; ~constQ.getArrayElement_( ~outBuf, i )});
~fBuf.destroy;
~outBuf.destroy;
(((step+1)/~numSteps) * 100).asInteger.postln;
0.yield;
});
"Done.".postln;
~sf.close;
};
// )
)
// the frequencies are static
~freqs = Array.fill( ~numKernels, { arg k; ~minFreq * pow( 2, k / ~bandsPerOct )});
s.boot;
// use a bank of fast sine oscillators for reproducation
~osciClass = SinOsc;
//~osciClass = FSinOsc;
//~osciClass = LFSaw;
//~osciClass = LFTri;
x = { arg amp = 50; var amps = LagControl.names( \amps ).kr( Array.fill( ~numKernels, 0 ), Array.fill( ~numKernels, 0.1 )); Mix( ~osciClass.ar( ~freqs, 0, amps )) * amp }.play;
// let's go through the sonogram
(
fork {
~coeffs.do({ arg frame, i;
x.setn( \amps, frame );
(((frame+1)/~coeffs.size) * 100).asInteger.postln;
0.05.wait;
});
}
)
x.free;
// filtered noise? warning: needs lots of CPU
x = { arg amp = 50; var amps = LagControl.names( \amps ).kr( Array.fill( ~numKernels, 0 ), Array.fill( ~numKernels, 0.1 )); Mix( Resonz.ar( WhiteNoise.ar( amps ), ~freqs, 0.02 )) * amp }.play;
// backwards
(
fork {
~coeffs.reverseDo({ arg frame, i;
x.setn( \amps, frame );
(((frame+1)/~coeffs.size) * 100).asInteger.postln;
0.04.wait;
});
}
)
x.free;
//////////////////////////////
~logCoeffs = ~coeffs.collect({ arg frame; frame.collect(_.ampdb)});
//GUI.swing;
// headMap Quark required!
// warning: very slow, so we limit the number of frames shown!
~logCoeffs.keep( 50 ).heatMap( showVals: false, colscheme: \coals );