Sound design (day 3 at APO33)

With the basic sound of the wavetables, the next layer of sound is connected to the bouncy balls connected to the main structure. From these balls, I take a rest position and use their velocity and deviation from the rest position as parameters. These parameters are then connected to a granular use of the signal buffers that are also used for the wavetable synthesis, using indirect mapping from the Influx quark in SuperCollider. The amplitude is mapped directly to the amount of deviation from the rest position.

This mapping results in an intensely noisy sound reaction if the model gets excited a lot.

The SynthDef

SynthDef( \grainBuf, {
    Out.ar( \out.kr(0),
        LeakDC.ar(
            ( 
            GrainBuf.ar( 2, Dust.ar( \dens.kr(10) ), \gdur.kr(0.1), \bufnum.kr(0), 
                \rate.kr(1) * LFNoise0.ar(\nfreq.kr(30), \nmul.kr(0.1), 1 ), 
                \gpos.kr(0.5), pan: \pos.kr(0)
            ) * 
            EnvGen.ar( Env.perc, Dust.ar( \rateEnv.kr(10) ), timeScale: \dur.kr(0.1) )
            * \amp.kr(0.1)
            ).tanh
        )
    );
}).add;

Instantiating the synths

~bouncySynths = 100.collect{ |it| 
    Synth.new( \grainBuf, [\bufnum, ~sigbuffers[it%10], \rate, 1, \amp,0.01, \pos, 1.0.rand2 ] )
};

Mapping through Influx and KMap

~influx = Influx( [\px, \py, \pz, \vx, \vy, \vz ], [\a,\b,\c,\d,\e,\f,\g,\h ] );
~kmap = KMap.new;

[
    [\a,\b,\c,\d,\e,\f,\g ],
    [\rate, \gdur, \gpos, \fmul,  \dens, \rateEnv, \dur ]
].flop.do{ |it|
    ~kmap.addPar( it[0], it[1] );
};

~kmap.addSpec( \rate, [0.1, 300, \exponential ] );
~kmap.addSpec( \gdur, [0.001, 0.05, \exponential ] );
~kmap.addSpec( \gpos, [0, 1, \linear ] );
~kmap.addSpec( \fmul, [0.05, 0.5, \exponential ] );
~kmap.addSpec( \dens, [1, 500, \exponential ] );
~kmap.addSpec( \rateEnv, [0.1, 50, \exponential ] );
~kmap.addSpec( \dur, [0.2, 10, \exponential ] );

[\a,\b,\c,\d,\e,\f,\g ].do{ |it| ~kmap.addSpec( it, [-1,1] ) };

~ampSpec = [0.001, 0.25, \exponential ];
~dposASpec = [0.2, 100, \exponential ].asSpec;
~dposSpec = [0.001, 100, \exponential ].asSpec;
~velSpec = [0.001, 100, \exponential ].asSpec;
~restBouncyPositions = 10.collect{ |i| 
    10.collect{|j| ~physics.getBouncyParameter( i, j, \position ); }
};

At each update of the model, do the mapping

var vel, pos, velMapped, posMapped, ampSum, amp;
ampSum = 0;
10.do{ |i|
    10.do{ |j|
        vel = ~physics.getBouncyParameter( i, j, \velocity );
        pos = ~physics.getBouncyParameter( i, j, \position ) - ~restBouncyPositions[i][j];
        velMapped = (~velSpec.unmap( vel.abs ) * vel.sign );
        posMapped = (~dposSpec.unmap( pos.abs ) * pos.sign);
        ~influx.set( *([ [\px, \py, \pz, \vx, \vy, \vz ], posMapped ++ velMapped ].flop.flat) );
        ~bouncySynths[i*10+j].set(
            *~kmap.getMapped(
                *(~influx.outNames.collect{ |it| [it, ~influx.outValDict.at( it ) ] }.flat;)
            )
        );
        amp = pos.collect{ |it| it.pow(2) }.sum.specMap( ~dposASpec, ~ampSpec );
        ~bouncySynths[i*10+j].set( \amp, amp );
        ampSum = ampSum + amp;
    };
};
Wed, 17 August, 2016
RSS Feed