Sound Library
The sound library is an external library for managing audio. It provides an interface for working
with streams of sound data that is similar to the IO part of the
standard library (but works on 32-bit floating point values instead of bytes). It also provides
decoding of common audio formats (currently, mp3, ogg, flac, and wav), and playback of audio
streams. The library also defines a thread, sound.Audio
, for executing sound-related
code.
The remainder of this part of the manual provides an overview of these interfaces.
Sound
The type sound.Sound
represents a stream of audio samples. As such, it is analogous to
the type core.io.IStream
in the standard library. The type itself does not provide any
audio data. Any of the derived types may be used for this purpose.
A sound stream is considered to consist of a sequence of samples. Each sample is represented by a
32-bit floating point number (core.Float
). If the sound stream contains multiple
channels, samples for all channels are interleaved in the stream as specified by the vorbis
format. For example, for 2 channels, the first sample is for the left channel, the second is for the
right, and so on. The interface expects consumers of the sound data to work in multiples of the
channel size.
Audio streams may be seekable or non-seekable. Seekable streams return a non-zero length, while non-seekable streams return a zero length.
The type has the following members:
-
core.Nat sampleFreq()
Get the sample frequency of the stream, measured in samples per second.
-
core.Nat channels()
Get the number of channels for this stream.
-
void close()
Close the stream now. Also closes any underlying input streams for this stream.
-
core.Bool more()
Is more data available in the stream? Might return false only after reading zero bytes for the first time.
-
core.Word length()
Get the length of the stream, measured in samples. Returns zero if the stream is not seekable.
-
core.Bool seek(core.Word to)
Seek in the input stream. Returns
false
if seeking is not supported, or an error occurred. The position is measured in samples. The position is expected to be a multiple of the number of channels. -
core.Word tell()
Get the current position, measured in samples. May return zero for non-seekable streams.
-
sound.Buffer read(sound.Buffer to)
Attempt to fill the buffer
to
with samples from the stream. Fills the bytes fromfilled
tocount
in the buffer. Only reads a multiple ofchannels
samples from the stream. If zero samples are read, then the end of the stream is reached. -
sound.Buffer read(core.Nat samples)
Read data from the buffer into a new, empty buffer with space for the specified number of samples.
Reading Sound
As mentioned above, the library contains support for some common audio formats, namely mp3, ogg, flac, and wav. Support for most of these are provided by external libraries that are compiled into the library on most platforms. Support for wav is native to the library, and as such support for compressed wav-files is limited.
The library provides the following classes to decode the different formats:
-
sound.Mp3Sound
-
sound.OggSound
-
sound.FlacSound
-
sound.WavSound
These are generally created by the functions openX
or openXStream
. The former accepts a
core.io.RIStream
and creates a seekable stream, while the latter accepts a
core.io.IStream
and creates a non-seekable stream.
The library also provides generic operations for opening sound files and automatically deducing the file format based on the header in the file:
-
sound.Sound sound(core.io.IStream src)
Create a sound stream for reading
src
based on the header insrc
. Will makesrc
into a seekable stream to provide a seekable audio stream. -
sound.Sound soundStream(core.io.IStream src)
Open sound from a streaming source. The resulting stream will not be seekable.
-
sound.Sound readSound(core.io.Url file)
Calls
sound(file.read())
. -
sound.Sound readSoundStream(core.io.Url file)
Calls
soundStream(file.read())
.
Buffer
The sound.Buffer
represents a series of samples, represented as 32-bit floating point
values in the range 1.0 to -1.0. The interface closely resembles that of core.io.Buffer
,
which is documented here.
As with the buffers in the IO library, copies of buffers generally refer to the same data, but are
copied across thread boundaries. As such, when using the read
function in a Sound
stream, it is
important to use the returned buffer, even though the buffer that was passed to the function is
updated in most cases.
The Buffer
has the following members:
-
init()
Default constructor. Create an empty buffer. Use the function
buffer
to create a buffer with non-zero size. -
core.Nat count()
Get the number of samples in the buffer in total.
-
core.Nat filled()
Get the number of samples from the beginning of the buffer that are considered to contain valid data. The buffer itself generally does not use this value. Rather, it is used as an universal marker for how much of the buffer is used for actual data, and how much is free.
-
void filled(core.Nat p)
Set the number of samples that are used. Limits the value to be maximum
count
. Marked as an assign functions, so thatfilled
can be used as a member variable in languages like Basic Storm. -
core.Nat free()
Get the number of free samples in the buffer, based on the
filled
member. -
core.Float& [](core.Nat id)
Access individual samples.
-
core.Bool empty()
Is the buffer empty according to the
filled
member? -
core.Bool full()
Is the buffer full, according to the
filled
member? -
void toS(core.StrBuf to)
Output. A toS() is generated automatically.
-
void outputMark(core.StrBuf to, core.Nat markAt)
Output the buffer, specifying an additional mark.
The buffer also has the following free function buffer
to create buffers:
-
sound.Buffer buffer(core.Nat count)
Create a buffer with room for
count
bytes. It will be empty initially.
Player
The type sound.Player
represents an audio stream that is being played on the system's
default speakers. On Windows, it uses the DirectSound API, and on Linux it relies on OpenAL. The
implementation typicallby buffers some amount of sound data internally to avoid artifacts. The
Player
provides basic controls for the audio playback:
-
init(sound.Sound sound)
Create a player that plays the specified
sound
. ThePlayer
takes responsibility for closing the sound stream eventually, and assumes that the sound stream is not modified externally. Will not play the sound untilplay
is called. -
void close()
Destroy any resources associated with the
Player
. The destructor automatically callsclose
eventually, but since this does not always happen promptly, it is a good idea to manually callclose
whenever possible. -
void play()
Start playing the sound.
-
core.Bool playing()
Is the stream currently playing?
-
void pause()
Pause the sound.
-
void stop()
Stop playing the sound. This also resets the playback position to zero (for seekable streams).
-
core.Duration time()
Get the time of playback.
-
core.Float volume()
Get the current volume.
-
void volume(core.Float level)
Set the sound volume (between 0 and 1). Marked as an assign function, so that
volume
can be treated as a member variable. -
void wait()
Wait until playback reaches the end of the stream, or until playback is stopped. Do not call from the UThread that manages callbacks.
-
void waitUntil(core.Duration t)
Wait until playback reaches or passes the specific duration since start, or if the player is stopped. Do not call from the UThread managing callbacks.