generate silent wav
Sat, 04 Jun 2011 23:14 categories: codeI wanted a few seconds of complete silent audio. Since I already knew how audio is encoded using LPCM I thought it would be simple enough to write a small snippet that also creates the RIFF file structure around it for a complete *.wav file. And indeed it is. This is how to generate a *.wav file containing some seconds of silence.
#!/usr/bin/python
from struct import pack
from sys import stdout
duration = 1 # seconds of silence
channels = 1 # number of channels
bps = 16 # bits per sample
sample = 44100 # sample rate
ExtraParamSize = 0
Subchunk1Size = 16+2+ExtraParamSize
Subchunk2Size = duration*sample*channels*bps/8
ChunkSize = 4 + (8 + Subchunk1Size) + (8 + Subchunk2Size)
stdout.write("".join([
'RIFF', # ChunkID (magic) # 0x00
pack('<I', ChunkSize), # ChunkSize # 0x04
'WAVE', # Format # 0x08
'fmt ', # Subchunk1ID # 0x0c
pack('<I', Subchunk1Size), # Subchunk1Size # 0x10
pack('<H', 1), # AudioFormat (1=PCM) # 0x14
pack('<H', channels), # NumChannels # 0x16
pack('<I', sample), # SampleRate # 0x18
pack('<I', bps/8 * channels * sample), # ByteRate # 0x1c
pack('<H', bps/8 * channels), # BlockAlign # 0x20
pack('<H', bps), # BitsPerSample # 0x22
pack('<H', ExtraParamSize), # ExtraParamSize # 0x22
'data', # Subchunk2ID # 0x24
pack('<I', Subchunk2Size), # Subchunk2Size # 0x28
'\0'*Subchunk2Size
]))
And because it was fun, the whole thing in shell:
#!/bin/sh
pack_int(){ printf "%08X\n" $1 | sed 's/\([0-9A-F]\{2\}\)\([0-9A-F]\{2\}\)\([0-9A-F]\{2\}\)\([0-9A-F]\{2\}\)/\\\\\\x\4\\\\\\x\3\\\\\\x\2\\\\\\x\1/I' | xargs printf; }
pack_short(){ printf "%04X\n" $1 | sed 's/\([0-9A-F]\{2\}\)\([0-9A-F]\{2\}\)/\\\\\\x\2\\\\\\x\1/I' | xargs printf; }
duration=1
channels=1
bps=16
sample=44100
Subchunk1Size=18
Subchunk2Size=$(($duration*$sample*$channels*$bps/8))
ChunkSize=$((20 + $Subchunk1Size + $Subchunk2Size))
echo -n RIFF
pack_int $ChunkSize
echo -n "WAVEfmt "
pack_int $Subchunk1Size
pack_short 1
pack_short $channels
pack_int $sample
pack_int $((bps/8 * channels * sample))
pack_short $((bps/8 * channels))
pack_short $bps
pack_short 0
echo -n data
pack_int $Subchunk2Size
dd if=/dev/zero bs=1 count=$Subchunk2Size 2>/dev/null