1
0
forked from 0ad/0ad
0ad/source/lib/res/snd.h

203 lines
8.8 KiB
C
Raw Normal View History

// OpenAL sound engine
//
// Copyright (c) 2004-5 Jan Wassenberg
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// Contact info:
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include "handle.h"
// overview:
// this module provides a moderately high-level sound interface. basic usage
// is opening a sound and requesting it be played; it is closed automatically
// when playback has finished (fire and forget).
// any number of sound play requests may be issued; the most 'important' ones
// are actually played (necessary due to limited hardware mixing capacity).
// 3d positional sounds (heard to emanate from a given spot) are supported.
// active sound instances are referenced by Handles, so changing volume etc.
// during playback is possible (useful for fadeout).
//
// sound setup:
// OpenAL provides portable access to the underlying sound hardware, and
// falls back to software mixing if no acceleration is provided.
// we allow the user to specify the device to use (in case the default
// has problems) and maximum number of sources (to reduce mixing cost).
//
// performance:
// much effort has been invested in efficiency: all sound data is cached,
// so every open() after the first is effectively free. large sound files are
// streamed from disk to reduce load time and memory usage. hardware mixing
// resources are suballocated to avoid delays when starting to play.
// therefore, the user can confidently fire off hundreds of sound requests.
// finally, lengthy initialization steps are delayed until the sound engine
// is actually needed (i.e. upon first open()). perceived startup time is
// therefore reduced - the user sees e.g. our main menu earlier.
//
// terminology:
// "hardware voice" refers to mixing resources on the DSP. strictly
// speaking, we mean 'OpenAL source', but this term is more clear.
// voice ~= source, unless expensive effects (e.g. EAX) are enabled.
// note: software mixing usually doesn't have a fixed 'source' cap.
// "gain" is quantified volume. 1 is unattenuated, 0.5 corresponds to -6 dB,
// and 0 is silence. this can be set per-source as well as globally.
// "position" of a sound is within the app's coordinate system,
// the orientation of which is passed to snd_update.
// "importance" of a sound derives from the app-assigned priority
// (e.g. voiceover must not be skipped in favor of seagulls) and
// distance from the listener. it's calculated by our prioritizer.
// "virtual source" denotes a sound play request issued by the app.
// this is in contrast to an actual AL source, which will be mixed
// into the output channel. the most important VSrc receive an al_src.
// "sound instances" store playback parameters (e.g. position), and
// reference the (centrally cached) "sound data" that will be played.
2004-10-30 17:17:19 +02:00
//
// device enumeration
//
// prepare to enumerate all device names (this resets the list returned by
// snd_dev_next). return 0 on success, otherwise -1 (only if the requisite
// OpenAL extension isn't available). on failure, a "cannot enum device"
// message should be presented to the user, and snd_dev_set need not be
// called; OpenAL will use its default device.
// may be called each time the device list is needed.
extern int snd_dev_prepare_enum();
// return the next device name, or 0 if all have been returned.
// do not call unless snd_dev_prepare_enum succeeded!
// not thread-safe! (static data from snd_dev_prepare_enum is used)
extern const char* snd_dev_next();
//
// sound system setup
//
// tell OpenAL to use the specified device in future.
// name = 0 reverts to OpenAL's default choice, which will also
// be used if this routine is never called.
//
// the device name is typically taken from a config file at init-time;
// the snd_dev* enumeration routines below are used to present a list
// of choices to the user in the options screen.
//
// if OpenAL hasn't yet been initialized (i.e. no sounds have been opened),
// this just stores the device name for use when init does occur.
// note: we can't check now if it's invalid (if so, init will fail).
// otherwise, we shut OpenAL down (thereby stopping all sounds) and
// re-initialize with the new device. that's fairly time-consuming,
// so preferably call this routine before sounds are loaded.
//
// return 0 on success, or the status returned by OpenAL re-init.
extern int snd_dev_set(const char* alc_new_dev_name);
// set maximum number of voices to play simultaneously,
// to reduce mixing cost on low-end systems.
// return 0 on success, or 1 if limit was ignored
// (e.g. if higher than an implementation-defined limit anyway).
extern int snd_set_max_voices(uint cap);
// set amplitude modifier, which is effectively applied to all sounds.
// must be non-negative; 1 -> unattenuated, 0.5 -> -6 dB, 0 -> silence.
extern int snd_set_master_gain(float gain);
//
// sound instance
//
// open and return a handle to a sound instance.
//
// if <snd_fn> is a text file (extension ".txt"), it is assumed
// to be a definition file containing the sound file name and
// its gain (0.0 .. 1.0).
// otherwise, <snd_fn> is taken to be the sound file name and
// gain is set to the default of 1.0 (no attenuation).
//
// is_stream (default false) forces the sound to be opened as a stream:
// opening is faster, it won't be kept in memory, but only one instance
// can be open at a time.
extern Handle snd_open(const char* snd_fn, bool stream = false);
// close the sound <hs> and set hs to 0. if it was playing,
// it will be stopped. sounds are closed automatically when done
// playing; this is provided for completeness only.
extern int snd_free(Handle& hs);
// request the sound <hs> be played. once done playing, the sound is
// automatically closed (allows fire-and-forget play code).
// if no hardware voice is available, this sound may not be played at all,
// or in the case of looped sounds, start later.
// priority (min 0 .. max 1, default 0) indicates which sounds are
// considered more important; this is attenuated by distance to the
// listener (see snd_update).
extern int snd_play(Handle hs, float priority = 0.0f);
// change 3d position of the sound source.
// if relative (default false), (x,y,z) is treated as relative to the
// listener; otherwise, it is the position in world coordinates.
2004-10-30 17:17:19 +02:00
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
extern int snd_set_pos(Handle hs, float x, float y, float z, bool relative = false);
// change gain (amplitude modifier) of the sound source.
// must be non-negative; 1 -> unattenuated, 0.5 -> -6 dB, 0 -> silence.
2004-10-30 17:17:19 +02:00
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
extern int snd_set_gain(Handle hs, float gain);
// change pitch shift of the sound source.
// 1.0 means no change; each reduction by 50% equals a pitch shift of
// -12 semitones (one octave). zero is invalid.
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
extern int snd_set_pitch(Handle hs, float pitch);
// enable/disable looping on the sound source.
// used to implement variable-length sounds (e.g. while building).
2004-10-30 17:17:19 +02:00
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
//
// notes:
// - looping sounds are not discarded if they cannot be played for lack of
// a hardware voice at the moment play was requested.
// - once looping is again disabled and the sound has reached its end,
// the sound instance is freed automatically (as if never looped).
extern int snd_set_loop(Handle hs, bool loop);
//
// sound engine
//
// call before first snd_open if all sound is to be disabled.
// this is a quick'n dirty way of speeding up startup during development -
// the caller's sound code need not be touched.
//
// can call later to reactivate sound; all settings ever set will be applied,
// and subsequent sound load / play requests will work.
extern int snd_disable(bool disabled);
// perform housekeeping (e.g. streaming); call once a frame.
//
// additionally, if any parameter is non-NULL, we set the listener
// position, look direction, and up vector (in world coordinates).
extern int snd_update(const float* pos, const float* dir, const float* up);
// free all resources and shut down the sound system.
// call before h_mgr_shutdown.
extern void snd_shutdown();