Difference between revisions of "SoX (Sound eXchange)"

From HalfgeekKB
Jump to navigation Jump to search
Line 68: Line 68:
  
 
  sox src.wav dst.wav lowpass 3700
 
  sox src.wav dst.wav lowpass 3700
 +
 +
=My scripts=
 +
 +
==Generating silence==
 +
 +
This script is intended for [[Cygwin]], because I'm using the Windows version of SoX.  Changing it for [[Unix]] is trivial, but if you're on Unix anyway you should be using dd and /dev/zero in a shell script instead.
 +
 +
<nowiki>
 +
#! /usr/bin/perl
 +
 +
use warnings;
 +
use strict;
 +
use Carp;
 +
 +
if(@ARGV != 2) {
 +
    die "usage: $0 seconds outfile\n";
 +
}
 +
 +
my $samples = int($ARGV[0] * 11025) * 4;
 +
my $file = $ARGV[1];
 +
 +
my $nulls = pack('C*', ( (0) x 1024 ) );
 +
 +
my $temp = "/tmp/s-$$-temp1.raw";
 +
my $wtemp = `cygpath -w "$temp"`;
 +
my $wfile = `cygpath -w "$file"`;
 +
chomp $wtemp;
 +
chomp $wfile;
 +
 +
my $out;
 +
open($out, ">$temp")
 +
    or die "Could not open temp file $temp for write\n";
 +
binmode $out;
 +
while($samples > length($nulls))
 +
{
 +
    print $out "$nulls";
 +
    $samples -= length($nulls);
 +
}
 +
$nulls = substr($nulls,0,$samples);
 +
print $out "$nulls";
 +
close $out;
 +
print "Temp file written.  Converting...\n";
 +
 +
my $cmd = qq(sox -s -w -r 11025 -c 2 "$wtemp" -r 44100 -c 2 "$wfile");
 +
system($cmd);
 +
unlink($temp);</nowiki>
  
 
=boutell.com scripts=
 
=boutell.com scripts=

Revision as of 12:49, 14 November 2005

SoX (Sound eXchange) is a GPL command-line sound processor available from http://sox.sourceforge.net/.

Uses

For my purposes, SoX will probably become most useful for converting WAV files between formats, and for converting to and from raw data files (which could then be concatenated using stuff like cat or perl, then converted back).

Converting to raw

This will convert a WAV file to a 44100Hz (-r), 2-channel (-c), signed (-s), 16-bit (-w) raw file. The -V flag sets verbose.

sox -V src.wav -r 44100 -c 2 -s -w dst.raw

If you're interested in the length of what you're converting, -V outputs some data on stderr (redirect with 2>) that looks something like this:

x:\programs\sox.exe: Detected file format type: wav

