andersch.dev

<2023-04-10 Mon>
[ audio ]

WAVE (File format)

The Waveform Audio File Format (WAVE, file extension .wav) is an audio file format standard used for storing uncompressed audio. It supports different bitstream encodings, with the most used one being the linear pulse-code modulation (LPCM) format. It is based on the Resource Interchange File Format (RIFF) and thus stores data in chunks.

Checking for .wav magic number

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>

#define RIFF_MAGIC_NUMBER "RIFF"
#define WAV_MAGIC_NUMBER  "WAVE"

struct wav_chunk
{
    uint8_t  chunk_id[4];
    uint32_t chunk_size;
};

struct wav_format
{
    uint16_t format_tag;            // format code
    uint16_t nr_channels;           // interleaved channels
    uint32_t sample_rate;           // blocks per second
    uint32_t data_rate;             // bytes per second
    uint16_t block_size;            // in bytes
    uint16_t bit_depth;             // bits per sample
    uint16_t cb_size;               // size of the extension (0 or 22)
    uint16_t valid_bits_per_sample; // Number of valid bits  // only if chunk_size >= 18
    uint32_t dw_channel_mask;       // Speaker position mask // only if chunk_size == 40
    uint8_t  sub_format[16];        // GUID                  // only if chunk_size == 40
};

int main(int argc, char** argv)
{
    FILE* wave_file = fopen(argv[1], "r");
    if (!wave_file)
    {
        printf("Error opening %s: %s\n", argv[1], strerror(errno));
        exit(-1);
    }

    char* file_buf = NULL;
    long  file_len = 0;

    fseek(wave_file, 0, SEEK_END);    // Jump to the end of the file
    file_len = ftell(wave_file);      // Get the current byte offset in the file
    rewind(wave_file);                // Jump back to the beginning of the file

    file_buf = (char *) malloc(file_len * sizeof(char));
    fread(file_buf, file_len, 1, wave_file); // Read in the entire file
    fclose(wave_file);

    char riff_magic_nr[4] = {file_buf[0], file_buf[1], file_buf[2],  file_buf[3] };
    char wav_magic_nr[4]  = {file_buf[8], file_buf[9], file_buf[10], file_buf[11]};
    if ((strcmp(riff_magic_nr, RIFF_MAGIC_NUMBER) != 0) ||
        (strcmp(wav_magic_nr, WAV_MAGIC_NUMBER)   != 0))
    {
        printf("Could not recognize file format of '%s'\n", argv[1]);
        free(file_buf);
        exit(-1);
    }

    return 0;
}

Resources