• Home
  • Tags
  • RSS
  • About
  • generate silent wav

    Timestamp:
    Tags: code

    I 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