x:\programs\sox.exe: WAV Chunk fmt
x:\programs\sox.exe: WAV Chunk data
x:\programs\sox.exe: Reading Wave file: Microsoft PCM format, 2 channels, 44100 samp/sec
x:\programs\sox.exe:         176400 byte/sec, 4 block align, 16 bits/samp, 521418428 data bytes
x:\programs\sox.exe: Input file src.wav: using sample rate 44100
        size shorts, encoding signed (2's complement), 2 channels
x:\programs\sox.exe: Output file dst.raw: using sample rate 44100
        size shorts, encoding signed (2's complement), 2 channels
x:\programs\sox.exe: Output file: comment "Processed by SoX"

521418428/176400 = 2955.887 = 49 minutes, 15.887 seconds, which is the correct length. Results may vary if the destination format is different than the source; the figures given for the output are for the source file only.

However, if the output is to raw data, it is also possible to divine the same figure with some intuition. After a conversion of the above src.wav to 32000Hz 2-channel signed 16-bit raw, the resulting file is 378353512 bytes long. 16 bits is 2 bytes, and each sample has data for 2 channels. 378353512 / (2 bytes * 2 channels * 32000Hz) = 2955.887, the correct number of seconds. Given this, you may just want to skip mucking about with redirection and just measure the result.

Converting raw to wav

Give the operating parameters of the raw file before the name of the raw file on the command line. It is possible to change format in the same pass by giving the output parameters before the output filename.

sox -V -r 44100 -c 2 -s -w src.raw dst.wav

This is a sample of what comes out on stderr with -V:

x:\programs\sox.exe: Detected file format type: raw

x:\programs\sox.exe: Input file src.raw: using sample rate 44100
        size shorts, encoding signed (2's complement), 2 channels
x:\programs\sox.exe: Writing Wave file: Microsoft PCM format, 2 channels, 44100 samp/sec
x:\programs\sox.exe:         176400 byte/sec, 4 block align, 16 bits/samp
x:\programs\sox.exe: Output file dst.wav: using sample rate 44100
        size shorts, encoding signed (2's complement), 2 channels
x:\programs\sox.exe: Output file: comment "Processed by SoX"

x:\programs\sox.exe: Finished writing Wave file, 521418428 data bytes 260709214 samples

Converting samplerate or number of channels

SoX doesn't seem to be able to handle samplerate and channels in one pass, so keep that in mind if things seem screwy.

Samplerate is the -r switch.

sox -V src.wav -r 44100 dst.wav

Channels is the -c switch.

sox -V src.wav -c 2 dst.wav

Lowpass

The example file suggests running a lowpass on anything before lowering its samplerate. What it suggests for a change from 11025Hz to 8000Hz looks something like this:

sox src.wav dst.wav lowpass 3700

My scripts

Generating silence

This script is intended for Cygwin, because I'm using the Windows version of SoX. Changing it for Unix is trivial, but if you're on Unix anyway you should be using dd and /dev/zero in a shell script instead.

#! /usr/bin/perl

use warnings;
use strict;
use Carp;

if(@ARGV != 2) {
    die "usage: $0 seconds outfile\n";
}

my $samples = int($ARGV[0] * 11025) * 4;
my $file = $ARGV[1];

my $nulls = pack('C*', ( (0) x 1024 ) );

my $temp = "/tmp/s-$$-temp1.raw";
my $wtemp = `cygpath -w "$temp"`;
my $wfile = `cygpath -w "$file"`;
chomp $wtemp;
chomp $wfile;

my $out;
open($out, ">$temp")
    or die "Could not open temp file $temp for write\n";
binmode $out;
while($samples > length($nulls))
{
    print $out "$nulls";
    $samples -= length($nulls);
}
$nulls = substr($nulls,0,$samples);
print $out "$nulls";
close $out;
print "Temp file written.  Converting...\n";

my $cmd = qq(sox -s -w -r 11025 -c 2 "$wtemp" -r 44100 -c 2 "$wfile");
system($cmd);
unlink($temp);

boutell.com scripts

Concatenating two .wav files

This is from http://www.boutell.com/scripts/catwav.html.

#!/bin/sh
sox $1 -r 44100 -c 2 -s -w /tmp/$$-1.raw
sox $2 -r 44100 -c 2 -s -w /tmp/$$-2.raw
cat /tmp/$$-1.raw /tmp/$$-2.raw > /tmp/$$.raw
sox -r 44100 -c 2 -s -w /tmp/$$.raw $3
rm /tmp/$$*.raw

Generating silence

This is from http://www.boutell.com/scripts/silence.html. I use my own, completely different version.

#!/usr/bin/perl

$seconds = $ARGV[0];
$file = $ARGV[1];
if ((!$seconds) || ($file eq "")) {
        die "Usage: silence seconds newfilename.wav\n";
}

open(OUT, ">/tmp/$$.dat");
print OUT "; SampleRate 8000\n";
$samples = $seconds * 8000;
for ($i = 0; ($i < $samples); $i++) {
        print OUT $i / 8000, "\t0\n";
}
close(OUT);

system("sox /tmp/$$.dat -b -r 44100 -c 2 -s -w $file");
unlink("/tmp/$$.dat");