1

Im trying to read the header of a wav file ( wav file that works with media players) in my program, but i only find invalid values ( for sample rate, number of channels ect)

pub const WavObject = struct {
    riff_identifier: *[4]u8, // Chunk identifier: "RIFF"
    riff_chunk_size: u32, // Chunk size (file size - 8 bytes)
    riff_format: *[4]u8, // Format identifier: "WAVE"
    fmt_identifier: *[4]u8, // Format subchunk identifier: "fmt "
    fmt_subchunk_size: u32, // Subchunk size (16 for PCM)
    fmt_audio_format: u16, // Audio format (1 for PCM)
    fmt_num_channels: u16, // Number of channels (1 for mono, 2 for stereo)
    fmt_sample_rate: u32, // Sample rate (samples per second)
    fmt_byte_rate: u32, // Byte rate (sample rate * block size)
    fmt_block_size: u16, // Block size (channels * bits per sample  8)
    fmt_bits_per_sample: u16, //Bits per sample (8 or 16)
    data_identifier: *[4]u8, // Data subchunk identifier: "data"
    data_size: u32, // Data subchunk size (size of the raw audio data)

    
    pub fn deserializeHeader(wavBytes: []u8, allocator: std.mem.Allocator) !*WavObject {
        var wavObj = try allocator.create(WavObject);
        if (wavBytes.len < 44) return error.InvalidWav;

        const riffChunku32: u32 = undefined;
        const subChunkSize: u32 = undefined;
        const audioFormat: u16 = undefined;
        const numChannels: u16 = undefined;
        const sampleRate: u32 = undefined;
        const byteRate: u32 = undefined;
        const blockSize: u16 = undefined;
        const bitsPerSample: u16 = undefined;
        const dataSize: u32 = undefined;

        // Parse individual fields from the wavBytes array
        std.mem.writeInt(u32, wavBytes[4..8], riffChunku32, .little);
        std.mem.writeInt(u32, wavBytes[16..20], subChunkSize, .little);
        std.mem.writeInt(u16, wavBytes[20..22], audioFormat, .little);
        std.mem.writeInt(u16, wavBytes[22..24], numChannels, .little);
        std.mem.writeInt(u32, wavBytes[24..28], sampleRate, .little);
        std.mem.writeInt(u32, wavBytes[28..32], byteRate, .little);
        std.mem.writeInt(u16, wavBytes[32..34], blockSize, .little);
        std.mem.writeInt(u16, wavBytes[34..36], bitsPerSample, .little);
        std.mem.writeInt(u32, wavBytes[40..44], dataSize, .little);

        wavObj.riff_identifier = wavBytes[0..4];
        wavObj.riff_chunk_size = riffChunku32;
        wavObj.riff_format = wavBytes[8..12];
        wavObj.fmt_identifier = wavBytes[12..16];
        wavObj.fmt_subchunk_size = subChunkSize;
        wavObj.fmt_audio_format = audioFormat;
        wavObj.fmt_num_channels = numChannels;
        wavObj.fmt_sample_rate = sampleRate;
        wavObj.fmt_byte_rate = byteRate;
        wavObj.fmt_block_size = blockSize;
        wavObj.fmt_bits_per_sample = bitsPerSample;
        wavObj.data_identifier = wavBytes[36..40];
        wavObj.data_size = dataSize;
        return wavObj;
    }
    // test code 
    test "basic play wav" {
    const start = std.time.microTimestamp();
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();
    // reads header and prints values
    const buffer = try allocator.alloc(u8, 2048 * 100000);
    const file = try std.fs.cwd().openFile("./samples/hip_hop_kick.wav", .{ .mode = std.fs.File.OpenMode.read_only });
    const reader = file.reader();
    _ = try reader.read(buffer);
    const wavObj = try wav.WavObject.deserializeHeader(buffer[0..44], allocator);
    wavObj.PrintHeader();
    std.debug.print("{d}", .{buffer[0..44]});
    const end = std.time.microTimestamp();

    std.debug.print("time {d} \n", .{end - start});
}
1
  • 1
    Is there a reason you are using *[4]u8 for riff_identifier, riff_format, fmt_identifier, and data_identifier? Why not just use [4]u8? Also, deserializeHeader seems to allocate the WavObject on the heap for no reason. You could return it by value. Commented Dec 16, 2024 at 14:30

1 Answer 1

1
    // Parse individual fields from the wavBytes array
   std.mem.writeInt(u32, wavBytes[4..8], riffChunku32, .little);
   ...

You're using writeInt, which writes to memory, not reads from it. Try using readInt.

If you change wavBytes to []const u8 type in deserializeHeader, you'll get a compiler error highlighting your mistake.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.