Waveform analysis/Top and tail: Difference between revisions

m
m (omissions added)
m (→‎{{header|Wren}}: Minor tidy)
 
(8 intermediate revisions by 6 users not shown)
Line 1:
{{draft task}}
 
The task is to crop a given audio waveform file, removing any leading or trailing silence from the wave file, leaving just the audible sound.
 
Line 8 ⟶ 7:
 
Note that the output file format should be the same as the initial input format. This should not be changed by the implemented procedure.
 
=={{header|Go}}==
As Go does not have any audio support in its standard library, this invokes the SoX utility to trim any leading or trailing silence from an audio file.
 
Unfortunately, you must know the length of the silence at the end of the audio file to trim off silence reliably. To work around this, we first trim off leading silence from the file, reverse it and then trim off the leading silence from that file. We then reverse the resulting file to the output file specified by the user.
 
Setting the squelch level to 2 or 3 per cent of the maximum sample value worked reasonably well in my tests.
<syntaxhighlight lang="go">package main
 
import (
"bufio"
"fmt"
"log"
"os"
"os/exec"
"strconv"
)
 
func check(err error) {
if err != nil {
log.Fatal(err)
}
}
 
func main() {
const sec = "00:00:01"
scanner := bufio.NewScanner(os.Stdin)
name := ""
for name == "" {
fmt.Print("Enter name of audio file to be trimmed : ")
scanner.Scan()
name = scanner.Text()
check(scanner.Err())
}
 
name2 := ""
for name2 == "" {
fmt.Print("Enter name of output file : ")
scanner.Scan()
name2 = scanner.Text()
check(scanner.Err())
}
squelch := 0.0
for squelch < 1 || squelch > 10 {
fmt.Print("Enter squelch level % max (1 to 10) : ")
scanner.Scan()
input := scanner.Text()
check(scanner.Err())
squelch, _ = strconv.ParseFloat(input, 64)
}
squelchS := strconv.FormatFloat(squelch, 'f', -1, 64) + "%"
 
tmp1 := "tmp1_" + name
tmp2 := "tmp2_" + name
 
// Trim audio below squelch level from start and output to tmp1.
args := []string{name, tmp1, "silence", "1", sec, squelchS}
cmd := exec.Command("sox", args...)
err := cmd.Run()
check(err)
 
// Reverse tmp1 to tmp2.
args = []string{tmp1, tmp2, "reverse"}
cmd = exec.Command("sox", args...)
err = cmd.Run()
check(err)
 
// Trim audio below squelch level from tmp2 and output to tmp1.
args = []string{tmp2, tmp1, "silence", "1", sec, squelchS}
cmd = exec.Command("sox", args...)
err = cmd.Run()
check(err)
 
// Reverse tmp1 to the output file.
args = []string{tmp1, name2, "reverse"}
cmd = exec.Command("sox", args...)
err = cmd.Run()
check(err)
 
// Remove the temporary files.
err = os.Remove(tmp1)
check(err)
err = os.Remove(tmp2)
check(err)
}</syntaxhighlight>
 
 
=={{header|Julia}}==
Implemented as a Gtk GUI app.
<syntaxhighlight lang="julia">using FileIO, Gtk, LibSndFile, Printf
 
function dB(buf, i, channels, cutoff=0.001)
xsum = sum(buf[k, j] * buf[k, j] for j in 1:channels, k in i-1:i+1)
sigmean = xsum / (channels * 3)
return sigmean < cutoff ? -60.0 : 20 * log(10, sigmean)
end
 
function silencecropperapp()
win = GtkWindow("Sound File Silence Cropping Tool", 800, 200) |> (GtkFrame() |> (vbox = GtkBox(:v)))
infilename, outfilename, modifyinputfile, trimmable = "", "", false, true
outchoices = Vector{GtkRadioButton}(undef, 2)
outchoices[1] = GtkRadioButton("Crop the Input File In-Place", active=true)
outchoices[2] = GtkRadioButton(outchoices[1], "Copy Output to File Chosen Below")
inbutton = GtkButton("Click to Choose Input File")
 
