Timeline mixing
Arrange sounds on a tempo grid and tracks, pump a bass to the kick, and duck music under a voice.
A timeline holds named tracks at one sample rate and a tempo grid. You place sounds on tracks at times, and ducking and track volumes are applied when it is rendered, so the stored tracks are never altered and the timeline can be changed and rendered again.
t = audioTimeline( bpm=120, beatsPerBar=4, sampleRate=44100, channels=2 );
kick = audioDrum( "kick" );
hat = audioDrum( type="hat", seed=2, level=0.5 );
pad = audioGain( audioFilter( audioOsc( "saw", audioFreq( "A2" ), 4 ), "lowpass", 900, 0.8 ), -12 );
audioAdd( timeline=t, sound=pad, at=0, track="music" );
for( at in audioBeats( t, 0, 16 ) ){
audioAdd( timeline=t, sound=kick, at=at, track="drums", db=-4 );
}
for( at in audioBeats( t, 0.5, 16, 1 ) ){
audioAdd( timeline=t, sound=hat, at=at, track="drums", db=-12, pan=0.3 );
}
audioSave( audioRender( timeline=t, tail=1 ), "beat.wav" );
t.beat( n ) and t.bar( n ) turn beats and bars into seconds. audioBeats( t, start, end, step ) lists moments on the grid, such as every beat, or every half beat with step=0.5. Sounds with another sample rate are converted for you, and mono sounds are panned into the stereo field with pan.
Make the bass pump
audioPump dips a track at given moments with a quick recovery, like a sidechain compressor keyed by the kick.
t = audioTimeline( bpm=124 );
kick = audioDrum( "kick" );
bass = audioGain( audioFilter( audioOsc( "saw", audioFreq( "A1" ), 8 ), "lowpass", 500, 1.2 ), -8 );
audioAdd( timeline=t, sound=bass, at=0, track="bass" );
for( at in audioBeats( t, 0, 16 ) ){
audioAdd( timeline=t, sound=kick, at=at, track="drums" );
}
audioPump( t, "bass", audioBeats( t, 0, 16 ), -6, 0.18 ); // down 6 dB on each kick, back in 0.18 s
mix = audioRender( t );
Duck music under a voice
audioDuck lowers a track while another is loud, which is the mix you would otherwise do by hand when a voice-over comes in.
t = audioTimeline( bpm=100 );
audioAdd( timeline=t, sound=music, at=0, track="music", db=-10 );
audioAdd( timeline=t, sound=voice, at=t.bar( 1 ), track="voice" );
audioDuck( t, "music", "voice", -9, -40, 0.01, 0.3 ); // down 9 dB while the voice is above -40 dB
mix = audioRender( timeline=t, tail=1 );
The voice-over example and the trailer guide use exactly this.
Track volume
audioTrackGain( t, "music", -6 ) sets the volume of a whole track. Use it to keep the music below the voice even when nobody speaks, and let audioDuck take it further while someone does.
Finish the mix
Render, fade, and finish with either audioSaturate (a warm tanh limiter that also normalizes the peak) or audioMaster, which delivers a loudness target.
mix = audioFade( audioRender( timeline=t, tail=2 ), 0.05, 1.5, "smooth" );
audioSave( audioMaster( audio=mix, target="streaming" ), "final.wav" );