ruuda / hound

A wav encoding and decoding library in Rust

Home Page:https://codeberg.org/ruuda/hound

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature request: writing wav to stdout and other !Seek sinks.

vi opened this issue · comments

Just set duration in header to maximum possible.

What do you want to achieve exactly? Do the samples ever end, and should the output be a valid wav file at that point? Is there a specific reason for choosing a maximal duration, or does your use case ignore the duration anyway?

One thing that might be possible is to only require W: io::Write on WavWriter, but to add the constraint W: io::Seek to WavWriter::flush() and WavWriter::finalize(). That would make it impossible to properly finalize the file on drop, but it is better to explicitly call finalize() anyway.

Just do like other multimedia command-line tools do: use 0xFFFFFFFF as chunk and data subchunk size initially, then patch it up to correct size on finalize if seeking is available (and just leave unpatched header otherwise).

Hound also fails to properly read wav pipes:

Error: FormatError("data chunk length is not a multiple of sample size")

0xFFFFFFFF should be treated as a special value that means "no length, this is a stream, just read until EOF".

This allows using Hound-based programs in pipeline, like this:

ffmpeg -i some_file.m4a -f wav - | ./program_reads_wav_and_outputs_wav | ffmpeg -i - -y output.mka

possible is to only require W: io::Write on WavWriter, but to add the constraint W: io::Seek to WavWriter::flush() and WavWriter::finalize()

It is one of options. But Drop may be a problem.

Another option may be to split it to higher-level WavWriter and lower-level impl::WavWriter. High-level version automatically calls finialize on Drop and requires Seek;
low-level writer has special function for patching up header (without flusing inner writer) requiring Seek and separate flush function that just flushes writer without seeking, also not finalizing automatically on drop.

I know you've already merged the solution, but FWIW, this is what DAWs do when recording audio, so that if the program crashes, you have something. A while back I saved an hour's worth of live Ableton recordings thanks to this. (Incidentally, Logic couldn't handle the infinite-duration header Ableton wrote and wouldn't import it, so I actually had to hexedit all the files and edit the duration value myself. Also it was AIFF-C, as this technique is not limited to WAV. But it worked!)

This feature would be great!
I believe this is also useful if you want to stream the bytes instead of recording to a file, is it not?

Not sure what's needed for streaming all the bytes, I suppose also updated header would be good for such a stream-like approach.