senslabel = GtkLabel("Threshold (db)")
thresholdslider = GtkScale(false, -40.0:10.0)
adj = GtkAdjustment(thresholdslider)
push!(vbox, outchoices[1], outchoices[2], inbutton, senslabel, thresholdslider)
 
crop = Vector{GtkRadioButton}(undef, 3)
crop[1] = GtkRadioButton("Crop File at Beginning")
crop[2] = GtkRadioButton(crop[1], "Crop File at End")
crop[3] = GtkRadioButton(crop[2], "Crop Both Ends", active=true)
cropchoice() = [get_gtk_property(b, :active, Bool) for b in crop]
 
trimfilebutton = GtkButton("Trim!")
push!(vbox, crop[1], crop[2], crop[3], trimfilebutton)
 
hbox = GtkBox(:h)
textentry = GtkEntry()
set_gtk_property!(textentry, :expand, true)
set_gtk_property!(textentry, :text, "Set Output File")
pickoutfilebutton = GtkButton("Choose Existing File for Output")
push!(hbox, textentry, pickoutfilebutton)
push!(vbox, hbox)
function reinitialize()
infilename, outfilename, modifyinputfile, trimmable = "", "", true, true
set_gtk_property!(trimfilebutton, :label, "Trim!")
toggleoutputactive(win)
end
function toggleoutputactive(w)
if get_gtk_property(outchoices[2], :active, Bool)
set_gtk_property!(textentry, :editable, true)
set_gtk_property!(textentry, :text, "Set Output File")
modifyinputfile = false
elseif get_gtk_property(outchoices[1], :active, Bool)
set_gtk_property!(textentry, :editable, false)
set_gtk_property!(textentry, :text, "Set Output File")
outfilename = ""
modifyinputfile = true
end
end
function pickinput(w)
filename = open_dialog("Pick a sound or music file to be trimmed.")
if filesize(filename) > 0
infilename = filename
set_gtk_property!(inbutton, :label, infilename)
end
trimbuttonlabel(win)
end
function pickoutput(w)
if get_gtk_property(outchoices[2], :active, Bool)
outfilename = open_dialog("Pick Output File To Be Overwritten.")
set_gtk_property!(textentry, :text, outfilename)
show(textentry)
end
end
function trimbuttonlabel(w)
tstart, tend, tboth = cropchoice()
toggleoutputactive(win)
if filesize(infilename) > 0
scut, ecut, b, nframes, fs = getsilence(get_gtk_property(adj, :value, Float64))
if (tboth && scut <= 1 && ecut >= nframes) ||
(tstart && scut <= 1) || (tend && ecut >= nframes)
set_gtk_property!(trimfilebutton, :label, "Nothing to trim.")
trimmable = false
else
text = @sprintf("Trim %7.2f seconds at front and %7.2f seconds at back.",
(scut - 1) / fs, (nframes - ecut) / fs)
set_gtk_property!(trimfilebutton, :label, text)
trimmable = true
end
else
set_gtk_property!(trimfilebutton, :label, "Trim!")
end
end
function trimsilence(w)
if trimmable
if modifyinputfile
outfilename = infilename
elseif outfilename == ""
s = get_gtk_property(textentry, :text, String)
outfilename = s != "Set Output File" ? s :
open_dialog("Pick or enter a file for output")
end
if filesize(outfilename) <= 0 || ask_dialog("Really change file $infilename?")
scut, ecut, buf, n, fs = getsilence(get_gtk_property(adj, :value, Float64))
FileIO.save(outfilename, buf[scut:ecut, :])
info_dialog("File $outfilename saved: $(filesize(outfilename)) bytes.", win)
reinitialize()
end
end
end
function getsilence(threshold, granularity=0.1)
buf = load(infilename)
(buflen, channels) = size(buf)
startcut, endcut = 0, buflen
nframes = LibSndFile.nframes(buf)
fs = LibSndFile.samplerate(buf)
cchoices = cropchoice()
if cchoices[1] || cchoices[3]
pos = findfirst(i -> dB(buf, i, channels) > threshold, 2:buflen-1)
if pos == nothing
# all below threshold
return buflen, 0, buf, nframes, fs
else
startcut = Int(floor(((pos / fs) - (pos / fs) % granularity) * fs))
startcut = startcut < 1 ? 1 : startcut
end
end
if cchoices[2] || cchoices[3]
pos = findlast(i -> dB(buf, i, channels) > threshold, 2:buflen-1)
if pos != nothing
endcut = Int(ceil((granularity + (pos / fs) - (pos / fs) % granularity) * fs))
endcut = endcut > nframes ? nframes : endcut
end
end
return startcut, endcut, buf, nframes, fs
end
 
