blob: 9d62b31a4daef651f0a2223d493e6eb34d02a7ae [file] [view]
# WavWriter library #
This library enables clients to save audio stream(s) to WAV audio files. This
is intended for use during development only: it allows developers to analyze
and improve audio fidelity in their components (including Fuchsia OS itself).
This functionality can be toggled by the bool template parameter on the
WavWriter object itself. When false, it results in zero additional code added
(assuming a reasonable optimizing compiler).
In Fuchsia, this library is used in various locations, including media examples
FX and wav_recorder, as well as the system audio mixer itself. What follows are
details on how to use the WavWriter library, followed by instructions on using
the WavWriter support built into the system mixer to inspect the final mixed
audio output streams -- useful when debugging audio-related code.
### Using WavWriter ###
See `wav_recorder` in 'examples/media' for a focused, easy-to-follow example
of using this library.
After creating a WavWriter object (with template parameter 'true' or blank),
the `Initialize` call creates a RIFF-based WAV audio file, leaving it open
and ready for writing the audio data into the file. The file is of non-zero
size because there is a file header describing the contents, but it contains
no audio data yet. The `Reset` call, incidently, returns the file to exactly
this state.
Subsequently, the `Write` call accepts a buffer of audio data, as well as the
number of bytes in that buffer, and it transfers those bytes directly into the
file. Note that for performance reasons, the file headers are not updated upon
every single `Write` call. Because the headers contain fields that denote the
amount of audio data, they must be updated eventually, but this could be done
only occasionally, or even just once at the end of the recording process. The
`UpdateHeaders` call does exactly this, writing the two fields that change as
the file grows in size, and returning the write cursor to the end of the open
file. Clients can call `UpdateHeader` as frequently as they wish (after every
_Write_, or every few seconds, or only once).
The `Close` call finalizes (closes) the file handle and returns the library to
an uninitialized state, preventing it from being written further. Before it
does so, `Close` first conveniently calls `UpdateHeader`. At any time, `Delete`
will remove the WAV file that has been created, leaving the file system as it
was before. Note that `Delete` can be called at any time after `Initialize` has
been called, even after `Close` has been called.
As mentioned above, by simply switching the template parameter to <false>, all
library code will convert to inlined stubs that are eliminated by a modern
optimizing compiler -- so you can instrument your code without worrying about
any impact on performance when this tracing is disenabled.
### Inspecting final output from the system mixer ###
In development builds of the Fuchsia OS, the WavWriter can be used to examine
the audio streams emitted by the system mixer (of course, this functionality is
removed from official production builds where this might pose a media security
or overall resource consumption risk).
To enable the WavWriter support in the system audio mixer, change the bool
(kWavWriterEnabled) found toward the top of driver_output.cc to 'true'. The
Fuchsia system mixer produces a final mix output stream (potentially
multi-channel) for every audio output device found. Thus, enabling the
WavWriter will cause an audio file to be created for each output device.
These files are created on the target (Fuchsia) device at location
'/tmp/wav_writer_N.wav', where N is a unique integer for each output. One can
copy these files back to the host with:
```
fx scp <ip of fuchsia device>:tmp/wav_writer_*.wav ~/Desktop/
```
At this time, once audio playback begins on any device, the system audio mixer
produces audio for ALL audio output devices (even if no client is playing
audio to that device). The wave files for these devices will, naturally,
contain silence.
Additionally, at this time Fuchsia continues mixing (once it has started) to
output devices indefinitely, even after all clients have closed. This will
change in the future. Until then, however, the most effective way to use this
tracing feature is to `killall audio_core` on the target, once playback is
complete. (The _audio_core_ process restarts automatically when needed, so
this is benign.) The mixer calls `UpdateHeader` to update the 'length'
parameter in both RIFF Chunk and WAV header after every successive file write,
so the files should be complete and usable even if you kill audio_core during
audio playback (which means that `Close` is never called).