Login / Register  0 items | $0.00 NewWhat is KVR? Submit News Advertise

Override WAV header

MrPresident
KVRer
 
1 post since 29 Sep, 2017

Postby MrPresident; Fri Sep 29, 2017 9:12 am Override WAV header

Hi all,

Is it possible to start playing a wav while it is still being generated, without knowing its final size? Is there a way to modify the number of samples after the header is written?

For example:

Subchunk2sz = 999999 // immutable
Data = {0, 0, 0 }
NewSubchunk2sz = 3

Thanks!
JCJR
KVRAF
 
2147 posts since 17 Apr, 2005, from S.E. TN

Postby JCJR; Fri Sep 29, 2017 8:04 pm Re: Override WAV header

Hi MrPresident. I guess it depends on how you like to read/write files. There are various audiofile libs, and various Stream type of interfaces accessible from language features.

I'm retired a few years, but started reading/writing files long ago using "fairly low level" OS file routines when thats about all there was to use, and remain mostly ignorant of the many modern alternate ways of doing files because the "low level" continued to work. No sense fixing what ain't broke. :)

Harking back to very early MacOS, file access was seemingly way over-built, written as an intelligence test to find out if a programmer is smart enough to figure out how to read/write a simple dang file. It was kinda slow compared to early windows file handling, and audio speed needed to use async file access on Macs of that era. But later on it was somewhat simplified and Mac file performance was improved.

Anyway, maybe "entirely the wrong way to do it" but on PC or Mac I'd very commonly write the header with the audio chunk size set to zero or whatever, write the audio until done. My write routines would count how many audio samples were written. When all audio was written, the last thing before closing the file, seek to the audio size fields in the header and write the final size of the audio, then close the file.

When computers started commonly having comfortable amounts of RAM, some of our programs might potentially have fairly long audio tracks, but no more than maybe six or a dozen stereo tracks. And we did a lot of "audio track generation on the fly".

So as long as it was unlikely to have to deal with insanely long songs having dozens of tracks, it was lots easier and faster to keep the audio tracks memory-resident, rather than hurt the brain with async read-ahead and progressive-write to disk kind of annoyances.

I'm just sayin, the last decade or so, early 2000's on, our typical audio track would just be a big memory pointer with the header the first data in the pointer, audio data following. So in that case, rendering a file, or assembling a track out of pieces, would write the dummy header to the pointer, then write audio data into the pointer until done, and if it needs to be saved to disk-- The whole dang file is in memory as it would appear on disk, so the last step before saving to disk is just update the size fields in the in-memory header, and then blockwrite the whole giant pointer to disk in one call. Easy peasy.

The thing about playing while also recording or rendering to disk file-- Maybe there are fancy disk access routines where you can be asunc random-access reading and writing many different places in an open file. But KISS "keep it simple stupid" file access I don't think you can be random-access reading one place in a disk file which is also open for writing, and you are in process of sequential data writing.

OTOH if you are rendering into a big in-memory pointer, just taking minor reasonable multi-threading precautions, one set of functions can be sequential writing to the "current end of data" somewhere in the middle of the big pointer, while another set of functions is random-access reading whatever it wants to read in parts of the in-memory file that have already been written.

When our Play button would get pressed and several audio tracks needed composited from scratch, we would create the in-memory pointers and render the first couple of seconds of each audio track, then start playback. The "compositing track writing" routines would keep running on a worker thread, adding audio data to the in-memory tracks, as playback would begin reading the in-memory tracks from the beginning of the song. So long as the "track writing" threads could keep ahead of the "track playback reading" at the current song location, it worked fine. On a real slow computer the track writing threads might not get done much sooner than playback comes to the end of the song, but on a fast computer maybe it would assemble all the audio tracks in a few seconds after playback begins, and shut off the track writing threads because they are done.

There are probably better ways to do it. I just told you about all I know about it. :)
stratum
KVRian
 
1285 posts since 29 May, 2012

Postby stratum; Fri Sep 29, 2017 11:54 pm Re: Override WAV header

The WAV format is fairly simple, if you write the IO code yourself you can just occasionally seek to the beginning and update the length field, and continue writing to the end. Obviously the player wouldn't read the header more than once though, so in the end it would be a waste of time unless you also write the player yourself.
~stratum~
PurpleSunray
KVRian
 
641 posts since 13 Mar, 2012

Postby PurpleSunray; Sat Sep 30, 2017 2:44 am Re: Override WAV header

MrPresident wrote:Hi all,

Is it possible to start playing a wav while it is still being generated, without knowing its final size? Is there a way to modify the number of samples after the header is written?

For example:

Subchunk2sz = 999999 // immutable
Data = {0, 0, 0 }
NewSubchunk2sz = 3

Thanks!


Set lenght to max (RIFF = 0xffffffff, chunk = 0xffffffff - 44)
Players will play until they reach end-of-file then.
Write real values when you'r done, otherwise players will show wrong playback duration.

RIFF header is easy to write/read, you don't need library for that:
http://www.topherlee.com/software/pcm-t ... ormat.html

Moderator: Moderators (Main)

Return to DSP and Plug-in Development