digitalmars.D.learn - Problems using rawWrite in an experiment with WAVs in D
- tososdk (58/58) Dec 27 2023 I was recreating some code from C++ to D:
- Richard (Rikki) Andrew Cattermole (10/10) Dec 27 2023 Because WaveHeader has no pointers in it, only raw memory, assuming it
- Paul Backus (18/24) Dec 27 2023 Here's the error message I got when I tried to compile your code:
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.
Dec 27 2023
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.
Dec 27 2023
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][1] to create a temporary slice that points to `wavh`: ```d file.rawWrite((&wahv)[0 .. 1]); ``` [1]: https://dlang.org/spec/expression.html#slice_expressions
Dec 27 2023