Search guides and the APICtrl K
  1. API reference
  2. Files and codecs

streams.h

Byte streams: one interface for a file, a buffer, a URL, or a window onto another stream.

#include <sonore/streams.h>
  • 7types
On this page

Design notes

Why a hierarchy, when everything else here is plain functions

The rest of this SDK reads files whole: a preset is a few kilobytes, a WAV is parsed by audiofile.h straight off the disk, and a vector of bytes is the simplest thing that could work. That stops being true the moment the same code has to read from more than one KIND of source -- a sample pack that is sometimes a file, sometimes a slice of a zip, sometimes an HTTP download -- and that is the one argument the reference's stream classes make which survives contact with a plugin. So: one small abstract InputStream, and the sources are FileInputStream (file_types.h), WebInputStream (net.h), MemoryInputStream, and two adaptors over any of them, BufferedInputStream and SubregionStream. Code that takes an InputStream& reads all of them.

The decisions a reader of a stream cares about

read() returns the bytes it produced, never a negative number: zero is the end, or a failure the stream can describe -- a caller that loops "while read() > 0" cannot spin on an error. Multi-byte readers name their byte order (readInt is little-endian, readIntBigEndian is not) and assemble values from bytes with shifts, never by casting a pointer -- an unaligned load is a crash on some ARM cores and undefined behaviour everywhere. A reader that runs out of input returns zero for the value; whoever needs to know checks isExhausted().

Threads

A stream is one reader's object. The memory streams never block; the file and network ones do I/O and may block for as long as a disk or a server takes, so NONE of them is for the audio thread. Read on a loader thread and hand the result over (audio_ring.h, the sampler's own streaming).

Types 7

Something bytes can be read from, in order, with a position.

Something bytes can be written to, with a position.

class MemoryInputStream : public InputStream

Reads a block of memory: either a copy it owns, or someone else's bytes that must outlive it.

class MemoryOutputStream : public OutputStream

Writes into a growing block of memory -- its own, or a vector the caller owns and keeps. Writing past the end grows it; writing at a position before the end overwrites, which is how a size field written as a placeholder is filled in afterwards.

class BufferedInputStream : public InputStream

Reads another stream through a buffer: many small reads (a parser taking a byte at a time) become few large ones on the source. Seeks inside the buffered window cost nothing; anywhere else is passed to the source.

class SubregionStream : public InputStream

A window onto part of another stream: position 0 here is startPositionInSourceStream there, and the end is lengthOfSourceStream later (or the source's end, when that is negative). How one entry of an uncompressed archive, or one chunk of a RIFF file, is handed to code that expects a stream of its own.

Somewhere a stream can be opened from, again and again: the reference's way for a reader that needs a fresh stream per use (a sample pool reopening a file per voice) to be handed a file, a URL or a buffer alike. FileInputSource is in file_types.h.

↑↓ to move↵ to openEvery public name in the headers, and every guide