Difference between revisions of "SoX (Sound eXchange)"
Line 10: | Line 10: | ||
sox -V src.wav -r 44100 -c 2 -s -w dst.raw | sox -V src.wav -r 44100 -c 2 -s -w dst.raw | ||
+ | |||
+ | For those interested in other representations, | ||
+ | |||
+ | * Signs | ||
+ | ** signed (-s) | ||
+ | ** unsigned (-u) | ||
+ | * Lengths | ||
+ | ** 8-bit/byte (-b) | ||
+ | ** 16-bit/word (-w) | ||
+ | ** 32-bit/long (-l) | ||
+ | |||
+ | If raw files are passed with the extensions .ub, .uw, .sb, .sw, .ul, or .sl, the corresponding representation will be assumed. | ||
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: | 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: |
Revision as of 21:18, 25 November 2005
SoX (Sound eXchange) is a GPL command-line sound processor available from http://sox.sourceforge.net/.
Contents
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
For those interested in other representations,
- Signs
- signed (-s)
- unsigned (-u)
- Lengths
- 8-bit/byte (-b)
- 16-bit/word (-w)
- 32-bit/long (-l)
If raw files are passed with the extensions .ub, .uw, .sb, .sw, .ul, or .sl, the corresponding representation will be assumed.
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");