Light design (day 3 at APO33)

After the direct mapping of the energy to the light - I decide that I need a more clear distinction in levels. So I create leaky integrators of the energy, and when the value from this gets passed a certain threshold, that corner shifts to a different light color.

Within these states and associated colors, the intensity varies directly with the energy, as before.

In addition, when the energy state changes, also the basic chord of the wavetable synthesis shifts, and the bouncy granular sounds get a new mapping of their parameters.

x.addExpected( 203, \energyInt, 4 );
x.setData( 203, [0,0,0,0] );

~leakPump = 0.01;
~leakLeak = 0.995;
x.nodes[201].action = { |data| 
    x.setData( 203, (~leakPump * data) + (~leakLeak * x.nodes[203].data) )
};

~energyThresholdsUp = (1..10).collect{ |it| [0.001,1.0, 7 ].asSpec.map( it/10 ) } ++ [ 1 ];
~energyThresholdsDown = [0] ++ (~energyThresholdsUp * 0.95);
~currentEnergyState = [0,0,0,0];
~colorHues = Array.series( 11, 0.0, 1/11 );

(
Tdef( \setLightsEnergy, {
var hasStateChange;
loop{
    hasStateChange = false;
    x.nodes[203].data.do{ |it,i|
        if ( it > ~energyThresholdsUp[ ~currentEnergyState[i] ] ){
            hasStateChange = true;
            ~currentEnergyState[i] = ~currentEnergyState[i] + 1;
            ~currentEnergyState.postln;
            ~influx.rand;
            ~currentEnergyState[i] = ~currentEnergyState[i].clip(0,~energyThresholdsUp.size-1);
        }{
            if ( it < ~energyThresholdsDown[ ~currentEnergyState[i] ] ){
                hasStateChange = true;
                ~currentEnergyState[i] = ~currentEnergyState[i] - 1;
                ~currentEnergyState.postln;
                ~influx.rand;
                ~currentEnergyState[i] = ~currentEnergyState[i].clip(0,~energyThresholdsUp.size-1);
            };
        };
        ~currentEnergyState[i] = ~currentEnergyState[i].clip(0,~energyThresholdsUp.size-1);
        ~intensity = x.nodes[202].data[i].specMap( ~energySpec, ~intensitySpec );
        ~color = Color.hsv( ~colorHues[ ~currentEnergyState[i] ], 1, ~intensity, 0 ).asArray;
        // ~color.postln;
        ~microWashes[i].rgbw_( *~color );
    };
    if ( hasStateChange ) { ~updateChord.value( ~currentEnergyState.sum.fold(0,15) ); };
    ~setAllLights.value;
    0.05.wait;
}
});
);

Tdef( \setLightsEnergy ).play;
Wed, 17 August, 2016

Sound design (first two days at APO33)

With the physics model created, then the question was of course how to make translate the resulting data into sound. The first idea I try out is if I take the distance from the center rod of each ring of nodes as a wave amplitude. So in other words, I translate these distances to a wavetable, which is then played back. As the model is set into motion, this will cause the waves to become louder and more complex at the same time.

(
SynthDef( \wavetable, {
    var bufSelect = Linen.kr( \gate.kr(1), \fade.kr(0.25), 1, \fade.kr );
    var signal = VOsc.ar( \bufnum.kr(0) + bufSelect, \freq.kr(500), \phase.kr(0) );
    Out.ar( \out.kr(0), Pan2.ar( signal, \pos.kr(0), \amp.kr(0.1) ) );
}).add;
);


10.do{ |jt, j|
    var distances = 10.collect{ |it| 
        ~physics.getParticleParameter( jt, it, \distance );
    } - ~meanParticleDistances[j];
    ~sigs[j] = ~createSplineSignal.value( distances );
    if ( ~sigs[j].notNil ){
        ~wavebuffers[j][~bufid].loadCollection( ~sigs[j].asWavetable );
        ~wavetables[j].set( \gate, ~bufid );
    };
};

To smooth the wavetable, I am using splines to interpolate to a smooth function between the points. Occasionally these give a glitch in the sound, so I am doing a check whether the glitch happens.

~createSplineSignal = { |indata|
    var splinedata, spline, signal;
    var data = indata;
    var maxData = data.maxItem;
    data = data ++ data[0];
    splinedata = [ (0..10), data ].flop;
    spline = BSpline( splinedata, 3 );
    signal = spline.interpolate(256).flop[1];
    // sometimes there is a strange glitch in the interpolation,
    // so we need to catch it:
    if ( (maxData - signal.maxItem).abs > 5.0 ){ 
        maxData.post; "\t".post;signal.maxItem.postln;
        nil;
    }{
        Signal.newFrom( signal );
    }
};
Tue, 16 August, 2016
RSS Feed