foreach(i -> signal_connect(toggleoutputactive, outchoices[i], :clicked), 1:2)
foreach(i -> signal_connect(trimbuttonlabel, crop[i], :clicked), 1:3)
signal_connect(pickoutput, pickoutfilebutton, :clicked)
setfromtext(w) = (outfilename = get_gtk_property(textentry, :text, String))
signal_connect(pickinput, inbutton, :clicked)
signal_connect(trimsilence, trimfilebutton, :clicked)
toggleoutputactive(win)
 
cond = Condition()
endit(w) = notify(cond)
signal_connect(endit, win, :destroy)
showall(win)
wait(cond)
end
 
silencecropperapp()
</syntaxhighlight>
 
=={{header|Nim}}==
{{trans|Go}}
<syntaxhighlight lang="nim">import os, osproc, strutils
 
const Sec = "00:00:01"
 
proc getString(prompt: string): string =
while true:
stdout.write prompt
stdout.flushFile()
try:
result = stdin.readLine().strip()
if result.len != 0: break
except EOFError:
quit "\nEOF encountered. Quitting.", QuitFailure
 
proc getFloatValue(prompt: string; minval, maxval: float): float =
while true:
stdout.write prompt
stdout.flushFile()
try:
result = stdin.readLine.strip().parseFloat()
if result notin minval..maxval:
echo "Invalid value"
else:
return
except ValueError:
echo "Error: invalid value."
except EOFError:
quit "\nEOF encountered. Quitting.", QuitFailure
 
let infile = getString("Enter name of audio file to be trimmed: ")
let outfile = getString("Enter name of output file: ")
let squelch = getFloatValue("Enter squelch level % max (1 to 10): ", 1, 10)
let squelchS = squelch.formatFloat(ffDecimal, precision = -1) & '%'
 
let tmp1 = "tmp1_" & infile
let tmp2 = "tmp2_" & infile
 
# Trim audio below squelch level from start and output to tmp1.
var args = @[infile, tmp1, "silence", "1", Sec, squelchS]
discard execProcess("sox", args = args, options = {poStdErrToStdOut, poUsePath})
 
# Reverse tmp1 to tmp2.
args = @[tmp1, tmp2, "reverse"]
discard execProcess("sox", args = args, options = {poStdErrToStdOut, poUsePath})
 
# Trim audio below squelch level from tmp2 and output to tmp1.
args = @[tmp2, tmp1, "silence", "1", Sec, squelchS]
discard execProcess("sox", args = args, options = {poStdErrToStdOut, poUsePath})
 
# Reverse tmp1 to the output file.
args = @[tmp1, outfile, "reverse"]
discard execProcess("sox", args = args, options = {poStdErrToStdOut, poUsePath})
 
# Remove the temporary files.
removeFile(tmp1)
removeFile(tmp2)</syntaxhighlight>
 
