Quick question about WAV header file

Hey there!
So I’m currently learning how to code in C and thought about writing a program that would allow me to read the WAV header file.
I’m very interested in writing similar programs because there are a lot of files that I can’t just open with notepad to read what’s inside, so I thought starting with the WAV header file would be a nice way to learn this since it’s very short, only 44 bytes.

I’m using the table here as a reference:

Everything was going well until I reached the 25–28 byte positions, which say:
“Sample Rate - 32 byte integer. Common values are 44100 (CD), 48000 (DAT). Sample Rate = Number of Samples per second, or Hertz.”

I’m finding it very hard to understand how a 32-byte integer fits in just 4 bytes (from 25 to 28). My current assumption is that maybe I should just write the number as a 4-byte integer, then fill the rest with zeros so it represents a 32-byte integer? However, I don’t think that makes much sense because the number would be very large.

Also, I have a feeling that it’s supposed to be 32 bits and not bytes, but since I’m very new to programming (it’s been a month and a half since I started learning C), I don’t want to assume that there’s an error in the source, so I’d prefer to ask the experts here : )

Thank you in advance!

@Yousri ,

Can you please share a sample WAV header file for our reference?

Hey Kashif!

I’m not sure how to do this properly, but after writing the code I was working on, here is the output from the terminal:
Terminal output.png (5.1 KB)

Here’s a text version as well:

RIFF: RIFF
File size: 352836
WAVE: WAVE
fmt: fmt 
previous Bytes size: 16
Type of format: 1 PCM
Format Channel: 2
Sample rate: 44100
Sample rate math: 176400
Mono/Stereo: 4
Bits per sample: 16
/////DATA///// 1635017060
File Size Data: 352800

I think it worked fine? It’s matching the table quite well
I had to set the sample rate to be a 32-bit integer instead of 32-byte integer, so I think it was a typo after all? (Unless I’m just lost)

Please note that this is my first time ever trying something like this. I believe my code isn’t the best (it feels unnecessarily long), so I’m sorry if it’s confusing to read. Here’s the code I wrote, in case it helps you with anything:

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

typedef uint8_t BYTE;
typedef int16_t BYTE_2;

int main(int argc, char *argv[])
{
    // Check command line arguments
    if (argc != 4)
    {
        printf("Usage: ./alone Input_file Output_file Factor(Number)\n");
        return 1;
    }

    // Open files
    FILE *input = fopen(argv[1], "r");
    if (input == NULL)
    {
        printf("Can't open file\n");
        return 2;
    }

    FILE *output = fopen(argv[2], "w");
    if (output == NULL)
    {
        printf("Can't create a file \n");
        return 3;
    }

    // Copy and output RIFF
    BYTE RIFF[4];
    fread(&RIFF, sizeof(RIFF), 1, input);
    fwrite(&RIFF, sizeof(RIFF), 1, input);
    printf("RIFF: ");
    for (int i = 0; i < 4; i++)
    {
        printf("%c", RIFF[i]);
    }
    printf("\n");

    // File size
    int file_size;
    fread(&file_size, sizeof(file_size), 1, input);
    fwrite(&file_size, sizeof(file_size), 1, input);
    printf("File size: %i\n", file_size);

    // Modify the rest of the file
    float factor = atof(argv[3]);

    // "WAVE"
    BYTE WAVE[4];
    fread(&WAVE, sizeof(WAVE), 1, input);
    fwrite(&WAVE, sizeof(WAVE), 1, input);
    printf("WAVE: ");
    for (int i = 0; i < 4; i++)
    {
        printf("%c", WAVE[i]);
    }
    printf("\n");

    // "fmt"
    BYTE fmt[4];
    fread(&fmt, sizeof(fmt), 1, input);
    fwrite(&fmt, sizeof(fmt), 1, input);
    printf("fmt: %s\n", &fmt[0]);

    // Length of previous
    int previous;
    fread(&previous, sizeof(previous), 1, input);
    fwrite(&previous, sizeof(previous), 1, input);
    printf("previous Bytes size: %i\n", previous);

    // Format type
    short format;
    fread(&format, sizeof(format), 1, input);
    fwrite(&format, sizeof(format), 1, input);
    printf("Type of format: %i", format);
    if (format == 1)
        printf(" PCM\n");
    else
        printf("\n");

    // Format Channel
    fread(&format, sizeof(format), 1, input);
    fwrite(&format, sizeof(format), 1, input);
    printf("Format Channel: %i\n", format);

    // Sample Rate
    int Sample_Rate;
    fread(&Sample_Rate, sizeof(Sample_Rate), 1, input);
    fwrite(&Sample_Rate, sizeof(Sample_Rate), 1, input);
    printf("Sample rate: %i\n", Sample_Rate);

    // Sample Rate Math:
    fread(&Sample_Rate, sizeof(Sample_Rate), 1, input);
    fwrite(&Sample_Rate, sizeof(Sample_Rate), 1, input);
    printf("Sample rate math: %i\n", Sample_Rate);

    // Mono/Stereo
    short M_S;
    fread(&M_S, sizeof(M_S), 1, input);
    fwrite(&M_S, sizeof(M_S), 1, input);
    printf("Mono/Stereo: %i\n", M_S);

    // Bits per sample
    fread(&M_S, sizeof(M_S), 1, input);
    fwrite(&M_S, sizeof(M_S), 1, input);
    printf("Bits per sample: %i\n", M_S);

    // Data
    fread(&Sample_Rate, sizeof(Sample_Rate), 1, input);
    fwrite(&Sample_Rate, sizeof(Sample_Rate), 1, input);
    printf("/////DATA///// %i\n", Sample_Rate);

    // File size Data
    fread(&Sample_Rate, sizeof(Sample_Rate), 1, input);
    fwrite(&Sample_Rate, sizeof(Sample_Rate), 1, input);
    printf("File Size Data: %i\n", Sample_Rate);

    // Write the new Wav file
    BYTE_2 buffer;
    while(fread(&buffer, sizeof(buffer), 1, input))
    {
        buffer *= factor;
        fwrite(&buffer, sizeof(buffer), 1, output);
    }



    // Close files
    fclose(input);
    fclose(output);
}

It’s supposed to print the header file in the terminal, then change the volume of the WAV file by multiplying it with the variable “factor” (I was just experimenting to learn stuff).

Thanks!

@Yousri

I would recommend you to use a small tool (Tiny Hex Editor) to see the binary values of the file.

As you can see in screenshot, the number is showing as

image.png (38.1 KB)

44AC0000

25th Byte: 44
26th Byte: AC
27th Byte: 00
28th Byte: 00

When you read it in 32-bit integer, it will be read as (Little Endian)

28th Byte- 27th Byte - 26th Byte - 25th Byte
0000AC44

Now you got this Hex number: 0000AC44

Convert it to decimal: 44100

image.png (12.1 KB)

Let me know if it answers your question.

2 Likes

Thank you Shakeel! Yes this answers my questions and helps a lot : D
I was very confused because in the linked table (WAV - Waveform Audio File Format) it said 32-byte integer, not 32-bit, so I thought I was supposed to use a different method to read it

Seeing you reading it in 32-bit (instead of bytes) cleared my confusion now, so thank you!
bit-byte.png (34.9 KB)

Also thank you for recommending that tool! I’ve already gave it a try and it’s very helpful : )

1 Like

@Yousri ,

We are glad to hear that the information provided was helpful to you.