@steve and @christop
OK I have re-read what you both have written and reconsidered my approach but with a caveat,
please don’t expect help with the code if it does not work for any specific purpose.
I coded it with a specific purpose in mind and as far as that goes, it’s working
for me so as far as I’m concerned, it’s job done.
@christop
Github Gist is a great idea but I don’t want to have to sign up and go thru all that, so will
rather just post the code here as it is Audacity related.
As to your valid point about the overlap between Linux users and knowing C, I suspect there
will be an even bigger overlap if it was done in Bash, albeit with some dependencies.
So re-wrote it in Bash and will post here.
Please read the notes before using it.
Although the script looks long (217 lines, it’s mostly comments, the actual code is around 10% of that).
Regarding your example of someone using it for inserting sweepers and bumpers, I don’t think
it will be the right tool for the job, as it was written for short, periodic sound clips such as drums.
But feel free to experiment and modify as you see fit.
@steve
To make it easier for potential users to peruse the code before downloading it, will post here
as CODE and also as an attachment (just change the extension from .txt to .sh).
Hope that is OK.
If not, please feel free to amend this post as you see fit.
#!/bin/bash
# ====================================================================================
#
# License for this script is CC0
# and you as the user assume all responsibility by using it.
#
# Please read carefully before using.
#
# ============
# DESCRIPTION:
# ============
#
# Linux Bash script to take Audacity exported timing file and convert
# to a single wav file with drum beats seperated by the
# timing in LabelTrack.txt
#
# The resulting wav file can then be dragged back into Audacity.
#
# The original version of this script was actually a compiled C pgm.
# However after re-reading comments by @Steve and @christop on the
# Audacity forum, I realize that compiling and indeed knowing C and having
# the tool chain, may be a problem for many.
# So here is a Bash only version, the downside is it has some dependencies
# and some are version specific due to bugs in them.
# This script is also orders of magnitude slower than the compiled C pgm.
# I guess that is the price to be paid for convinience ;-)
#
# Dependencies for this script are Sox, bc and ffmpeg
#
# Very N.B. The latest version of sox (14.x) has several known bugs,
# I used v12.18.2
# bc version is 1.07.1 but most will do.
# ffmpeg is version 4.1.10 but most newer ones will be OK.
#
# Note that silence.wav and beat.wav must be mono and originally created by you.
#
# To change the drum sample, just overwrite the current one
# but keep the name the same, i.e. beat.wav or change the script.
# Remember, must be mono 16 bit wav.
# Must also compensate for it's length when we send to bc.
# (Watch out for this or you will get wrong timing placements)
#
# ================
# NOTES ON USING:
# ================
#
# Create a folder, I called mine TimingsToBeats (same as this script)
# and in there place this script (with exec permissions), and silence.wav
# which is just a mono 10 sec clip of silence which this script will
# create temp files from with needed durations and then delete the temp files.
# It will not delete silence.wav itself.
#
# Make sure you create a 10 sec silence mono file before running this script.
# Easy enough in Audacity, just export as Mono, wav (16 bit) at 44.1KHz
# The exported LabelTrack.txt file from Audacity should also be saved in this folder.
#
# Also ensure you have a short, mono "beat.wav" file in the same folder.
# This is the audio clip that this script will insert at the timings in the LabelTrack.txt
#
# To execute the script, open a command prompt in the folder and type:
# ./TimingsToBeats.sh
#
# If all goes well, you should see a printout for each "time" entry and a
# "Conversion Complete" message at the end.
#
# ==========================
# MORE NOTES AND DISCLAIMER:
# ==========================
#
# I wrote this for a specific need I have, i.e. to add extra percussion to existing
# audio tracks.
# As such, percussion sounds tend to be short (50 - 100 mS in most cases) and also,
# and this is important, percussion is mono in a mix (i.e. center).
# With that in mind, this script is only meant for mono files, starting with the
# LabelTrack.txt file, to the silence and the extra percussion sound to add.
# It will not work with ultra long sounds or stereo tracks as is.
#
# The script is simple enough and well commented so if it does not work for you,
# modify it until it does.
#
# Also, please don't ask for help or send bug reports and expect a reply from me.
# I don't mean to come across as rude, but I simply don't have the time to tend to them.
# From time to time, I do visit the forum and may comment but don't hold me to it.
# You are of course free to discuss, modify and comment amongst yourselves for the
# benefit of yourself and others.
#
# As I mentioned before, this in the Bash version and as such, will not be as quick
# or as efficiently coded as it's C version.
#
# Are there bugs? Probably but it does the job for me so mission accomplished.
# Please also be aware that there is no error checking whatsoever, originally
# this script (pgm actually) was only for my own use until I was convinced to
# publicly release it. ;-)
#
# Lastly, keep in mind that when used to add percussion sounds to an existing
# audio track, there will be drift over time.
# This is due to the slight timing differences of the system where the audio track
# was created versus the new track.
#
# For example, let's say you download a song from YT and it should be 120 BPM,
# I can guarantee that it's not exactly at that BPM and as the track progresses,
# the error will accumulate and drift out of time more and more.
# In practice, it's not a big deal to cut and then "nudge" bits of the newly created
# track to match up.
#
# For an average song of say 4 minutes, you will only need to make 15 or so cuts
# and "nudges".
# A lot less time consuming than manually having to add each new "drum" sound by hand.
# Do the math, a four minute song at 120 BPM with 4/4 timing, there will be close to
# several hundred drum beats.
# Something you don't want to do by hand, and hence the reason for this script.
#
# There are of course other ways to do something similar but they all have certain disadvantages.
# One example is Audacity's "Generate Rhythm Track" but you will be limited by the sounds it adds
# and drift will still be a problem.
#
# Hope it's of some use to others as is or you may find other uses for it.
# Paulo-V
# ====================================================================================
Input="LabelTrack.txt"
Silence="silence.wav"
DrumBeat="beat.wav"
OutputFileRaw="TheOutput.raw"
OutputFile="TheOutput.wav"
TempFileRaw="Temp.raw"
TempSilence="TempSilence.wav"
ThisLine=0
PreviousLine="000.000000"
CurrentLine="000.000000"
# ======================================================================
# Begin file read loop.
# Note that Bash will work out that LabelTrack.txt has 3 columns
#
# This is the format that Audacity spits out the labels track and I haven't
# found a way to change it.
# Also make sure that there is no space between Label and Track in the text
# file name when you export it.
#
# Since we only want the middle column, we still assign 3 vars to the read loop
# i.e. Ignore, ThisLine, IgnoreThisToo.
# but only use ThisLine.
#
# We should actually only use the first column (which is identical to the second)
# but for some reason the Bash read command truncates the first number.
# Didn't want to waste time finding out, so just used the second column.
# =======================================================================
while read -r Ignore ThisLine IgnoreThisToo
do
# =======================================================================
# Send to bc to do the maths, subtract length of actual drum beat (50 mS)
# and the sed at the end is to add a leading zero else sox complains.
# =======================================================================
CurrentLine=$(echo "scale=9;($ThisLine - $PreviousLine - 0.05)" | bc -l | sed 's/^\./0./')
# ========================================================================
# The line below is just a visual sanity timings check.
# ========================================================================
echo "current ---> "$CurrentLine " this ----> "$ThisLine " previous ---> " $PreviousLine
# =========================================================================
# Create temp silence file of duration picked up by timings,
# Add that to drum beat and save in output file.
# =========================================================================
sox $Silence $TempSilence trim 0 $CurrentLine
sox $TempSilence $DrumBeat $OutputFile
# ==========================================================================
# Now, it will convert that wav to raw pcm so we can just keep appending
# without worring about headers.
# ffmpeg works better than sox for this.
# The -y at the end tells ffmpeg to overwrite any existing files
# and the > /dev/null thing surpresses all the cli output garbage.
# ==========================================================================
ffmpeg -i $OutputFile -f s16le -acodec pcm_s16le $OutputFileRaw -y > /dev/null 2>&1
# ===========================================================================
# Do the actual concatinating (appending) with cat.
# could have also used dd
# dd if="$OutputFileRaw" of="$TempFileRaw" status=none conv=notrunc oflag=append
# ===========================================================================
cat $OutputFileRaw >> $TempFileRaw
PreviousLine=$ThisLine
done < "$Input"
# ============================================================================
# End of timings file read loop so convert the raw pcm back to wav with ffmpeg
# This is now the wav we import back into Audacity or other DAW.
# ============================================================================
ffmpeg -f s16le -ar 44.1k -ac 1 -i $TempFileRaw $OutputFile -y > /dev/null 2>&1
# ============================================================================
# Remove temp files.
# The wav file to be dragged back into Audacity is called TheOutput.wav
# ============================================================================
rm $TempFileRaw
rm $OutputFileRaw
rm $TempSilence
echo "========== Conversion Complete ============="
The actual script is also attached to this post, see below.
(Remember to change extension from .txt to .sh and set required permissions).
TimingsToBeats.txt (9.1 KB)