=={{header|Phix}}==
The first part is a copy of [[Musical_scale#version_2]] but with first and last 2s written out as silence.<br>
I referred to http://soundfile.sapp.org/doc/WaveFormat/ when writing this.<br>
You may want to check for average volume over some period, rather than just all-0.<br>
This is clearly just a starting point and not a practical/useful/finished product!
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (file i/o)</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">sample_rate</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">44100</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">duration</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">dataLength</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sample_rate</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">duration</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">hdrSize</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">44</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">fileLen</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dataLength</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">hdrSize</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">freqs</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">261.6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">293.6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">329.6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">349.2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">392.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">440.0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">493.9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">523.3</span> <span style="color: #0000FF;">},</span>
<span style="color: #000000;">wavhdr</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"RIFF"</span><span style="color: #0000FF;">&</span>
<span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fileLen</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)&</span>
<span style="color: #008000;">"WAVE"</span><span style="color: #0000FF;">&</span>
<span style="color: #008000;">"fmt "</span><span style="color: #0000FF;">&</span>
<span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)&</span> <span style="color: #000080;font-style:italic;">-- length of format data (= 16)</span>
<span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)&</span> <span style="color: #000080;font-style:italic;">-- type of format (= 1 (PCM))</span>
<span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)&</span> <span style="color: #000080;font-style:italic;">-- number of channels (= 1)</span>
<span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sample_rate</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)&</span> <span style="color: #000080;font-style:italic;">-- sample rate</span>
<span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sample_rate</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)&</span> <span style="color: #000080;font-style:italic;">-- sample rate * bps(8) * channels(1) / 8 (= sample rate)</span>
<span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)&</span> <span style="color: #000080;font-style:italic;">-- bps(8) * channels(1) / 8 (= 1)</span>
<span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)&</span> <span style="color: #000080;font-style:italic;">-- bits per sample (bps) (= 8)</span>
<span style="color: #008000;">"data"</span><span style="color: #0000FF;">&</span>
<span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dataLength</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- size of data section</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">wavhdr</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">hdrSize</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- sanity check</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"notes.wav"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"wb"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">wavhdr</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">duration</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">omega</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span> <span style="color: #0000FF;">*</span> <span style="color: #004600;">PI</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">freqs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">dataLength</span><span style="color: #0000FF;">/</span><span style="color: #000000;">duration</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">32</span> <span style="color: #0000FF;">*</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">omega</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">sample_rate</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- integer byte = and_bits(y,#FF) -- (makes for no cropping)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">byte</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">2</span> <span style="color: #008080;">or</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">7</span><span style="color: #0000FF;">?</span><span style="color: #000000;">0</span><span style="color: #0000FF;">:</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#FF</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">byte</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- &lt;/copy of Musical_scale&gt;</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">raw</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"notes.wav"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">"RIFF"</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">rawlen</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">..</span><span style="color: #000000;">8</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">rawlen</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">fileLen</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">9</span><span style="color: #0000FF;">..</span><span style="color: #000000;">12</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">"WAVE"</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">13</span><span style="color: #0000FF;">..</span><span style="color: #000000;">16</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">"fmt "</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">17</span><span style="color: #0000FF;">..</span><span style="color: #000000;">20</span><span style="color: #0000FF;">])!=</span><span style="color: #000000;">16</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- 2 bytes per sample</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">21</span><span style="color: #0000FF;">..</span><span style="color: #000000;">22</span><span style="color: #0000FF;">])!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- must be PCM</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">channels</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">23</span><span style="color: #0000FF;">..</span><span style="color: #000000;">24</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">channels</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">channels</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- mono or stereo (else??)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bps</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">35</span><span style="color: #0000FF;">..</span><span style="color: #000000;">36</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bps</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">8</span> <span style="color: #008080;">and</span> <span style="color: #000000;">bps</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">16</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- 8 or 16 bits per sample?</span>
<span style="color: #000000;">bps</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">bps</span><span style="color: #0000FF;">/</span><span style="color: #000000;">8</span><span style="color: #0000FF;">*</span><span style="color: #000000;">channels</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">-- ===&gt; bytes per sample (pair(s)(s))</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">37</span><span style="color: #0000FF;">..</span><span style="color: #000000;">40</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">"data"</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">rawdata</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">41</span><span style="color: #0000FF;">..</span><span style="color: #000000;">44</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">rawdata</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">dataLength</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bs</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">be</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">crop</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">bs</span><span style="color: #0000FF;">=</span><span style="color: #000000;">45</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">by</span> <span style="color: #000000;">bps</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">-- some volume threshold...</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">bs</span><span style="color: #0000FF;">..</span><span style="color: #000000;">bs</span><span style="color: #0000FF;">+</span><span style="color: #000000;">bps</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (assumes unsigned)</span>
<span style="color: #000000;">crop</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">bps</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">be</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">bs</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">bps</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">be</span><span style="color: #0000FF;">-</span><span style="color: #000000;">bps</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">be</span><span style="color: #0000FF;">])></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">crop</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">bps</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">crop</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"nothing to crop\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"cropping %d bytes\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">crop</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">rawlen</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">crop</span>
<span style="color: #000000;">rawdata</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">crop</span>
<span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">..</span><span style="color: #000000;">8</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rawlen</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">41</span><span style="color: #0000FF;">..</span><span style="color: #000000;">44</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rawdata</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">raw</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">be</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">raw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">46</span><span style="color: #0000FF;">..</span><span style="color: #000000;">bs</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"notes.wav"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"wb"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">raw</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000080;font-style:italic;">-- without cropping 8s, with 4s</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">WINDOWS</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">system</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"notes.wav"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">LINUX</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">system</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"aplay notes.wav"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
 
