Files
hpr_website/www/eps/hpr2135/hpr2135_full_shownotes.html

421 lines
32 KiB
HTML
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<meta name="author" content="Dave Morriss">
<title>Audio speedup script (HPR Show 2135)</title>
<style type="text/css">code{white-space: pre;}</style>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
<link rel="stylesheet" href="http://hackerpublicradio.org/css/hpr.css">
</head>
<body id="home">
<div id="container" class="shadow">
<header>
<h1 class="title">Audio speedup script (HPR Show 2135)</h1>
<h2 class="author">Dave Morriss</h2>
<hr/>
</header>
<main id="maincontent">
<article>
<header>
<h1>Table of Contents</h1>
<nav id="TOC">
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#overview-of-the-script">Overview of the script</a></li>
<li><a href="#an-analysis-of-the-script">An analysis of the script</a></li>
<li><a href="#conclusion">Conclusion</a></li>
<li><a href="#links">Links</a></li>
</ul>
</nav>
</header>
<h2 id="introduction">Introduction</h2>
<p>Back in 2015 Ken Fallon did a show (episode <a href="http://hackerpublicradio.org/eps/hpr1766" title="The Sox of Silence">1766</a>) on how to use <code>sox</code> to truncate silence and speed up audio.</p>
<p>Inspired by this I wrote a Bash script to aid my use of the technique, which I thought Id share with you.</p>
<h2 id="overview-of-the-script">Overview of the script</h2>
<p>I called the script <code>speedup</code> although it performs the dual functions of speeding up and truncating silence.</p>
<p>The script is invoked thus:</p>
<pre><code>$ speedup [options] filename</code></pre>
<p>(If you didnt place it somewhere in your <code>PATH</code> then youd need to include the path to the script such as <code>./speedup</code> if its in the current directory.)</p>
<p>The <code>filename</code> argument should be the full path of the audio file. Unless deleted with the <strong>-c</strong> option (see below) the script will rename the original file and create the modified file with the same name as the original. When finished processing the original file unmodified will have the name <em>NAME</em>_.<em>EXT</em> with an underscore added after the original name as shown.</p>
<p>The options are used to select the various features. They are:</p>
<dl>
<dt><strong>-s</strong></dt>
<dd><pre><code>This option causes the audio to be sped up. It can be
repeated and the speed up is increased for every -s given.</code></pre>
</dd>
<dt><strong>-t</strong></dt>
<dd><pre><code>This option causes the audio to have silences truncated.
It can be repeated to increase the sensitivity of the
truncation.</code></pre>
</dd>
<dt><strong>-m</strong></dt>
<dd><pre><code>Mix-down multiple (stereo) tracks to mono.</code></pre>
</dd>
<dt><strong>-c</strong></dt>
<dd><pre><code>Delete the original file leaving the modified file behind with the
same name as the original.</code></pre>
</dd>
<dt><strong>-d</strong></dt>
<dd><pre><code>Engage dry-run mode where the planned actions are reported but nothing
is actually done.</code></pre>
</dd>
<dt><strong>-D</strong></dt>
<dd><pre><code>Run in DEBUG mode where more information is reported about what is
going on.</code></pre>
</dd>
<dt><strong>-h</strong></dt>
<dd><pre><code>Print the help information.</code></pre>
</dd>
</dl>
<p>As mentioned above, the <em>speedup</em> and <em>truncate</em> functions can be “turned up” by repeating the options. The script counts the number of times a <strong>-s</strong> or <strong>-t</strong> option occurs and uses that number to index a list of speeds or truncation parameters. We will look at how this is done and what the possibilities are later.</p>
<p>The options conform to the usual Unix standard and can be concatenated, so the following invocations are the same and perform three levels of speeding up and one of truncation:</p>
<pre><code>speedup -s -s -s -t ~/Bashpodder/Podcasts/2016-08-25/tllts_670-08-17-16.ogg
speedup -ssst ~/Bashpodder/Podcasts/2016-08-25/tllts_670-08-17-16.ogg</code></pre>
<h2 id="an-analysis-of-the-script">An analysis of the script</h2>
<p>The script is available for download <a href="hpr2135_speedup.bash" title="The speedup script">here</a>. It is also available on GitLab in a <a href="https://gitlab.com/davmo/hprmisc" title="GitLab repository of HPR scripts">repository</a> I use for all of the scripts I talk about on HPR.</p>
<p>We will examine the script in chunks<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="co">#!/usr/bin/env bash</span>
<span class="co">#===============================================================================</span>
<span class="co">#</span>
<span class="co"># FILE: speedup</span>
<span class="co">#</span>
<span class="co"># USAGE: ./speedup [-s ...] [-t ...] [-m] [-c] [-d] [-D] [-h] filename</span>
<span class="co">#</span>
<span class="co"># DESCRIPTION: A script to perform a speedup and silence removal on a given</span>
<span class="co"># audio file</span>
<span class="co">#</span>
<span class="co"># OPTIONS: ---</span>
<span class="co"># REQUIREMENTS: ---</span>
<span class="co"># BUGS: ---</span>
<span class="co"># NOTES: ---</span>
<span class="co"># AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com</span>
<span class="co"># VERSION: 0.0.4</span>
<span class="co"># CREATED: 2015-05-01 21:51:32</span>
<span class="co"># REVISION: 2016-04-22 11:35:08</span>
<span class="co">#</span>
<span class="co">#===============================================================================</span>
<span class="kw">set</span> <span class="ex">-o</span> nounset # Treat unset variables as an error
<span class="va">SCRIPT=${0##</span>*/<span class="va">}</span>
<span class="va">VERSION=</span><span class="st">&quot;0.0.4&quot;</span>
<span class="co">#=== FUNCTION ================================================================</span>
<span class="co"># NAME: _usage</span>
<span class="co"># DESCRIPTION: Report usage</span>
<span class="co"># PARAMETERS: 1 - the exit value (so it can be used to return an error</span>
<span class="co"># value)</span>
<span class="co"># RETURNS: Nothing</span>
<span class="co">#===============================================================================</span>
<span class="fu">_usage ()</span> <span class="kw">{</span>
<span class="bu">local</span> <span class="va">res=</span><span class="st">&quot;</span><span class="va">${1:-</span>0<span class="va">}</span><span class="st">&quot;</span>
<span class="fu">cat</span> <span class="op">&lt;&lt;-endusage</span>
Usage: <span class="va">${SCRIPT}</span> [-s ...] [-t ...] [-m] [-c] [-d] [-D] [-h] filename
Speeds up and truncates silence in an audio file
Options:
-s This option if present causes the audio to be sped up.
The option can be repeated and the speed up is increased for
every -s given
-t This option if present causes the audio to to have silences
truncated. The option can be repeated to increase the
sensitivity of the truncation
-m Mix-down multiple (stereo) tracks to mono
-c Delete the original file leaving the modified file behind with
the same name as the original
-d Engage dry-run mode where the planned actions are reported
but nothing is actually done
-D Run in DEBUG mode where more information is reported
about what is going on
-h Print this help
Arguments:
filename The full path of the audio file containing the podcast episode.
Note:
Unless deleted with the -c option the script will rename the original file
and create the modified file with the same name as the original. The
original file will have the name &#39;NAME_.EXT&#39; with an underscore added after
the original name.
Version: <span class="va">$VERSION</span>
endusage
exit &quot;<span class="va">$res</span>&quot;
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</code></pre></div>
<p>The first part consists of a comment, the declaration of a <code>SCRIPT</code> variable (taken from the <code>$0</code> argument), and the version number.</p>
<p>This is followed by the definition of function <code>_usage</code>. This simply lists a “here document” using the <code>cat &lt;&lt;-endusage</code> statement near the top, and then exits using the argument as an exit value. The function is called to show how to use the script, so its not appropriate to run the script afterwards.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">
<span class="co">#</span>
<span class="co"># Default settings</span>
<span class="co">#</span>
<span class="va">CLEANUP=</span>0
<span class="va">DEBUG=</span>0
<span class="va">DRYRUN=</span>0
<span class="va">SPEEDUP=</span>0
<span class="va">TRUNCATE=</span>0
<span class="va">MIXDOWN=</span>0
<span class="co">#</span>
<span class="co"># Process options</span>
<span class="co">#</span>
<span class="kw">while</span> <span class="bu">getopts</span> :cDdhmst opt
<span class="kw">do</span>
<span class="kw">case</span> <span class="st">&quot;</span><span class="va">${opt}</span><span class="st">&quot;</span><span class="kw"> in</span>
c<span class="kw">)</span> <span class="va">CLEANUP=</span>1<span class="kw">;;</span>
D<span class="kw">)</span> <span class="va">DEBUG=</span>1<span class="kw">;;</span>
d<span class="kw">)</span> <span class="va">DRYRUN=</span>1<span class="kw">;;</span>
s<span class="kw">)</span> <span class="kw">((</span>SPEEDUP++<span class="kw">));;</span>
t<span class="kw">)</span> <span class="kw">((</span>TRUNCATE++<span class="kw">));;</span>
m<span class="kw">)</span> <span class="va">MIXDOWN=</span>1<span class="kw">;;</span>
h<span class="kw">)</span> <span class="ex">_usage</span> 1<span class="kw">;;</span>
<span class="ex">*</span>) <span class="ex">_usage</span> 1<span class="kw">;;</span>
<span class="kw">esac</span>
<span class="kw">done</span>
<span class="bu">shift</span> <span class="va">$((</span>OPTIND - 1<span class="va">))</span></code></pre></div>
<p>In this section a collection of variables associated with the options is initialised. The <code>while</code> loop then processes the options. Note how the <strong>s</strong> and <strong>t</strong> options increment the variables <code>SPEEDUP</code> and <code>TRUNCATE</code>. Otherwise, presence of an option turns on (sets to 1) the variables defined earlier.</p>
<p>The <code>shift</code> statement at the end of this chunk is needed to remove all of the (now processed) options from the argument list, leaving the filename as argument 1 (<code>$1</code>).</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">
<span class="co">#</span>
<span class="co"># Check there is one argument</span>
<span class="co">#</span>
<span class="kw">if [[</span> <span class="va">$#</span> <span class="ot">-ne</span> 1<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="bu">echo</span> <span class="st">&quot;Error: filename missing&quot;</span>
<span class="ex">_usage</span> 1
<span class="kw">fi</span>
<span class="co">#</span>
<span class="co"># Does the file given as an argument exist?</span>
<span class="co">#</span>
<span class="kw">if [[</span> <span class="ot">!</span> <span class="ot">-e</span> <span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span><span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="bu">echo</span> <span class="st">&quot;File not found: </span><span class="va">$1</span><span class="st">&quot;</span>
<span class="bu">exit</span> 1
<span class="kw">fi</span></code></pre></div>
<p>Now the script checks for the <code>filename</code> argument, aborting via function <code>_usage</code> if not found. It then checks to see if the file actually exists, and aborts with an error message if it doesnt.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">
<span class="kw">if [[</span> <span class="va">$DRYRUN</span> <span class="ot">-eq</span> 1<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="bu">echo</span> <span class="st">&quot;Dry run: no changes will be made&quot;</span>
<span class="kw">fi</span></code></pre></div>
<p>This chunk simply detects the use of the <strong>-d</strong> (dry run) option and reports that it is on.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">
<span class="co">#</span>
<span class="co"># Work out the speed-up we want (if any) and generate the argument to sox</span>
<span class="co">#</span>
<span class="va">SPEEDS=(</span> 1.05 1.1 1.2 1.3 1.4 1.5 1.6 1.7 <span class="va">)</span>
<span class="kw">if [[</span> <span class="va">$SPEEDUP</span> <span class="ot">-eq</span> 0<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="va">TEMPO=</span>
<span class="kw">else</span>
<span class="kw">if [[</span> <span class="va">$SPEEDUP</span> <span class="ot">-gt</span> <span class="va">${#SPEEDS[@]}</span><span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="va">SPEEDUP=${#SPEEDS[@]}</span>
<span class="kw">fi</span>
<span class="kw">((</span>SPEEDUP--<span class="kw">))</span>
<span class="va">speed=${SPEEDS[$SPEEDUP]}</span>
<span class="va">TEMPO=</span><span class="st">&quot;tempo </span><span class="va">${speed}</span><span class="st">&quot;</span>
<span class="kw">fi</span></code></pre></div>
<p>This chunk detects the speedup level and creates a <code>TEMPO</code> variable with the result. If there was no <strong>-s</strong> option then the variable is empty. If a value was given then it is checked to see that it doesnt exceed the number of speeds defined. These speeds are defined in the variable <code>SPEEDS</code> which is an array. You can see the script caters for speeds of 1.05, 1.1, 1.2 and so forth up to 1.7. This list was created for my needs, you could redefine it according to your needs.</p>
<p>The speed count in variable <code>SPEEDUP</code> is decremented to index the array which starts at index zero, then the value is stored in variable <code>speed</code> and used to define variable <code>TEMPO</code> ready for use with <code>sox</code>.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">
<span class="co">#</span>
<span class="co"># Work out the silence truncation parameters (if any). The first set trims</span>
<span class="co"># silence but ignores silences of 0.5 seconds in the middle (like pauses for</span>
<span class="co"># breaths). The second set removes everything but can make a rather rushed</span>
<span class="co"># result. See http://digitalcardboard.com/blog/2009/08/25/the-sox-of-silence/</span>
<span class="co"># for some advice.</span>
<span class="co">#</span>
<span class="va">TRUNCS=(</span> <span class="st">&quot;1 0.1 1% -1 0.5 1%&quot;</span> <span class="st">&quot;1 0.1 1% -1 0.1 1%&quot;</span> <span class="va">)</span>
<span class="kw">if [[</span> <span class="va">$TRUNCATE</span> <span class="ot">-eq</span> 0<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="va">SILENCE=</span>
<span class="kw">else</span>
<span class="kw">if [[</span> <span class="va">$TRUNCATE</span> <span class="ot">-gt</span> <span class="va">${#TRUNCS[@]}</span><span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="va">TRUNCATE=${#TRUNCS[@]}</span>
<span class="kw">fi</span>
<span class="kw">((</span>TRUNCATE--<span class="kw">))</span>
<span class="va">silence=${TRUNCS[$TRUNCATE]}</span>
<span class="va">SILENCE=</span><span class="st">&quot;silence </span><span class="va">${silence}</span><span class="st">&quot;</span>
<span class="kw">fi</span></code></pre></div>
<p>This chunk does more or less the same as the preceding one for silence truncation. The main difference is that the array <code>TRUNCS</code> contains only two components and each one is a string of numbers. The setting of sound truncation parameters for <code>sox</code> is quite complicated. See the reference in the comments and <a href="http://hackerpublicradio.org/eps/hpr1766" title="The Sox of Silence">show 1766</a> if you want to understand it. The end result is that the variable <code>SILENCE</code> contains the necessary parameter for <code>sox</code>.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">
<span class="kw">if [[</span> <span class="va">$MIXDOWN</span> <span class="ot">==</span> 0<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="va">REMIX=</span>
<span class="kw">else</span>
<span class="va">REMIX=</span><span class="st">&quot;remix -&quot;</span>
<span class="kw">fi</span>
<span class="co">#</span>
<span class="co"># Report some internals in debug mode</span>
<span class="co">#</span>
<span class="kw">if [[</span> <span class="va">$DEBUG</span> <span class="ot">-eq</span> 1<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="bu">echo</span> <span class="st">&quot;SPEEDUP = </span><span class="va">$SPEEDUP</span><span class="st">&quot;</span>
<span class="bu">echo</span> <span class="st">&quot;TRUNCATE = </span><span class="va">$TRUNCATE</span><span class="st">&quot;</span>
<span class="bu">echo</span> <span class="st">&quot;MIXDOWN = </span><span class="va">$MIXDOWN</span><span class="st">&quot;</span>
<span class="bu">echo</span> <span class="st">&quot;speed = </span><span class="va">${speed:-</span>0<span class="va">}</span><span class="st">&quot;</span>
<span class="bu">echo</span> <span class="st">&quot;silence = </span><span class="va">${silence:-}</span><span class="st">&quot;</span>
<span class="bu">echo</span> <span class="st">&quot;TEMPO = </span><span class="va">$TEMPO</span><span class="st">&quot;</span>
<span class="bu">echo</span> <span class="st">&quot;SILENCE = </span><span class="va">$SILENCE</span><span class="st">&quot;</span>
<span class="bu">echo</span> <span class="st">&quot;REMIX = </span><span class="va">$REMIX</span><span class="st">&quot;</span>
<span class="kw">fi</span>
<span class="co">#</span>
<span class="co"># Is there anything to do?</span>
<span class="co">#</span>
<span class="kw">if [[</span> <span class="ot">-z</span> <span class="va">$TEMPO</span> &amp;&amp; <span class="ot">-z</span> <span class="va">$SILENCE</span><span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="bu">echo</span> <span class="st">&quot;Nothing to do; exiting&quot;</span>
<span class="bu">exit</span> 1
<span class="kw">fi</span></code></pre></div>
<p>Next, the <strong>-m</strong> option is checked and the variable <code>REMIX</code> defined to contain the <code>sox</code> parameter which will result in the stereo audio being remixed to mono.</p>
<p>Then, if the <strong>-D</strong> (debug) option was provided the various settings are reported. This mainly of use to someone debugging or developing this script.</p>
<p>Lastly in this chunk the script checks to see if there is any work to do. If neither <code>TEMPO</code> nor <code>SILENCE</code> is set to anything then there is no need to continue, and it exits.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">
<span class="co">#</span>
<span class="co"># Divide up the path to the file</span>
<span class="co">#</span>
<span class="va">orig=</span><span class="st">&quot;</span><span class="va">$(</span><span class="ex">realpath</span> <span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span><span class="va">)</span><span class="st">&quot;</span>
<span class="va">odir=</span><span class="st">&quot;</span><span class="va">${orig%</span>/*<span class="va">}</span><span class="st">&quot;</span>
<span class="va">oname=</span><span class="st">&quot;</span><span class="va">${orig##</span>*/<span class="va">}</span><span class="st">&quot;</span>
<span class="va">oext=</span><span class="st">&quot;</span><span class="va">${oname##</span>*.<span class="va">}</span><span class="st">&quot;</span>
<span class="co">#</span>
<span class="co"># The name of the original file will be changed to this</span>
<span class="co">#</span>
<span class="va">new=</span><span class="st">&quot;</span><span class="va">${odir}</span><span class="st">/</span><span class="va">${oname%</span>.<span class="va">$oext}</span><span class="st">_.</span><span class="va">${oext}</span><span class="st">&quot;</span>
<span class="co">#</span>
<span class="co"># Report the name of the input file</span>
<span class="co">#</span>
<span class="bu">echo</span> <span class="st">&quot;Processing </span><span class="va">$orig</span><span class="st">&quot;</span>
<span class="co">#</span>
<span class="co"># If the new name exists we already processed it</span>
<span class="co">#</span>
<span class="kw">if [[</span> <span class="ot">-e</span> <span class="va">$new</span><span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="bu">echo</span> <span class="st">&quot;Oops! Looks like this file has already been sped up&quot;</span>
<span class="bu">exit</span> 1
<span class="kw">fi</span>
<span class="co">#</span>
<span class="co"># Rename the original file</span>
<span class="co">#</span>
<span class="kw">if [[</span> <span class="va">$DRYRUN</span> <span class="ot">-eq</span> 1<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="bu">printf</span> <span class="st">&quot;Dry run: rename %s to %s\n&quot;</span> <span class="st">&quot;</span><span class="va">$orig</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$new</span><span class="st">&quot;</span>
<span class="kw">else</span>
<span class="fu">mv</span> <span class="st">&quot;</span><span class="va">$orig</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">$new</span><span class="st">&quot;</span>
<span class="kw">fi</span></code></pre></div>
<p>This chunk works on the file, making a new name for it so the converted file can have the original name.</p>
<p>Firstly the script save the full pathname into variable <code>orig</code> (using <code>realpath</code> to sort out any links or relative directories). Then it parses the filename into the path, the filename and the extension. It then reassembles it adding an underscore after the filename in the variable <code>new</code>.</p>
<p>The script checks that the new file doesnt exist, because if it does theres a good chance that this audio file has been processed already, so it gives up.</p>
<p>Finally in this chunk the script renames the original file to the new name (or reports what it would do if we are in “dry run” mode).</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">
<span class="co">#</span>
<span class="co"># Speed up and remove long silences as requested</span>
<span class="co"># -S requests a progress display</span>
<span class="co"># -v2 adjusts the volume of the file that follows it on the command line by</span>
<span class="co"># a factor of 2</span>
<span class="co"># -V9 requests a very high (debug) level of verbosity (default -V2)</span>
<span class="co"># remix - mixes all stereo to mono</span>
<span class="co">#</span>
<span class="kw">if [[</span> <span class="va">$DRYRUN</span> <span class="ot">-eq</span> 1<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="bu">printf</span> <span class="st">&quot;Dry run: %s\n&quot;</span> \
<span class="st">&quot;sox -S -v2 </span><span class="dt">\&quot;</span><span class="va">${new}</span><span class="dt">\&quot;</span><span class="st"> </span><span class="dt">\&quot;</span><span class="va">${orig}</span><span class="dt">\&quot;</span><span class="st"> </span><span class="va">${TEMPO}</span><span class="st"> </span><span class="va">${REMIX}</span><span class="st"> </span><span class="va">${SILENCE}</span><span class="st">&quot;</span>
<span class="kw">else</span>
<span class="co"># [We want TEMP, REMIX and SILENCE to be word-split etc]</span>
<span class="co"># shellcheck disable=SC2086</span>
<span class="fu">sox</span> -S -v2 <span class="st">&quot;</span><span class="va">${new}</span><span class="st">&quot;</span> <span class="st">&quot;</span><span class="va">${orig}</span><span class="st">&quot;</span> <span class="va">${TEMPO}</span> <span class="va">${REMIX}</span> <span class="va">${SILENCE}</span>
<span class="kw">fi</span></code></pre></div>
<p>This is the meat of the script. The <code>sox</code> program is given the various parameters which have been created. If “dry run” mode is on then the script just prints what it would do, but otherwise it processes the renamed file into the original filename with the chosen parameters.</p>
<p>As an aside, I use a Vim plugin called “<em>Syntastic</em>” which applies a syntax checker to various source files as they are saved during an edit, reporting any errors the checker finds. The checker for Bash is called “<em>shellcheck</em>” and some of its checks can be turned off with comments like:</p>
<pre><code># shellcheck disable=SC2086</code></pre>
<p>This is necessary here because <em>shellcheck</em> objects to the fact that variables like “<code>${TEMPO}</code>” are not quoted. We do not want to quote them here otherwise <code>sox</code> will not get the necessary arguments like <code>tempo 1.5</code>. However, we <strong>do</strong> want to quote the filenames in case they contain spaces or other dangerous characters.</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash">
<span class="co">#</span>
<span class="co"># Delete the original file if asked. Note that the script can&#39;t detect that</span>
<span class="co"># the audio has been sped up if this file is missing.</span>
<span class="co">#</span>
<span class="kw">if [[</span> <span class="va">$CLEANUP</span> <span class="ot">-eq</span> 1<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="kw">if [[</span> <span class="va">$DRYRUN</span> <span class="ot">-eq</span> 1<span class="kw"> ]]</span>; <span class="kw">then</span>
<span class="bu">printf</span> <span class="st">&quot;Dry run: delete %s\n&quot;</span> <span class="st">&quot;</span><span class="va">$new</span><span class="st">&quot;</span>
<span class="kw">else</span>
<span class="fu">rm</span> -f <span class="st">&quot;</span><span class="va">$new</span><span class="st">&quot;</span>
<span class="kw">fi</span>
<span class="kw">fi</span>
<span class="bu">exit</span>
<span class="co"># vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21</span></code></pre></div>
<p>Finally the script checks whether the <strong>-c</strong> option has requested the original (renamed) file be deleted. If so, the deletion request is reported in “dry run” mode or is actioned otherwise.</p>
<p>The comment on the last line is a so-called Vim “<em>modeline</em>” which contains settings for the Vim editor.</p>
<h2 id="conclusion">Conclusion</h2>
<p>I use this as part of my podcast download workflow. In particular I process “The Linux Link Tech Show” thus:</p>
<pre><code>./db_list_episodes -ab &quot;Linux Link&quot; | xargs -i ./speedup -ssst {}</code></pre>
<p>Here <code>db_list_episodes</code> is a script which lists the paths to all of the episodes of a given podcast known to the database where I hold podcast data. The list is passed to the command <code>xargs</code> which runs <code>speedup</code> on each file as shown.</p>
<p>I have used this script regularly since I wrote it in May 2015. It does all that I want it to do at the moment, but in the next version I think I would change the logic which causes nothing to be done unless there are speed and silence truncation changes to be made. For example, since a number of podcasts I download from the BBC have surprisingly low sound compared to most others Id quite like to amplify them.</p>
<p>I hope you find this script useful. Please contact me with any comments, corrections or improvements.</p>
<h2 id="links">Links</h2>
<ul>
<li>HPR show 1766 “<em>The Sox of Silence</em>”: <a href="http://hackerpublicradio.org/eps/hpr1766" class="uri">http://hackerpublicradio.org/eps/hpr1766</a></li>
<li>Original article on doing clever things with <strong>sox</strong>: <a href="http://digitalcardboard.com/blog/2009/08/25/the-sox-of-silence/" class="uri">http://digitalcardboard.com/blog/2009/08/25/the-sox-of-silence/</a></li>
<li>The <code>speedup</code> script for download: <a href="hpr2135_speedup.bash" class="uri">hpr2135_speedup.bash</a></li>
<li>The repository containing the <code>speedup</code> script on GitLab: <a href="https://gitlab.com/davmo/hprmisc" class="uri">https://gitlab.com/davmo/hprmisc</a></li>
</ul>
<!--
vim: syntax=markdown:ts=8:sw=4:ai:et:tw=78:fo=tcqn:fdm=marker
-->
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p>Normally I number the lines of scripts such as this in the notes. When trying to do so this time the tool I use to generate HTML notes (Pandoc) did not seem to like the fact that I chopped the script into chunks and misbehaved. Since the script is quite long I didnt want to leave my annotations to the end, so went with the un-numbered chunks you see here.<a href="#fnref1"></a></p></li>
</ol>
</section>
</article>
</main>
</div>
</body>
</html>