Thread overview
Problems using rawWrite in an experiment with WAVs in D
Dec 27
tososdk
December 27

I was recreating some code from C++ to D:

import std.stdio;
import std.file;
import std.string;
import std.math;

struct WavHeader {
    char[4] riff;
    int flength;
    char[4] wave;
    char[4] fmt;
    int chunk_size;
    short format_tag;
    short num_chans;
    int sample_rate;
    int bytes_per_second;
    short bytes_per_sample;
    short bits_per_sample;
    char[4] data;
    int dlength;
}

void main() {
    WavHeader wahv;

    wahv.riff[] = "RIFF".dup;
    wahv.wave[] = "WAVE".dup;
    wahv.fmt[] = "fmt ".dup;
    wahv.data[] = "data".dup;

    wahv.chunk_size = 16;
    wahv.format_tag = 1;
    wahv.num_chans = 1;
    wahv.sample_rate = 8000;
    wahv.bits_per_sample = 16;
    wahv.bytes_per_sample = cast(short)((wahv.bits_per_sample / 8) * wahv.num_chans);
    wahv.bytes_per_second = wahv.sample_rate * wahv.bytes_per_sample;

    const int duration_seconds = 10;
    const int buffer_size = wahv.sample_rate * duration_seconds;
    wahv.dlength = buffer_size * wahv.bytes_per_sample;
    wahv.flength = wahv.dlength + 44;

    short[] buffer = new short[buffer_size];

    foreach (i; 0 .. buffer_size) {
        buffer[i] = cast(short)(cos((2.0 * PI * 256.0 * i) / wahv.sample_rate) * 1000);
    }

  // Corrected file handling
  auto file = File("test.wav", "r");
  file.rawWrite(wahv);

  // Writing the audio data as raw bytes
  file.rawWrite(cast(ubyte[])buffer);

  file.close();
}

But since I am somewhat new to these topics and even more so to Dlang, I don't understand very well. The problem occurs in the creation of the .wav, regarding rawWrite, I'm not really sure what to do in that specific part. Maybe I'm ignorant, but I'm not very good at these topics, plus it's for experimentation.

December 28
Because WaveHeader has no pointers in it, only raw memory, assuming it is all in the cpu endianesss and with ``align(1)`` you can slice that block of stack memory and write from that.

```d
file.rawWrite((cast(ubyte*)&wahv)[0 .. WaveHeader.sizeof]);
```

However I would recommend doing it field by field.

A lot more work, but allows you to handle endianness issues and remove alignment concerns. Also changing of field sizes if required.

Same principles as the code above.
December 27

On Wednesday, 27 December 2023 at 20:20:23 UTC, tososdk wrote:

>

I was recreating some code from C++ to D:
[...]
But since I am somewhat new to these topics and even more so to Dlang, I don't understand very well. The problem occurs in the creation of the .wav, regarding rawWrite, I'm not really sure what to do in that specific part. Maybe I'm ignorant, but I'm not very good at these topics, plus it's for experimentation.

Here's the error message I got when I tried to compile your code:

Error: template `std.stdio.File.rawWrite` is not callable using argument types `!()(WavHeader)`
/dlang/dmd/linux/bin64/../../src/phobos/std/stdio.d(1273):        Candidate is: `rawWrite(T)(in T[] buffer)`

What this message is saying is that you tried to pass a WavHeader to rawWrite, but rawWrite expects a slice (T[], where T can be any type) as an argument.

The easiest way to fix this is to use pointer slicing to create a temporary slice that points to wavh:

  file.rawWrite((&wahv)[0 .. 1]);