=={{header|Wren}}==
{{trans|Go}}
The ability to call external processes such as ''SoX'' is expected to be added to Wren-cli in the next release. In the meantime, we embed the following Wren script in a C host to complete this task.
<syntaxhighlight lang="wren">/* Waveform_analysis_Top_and_tail.wren */
 
class C {
foreign static getInput(maxSize)
 
foreign static sox(args)
 
foreign static removeFile(name)
}
 
var sec = "00:00:01"
 
var name = ""
while (name == "") {
System.write("Enter name of audio file to be trimmed : ")
name = C.getInput(80)
}
 
var name2 = ""
while (name2 == "") {
System.write("Enter name of output file : ")
name2 = C.getInput(80)
}
 
var squelch = 0
while (!squelch || squelch < 1 || squelch > 10) {
System.write("Enter squelch level \% max (1 to 10) : ")
squelch = Num.fromString(C.getInput(5))
}
var squelchS = squelch.toString + "\%"
 
var tmp1 = "tmp1_" + name
var tmp2 = "tmp2_" + name
 
// Trim audio below squelch level from start and output to tmp1.
var args = [name, tmp1, "silence", "1", sec, squelchS]
C.sox(args.join(" "))
 
// Reverse tmp1 to tmp2.
args = [tmp1, tmp2, "reverse"]
C.sox(args.join(" "))
 
// Trim audio below squelch level from tmp2 and output to tmp1.
args = [tmp2, tmp1, "silence", "1", sec, squelchS]
C.sox(args.join(" "))
 
// Reverse tmp1 to the output file.
args = [tmp1, name2, "reverse"]
C.sox(args.join(" "))
 
// Remove the temporary files.
C.removeFile(tmp1)
C.removeFile(tmp2)</syntaxhighlight>
<br>
We now embed this in the following C program, compile and run it.
<syntaxhighlight lang="c">/* gcc Waveform_analysis_Top_and_tail.c -o Waveform_analysis_Top_and_tail -lwren -lm */
 
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include "wren.h"
 
void C_getInput(WrenVM* vm) {
int maxSize = (int)wrenGetSlotDouble(vm, 1) + 2;
char input[maxSize];
fgets(input, maxSize, stdin);
__fpurge(stdin);
input[strcspn(input, "\n")] = 0;
wrenSetSlotString(vm, 0, (const char*)input);
}
 
void C_sox(WrenVM* vm) {
const char *args = wrenGetSlotString(vm, 1);
char command[strlen(args) + 4];
strcpy(command, "sox ");
strcat(command, args);
system(command);
}
 
void C_removeFile(WrenVM* vm) {
const char *name = wrenGetSlotString(vm, 1);
if (remove(name) != 0) perror("Error deleting file.");
}
 
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "C") == 0) {
if (isStatic && strcmp(signature, "getInput(_)") == 0) return C_getInput;
if (isStatic && strcmp(signature, "sox(_)") == 0) return C_sox;
if (isStatic && strcmp(signature, "removeFile(_)") == 0) return C_removeFile;
}
}
return NULL;
}
 
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
 
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
 
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
 
int main(int argc, char **argv) {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignMethodFn = &bindForeignMethod;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "Waveform_analysis_Top_and_tail.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}</syntaxhighlight>
 
{{omit from|AWK}}
Line 15 ⟶ 563:
{{omit from|Lotus 123 Macro Scripting}}
{{omit from|Openscad}}
{{omit from|Scala}}
{{omit from|TPP}}
{{omit from|UNIX Shell}}
9,482

edits