Given a number of audio files, (say, *.wav), I'd like a command line way to mix these files as tracks with individual volumes, and define global loop points, so the audio mix loops seamlessly.
Could anyone suggest any alternatives?
Many thanks in advance,
Cheers!
In fact, a "command line looper" can almost be achieved with melt
and the file below – the problem is that: the looping is not really seamless (there are audible clicks); I cannot see a way to mix more than two channels; and in spite of adding the -audio-track | -hide-video
switch on the command line, a blank screen is still shown. (some more on looping in melt
here: Re: [Mlt-devel] loop for producer)
This command must be used to call melt
in "looping" mode:
melt eof=loop loop.mlt
… while the loop.mlt
file (calling upon audio files test.wav
and test2.wav
) is this (it will be 70 frames long during loop playback in total):
<mlt>
<producer id="producer0">
<property name="aspect_ratio">0.000000</property>
<property name="resource">test.wav</property>
<property name="audio_index">0</property>
<property name="video_index">-1</property>
<property name="global_feed">1</property>
</producer>
<producer id="producer1">
<property name="aspect_ratio">0.000000</property>
<property name="resource">test2.wav</property>
<property name="audio_index">0</property>
<property name="video_index">-1</property>
<property name="global_feed">1</property>
</producer>
<playlist id="playlist0">
<entry producer="producer0" in="0" out="30"/>
<blank length="10"/>
<entry producer="producer0" in="0" out="30"/>
</playlist>
<playlist id="playlist1">
<blank length="30"/>
<entry producer="producer1" in="0" out="10"/>
</playlist>
<tractor id="tractor0" title="loop.mlt" global_feed="1" in="0" out="71">
<multitrack id="multitrack0">
<track producer="playlist0" hide="video"/>
<track producer="playlist1" hide="video"/>
</multitrack>
<transition id="transition1" in="0" out="71">
<property name="a_track">0</property>
<property name="b_track">1</property>
<property name="mlt_service">mix</property>
<property name="start">0.5</property>
<property name="end">0.5</property>
<property name="combine">1</property>
<property name="always_active">1</property>
</transition>
</tractor>
</mlt>
Best Answer
Well, I think I found a solution for a Linux command-line multitrack audio looper - and that is to use a ChucK => Strongly-timed, On-the-fly Audio Programming Language script.
First of all,
ChucK
can be installed viasudo apt-get install chuck
in Debian/Ubuntu. However, after you install, try to typechuck
and then TAB in terminal; you should get something like:... that is to say - note that there are three
ChucK
executables; each for a separate Linux audio backend - and note that the default executable,chuck
, actually refers to JACK (the other executables, obviously, refer to ALSA and OSS).Since most typical users on Linux (also myself) do not actually have
jack
installed - running thechuck
executable may cause dissapointment, as it won't result with sound (given thatjack
is not present on the system); see, for instance:You may want to run
chuck --probe
and see what is reported for different backends - expect a complaint fromchuck
if JACK is not present and running, butchuck.alsa
should pass:For most users, then, running
chuck.alsa
instead should do the trick - however, note that this will likely take up the audio device directly (doesn't look likechuck
is aware ofpulseaudio
) - and then you will not be able to run other audio-generating programs (likevlc
) in parallel, and have the sound mixed from both applications (the other application will basically stay silent).But this being noted - we can now proceed with a
ChucK
script for looping.One of the great things about
ChucK
is that basially we can define one script that handles the playback and looping of just one sound - and then call multiple instances of that script in parallel - which effectively creates a multitrack audio looper!After some messing around with
ChucK
examples - see:... I managed to cook my own script - primarily based on examples: sndbuf.ck and valueat.ck - which I've called loopsndbuf.ck:
(see the online version for more comments)
Having saved this script, we can now call it with
chuck
as interpreter:... which will start loading the sound as in default settings, and looping it. Or, we can call the script with arguments - note that the character to separate arguments from a
chuck
script is colon (:
):... or, - finally - we can call multiple instances of the
loopsndbuf.ck
script, whichchuck
will run in parallel. For this, I'd rather put everything in a bash script, let's call itloopchuck.sh
:Running this script should basically load separate instances of the script, each with their own file and volume -
chuck
will then first load all audio into memory, spitting something like this to stdout:... and then, it will have all the scripts start at the same time - and then it will loop all the sounds individually at sample accuracy, according to their file length - wrapping the loop for each file, when it concludes, separately. In other words, the phases of the loops are independent (similar to how the GUI program terminatorX treats loops by default) - and that is exactly what I was looking for
:)
!! Note that you may have to press CTRL+C twice to fully stop theloopchuck.sh
script. (and yes, the audio samples used are from Freesound.org)Note, however, that while
chuck
loads all these files in memory, it uses quite a bit of CPU reproducing and mixing these loops - and so expect to have drops in the audio, if the OS has to handle some heavy operations (like GUI, say in the case when scrolling a webpage in your browser). In order to avoid this, I guess ajack
setup has to be used - but then one has to get involved with Linux real-time priorities and whatnot (which isn't necessarily a straightforward process).Well, I guess I'm happy now - since this is all I wanted (
I just wish I could mix this audio output with one from say- done, check other answer)vlc
or youtube infirefox
, though:)
; hope it helps others, too,Cheers!