/** * @file * * Audiere Sound System * Version 1.9.4 * (c) 2001-2003 Chad Austin * * This API uses principles explained at * http://aegisknight.org/cppinterface.html * * This code licensed under the terms of the LGPL. See doc/license.txt. * * * Note: When compiling this header in gcc, you may want to use the * -Wno-non-virtual-dtor flag to get rid of those annoying "class has * virtual functions but no virtual destructor" warnings. * * This file is structured as follows: * - includes, macro definitions, other general setup * - interface definitions * - DLL-safe entry points (not for general use) * - inline functions that use those entry points */ #ifndef AUDIERE_H #define AUDIERE_H #include #include #ifdef _MSC_VER #pragma warning(disable : 4786) #endif #ifndef __cplusplus #error Audiere requires C++ #endif // DLLs in Windows should use the standard (Pascal) calling convention #ifndef ADR_CALL #if defined(WIN32) || defined(_WIN32) #define ADR_CALL __stdcall #else #define ADR_CALL #endif #endif // Export functions from the DLL #ifndef ADR_DECL # if defined(WIN32) || defined(_WIN32) # ifdef AUDIERE_EXPORTS # define ADR_DECL __declspec(dllexport) # else # define ADR_DECL __declspec(dllimport) # endif # else # define ADR_DECL # endif #endif #define ADR_FUNCTION(ret) extern "C" ADR_DECL ret ADR_CALL #define ADR_METHOD(ret) virtual ret ADR_CALL namespace audiere { class RefCounted { protected: /** * Protected so users of refcounted classes don't use std::auto_ptr * or the delete operator. * * Interfaces that derive from RefCounted should define an inline, * empty, protected destructor as well. */ ~RefCounted() { } public: /** * Add a reference to the internal reference count. */ ADR_METHOD(void) ref() = 0; /** * Remove a reference from the internal reference count. When this * reaches 0, the object is destroyed. */ ADR_METHOD(void) unref() = 0; }; template class RefPtr { public: RefPtr(T* ptr = 0) { m_ptr = 0; *this = ptr; } RefPtr(const RefPtr& ptr) { m_ptr = 0; *this = ptr; } ~RefPtr() { if (m_ptr) { m_ptr->unref(); m_ptr = 0; } } RefPtr& operator=(T* ptr) { if (ptr != m_ptr) { if (m_ptr) { m_ptr->unref(); } m_ptr = ptr; if (m_ptr) { m_ptr->ref(); } } return *this; } RefPtr& operator=(const RefPtr& ptr) { *this = ptr.m_ptr; return *this; } T* operator->() const { return m_ptr; } T& operator*() const { return *m_ptr; } operator bool() const { return (m_ptr != 0); } T* get() const { return m_ptr; } private: T* m_ptr; }; template bool operator==(const RefPtr& a, const RefPtr& b) { return (a.get() == b.get()); } template bool operator==(const RefPtr& a, const T* b) { return (a.get() == b); } template bool operator==(const T* a, const RefPtr& b) { return (a == b.get()); } template bool operator!=(const RefPtr& a, const RefPtr& b) { return (a.get() != b.get()); } template bool operator!=(const RefPtr& a, const T* b) { return (a.get() != b); } template bool operator!=(const T* a, const RefPtr& b) { return (a != b.get()); } /** * A basic implementation of the RefCounted interface. Derive * your implementations from RefImplementation. */ template class RefImplementation : public Interface { protected: RefImplementation() { m_ref_count = 0; } /** * So the implementation can put its destruction logic in the destructor, * as natural C++ code does. */ virtual ~RefImplementation() { } public: void ADR_CALL ref() { ++m_ref_count; } void ADR_CALL unref() { if (--m_ref_count == 0) { delete this; } } private: int m_ref_count; }; /** * Represents a random-access file, usually stored on a disk. Files * are always binary: that is, they do no end-of-line * transformations. File objects are roughly analogous to ANSI C * FILE* objects. * * This interface is not synchronized. */ class File : public RefCounted { protected: ~File() { } public: /** * The different ways you can seek within a file. */ enum SeekMode { BEGIN, CURRENT, END, }; /** * Read size bytes from the file, storing them in buffer. * * @param buffer buffer to read into * @param size number of bytes to read * * @return number of bytes successfully read */ ADR_METHOD(int) read(void* buffer, int size) = 0; /** * Jump to a new position in the file, using the specified seek * mode. Remember: if mode is END, the position must be negative, * to seek backwards from the end of the file into its contents. * If the seek fails, the current position is undefined. * * @param position position relative to the mode * @param mode where to seek from in the file * * @return true on success, false otherwise */ ADR_METHOD(bool) seek(int position, SeekMode mode) = 0; /** * Get current position within the file. * * @return current position */ ADR_METHOD(int) tell() = 0; }; typedef RefPtr FilePtr; /// Storage formats for sample data. enum SampleFormat { SF_U8, ///< unsigned 8-bit integer [0,255] SF_S16, ///< signed 16-bit integer in host endianness [-32768,32767] }; /// Supported audio file formats. enum FileFormat { FF_AUTODETECT, FF_WAV, FF_OGG, FF_FLAC, FF_MP3, FF_MOD, FF_AIFF, FF_SPEEX, }; /** * Source of raw PCM samples. Sample sources have an intrinsic format * (@see SampleFormat), sample rate, and number of channels. They can * be read from or reset. * * Some sample sources are seekable. Seekable sources have two additional * properties: length and position. Length is read-only. * * This interface is not synchronized. */ class SampleSource : public RefCounted { protected: ~SampleSource() { } public: /** * Retrieve the number of channels, sample rate, and sample format of * the sample source. */ ADR_METHOD(void) getFormat( int& channel_count, int& sample_rate, SampleFormat& sample_format) = 0; /** * Read frame_count samples into buffer. buffer must be at least * |frame_count * GetSampleSize(format) * channel_count| bytes long. * * @param frame_count number of frames to read * @param buffer buffer to store samples in * * @return number of frames actually read */ ADR_METHOD(int) read(int frame_count, void* buffer) = 0; /** * Reset the sample source. This has the same effect as setPosition(0) * on a seekable source. On an unseekable source, it resets all internal * state to the way it was when the source was first created. */ ADR_METHOD(void) reset() = 0; /** * @return true if the stream is seekable, false otherwise */ ADR_METHOD(bool) isSeekable() = 0; /** * @return number of frames in the stream, or 0 if the stream is not * seekable */ ADR_METHOD(int) getLength() = 0; /** * Sets the current position within the sample source. If the stream * is not seekable, this method does nothing. * * @param position current position in frames */ ADR_METHOD(void) setPosition(int position) = 0; /** * Returns the current position within the sample source. * * @return current position in frames */ ADR_METHOD(int) getPosition() = 0; /** * @return true if the sample source is set to repeat */ ADR_METHOD(bool) getRepeat() = 0; /** * Sets whether the sample source should repeat or not. Note that not * all sample sources repeat by starting again at the beginning of the * sound. For example MOD files can contain embedded loop points. * * @param repeat true if the source should repeat, false otherwise */ ADR_METHOD(void) setRepeat(bool repeat) = 0; /// Returns number of metadata tags present in this sample source. ADR_METHOD(int) getTagCount() = 0; /** * Returns the key of the i'th tag in the source. If the tag is * "author=me", the key is "author". */ virtual const char* ADR_CALL getTagKey(int i) = 0; /** * Returns the value of the i'th tag in the source. If the tag is * "author=me", the value is "me". */ virtual const char* ADR_CALL getTagValue(int i) = 0; /** * Returns the type of the i'th tag in the source. The type is where * the tag comes from, i.e. "ID3v1", "ID3v2", or "vorbis". */ virtual const char* ADR_CALL getTagType(int i) = 0; }; typedef RefPtr SampleSourcePtr; /** * LoopPointSource is a wrapper around another SampleSource, providing * custom loop behavior. LoopPointSource maintains a set of links * within the sample stream and whenever the location of one of the links * (i.e. a loop point) is reached, the stream jumps to that link's target. * Each loop point maintains a count. Every time a loop point comes into * effect, the count is decremented. Once it reaches zero, that loop point * is temporarily disabled. If a count is not a positive value, it * cannot be disabled. Calling reset() resets all counts to their initial * values. * * Loop points only take effect when repeating has been enabled via the * setRepeat() method. * * Loop points are stored in sorted order by their location. Each one * has an index based on its location within the list. A loop point's * index will change if another is added before it. * * There is always one implicit loop point after the last sample that * points back to the first. That way, this class's default looping * behavior is the same as a standard SampleSource. This loop point * does not show up in the list. */ class LoopPointSource : public SampleSource { protected: ~LoopPointSource() { } public: /** * Adds a loop point to the stream. If a loop point at 'location' * already exists, the new one replaces it. Location and target are * clamped to the actual length of the stream. * * @param location frame where loop occurs * @param target frame to jump to after loop point is hit * @param loopCount number of times to execute this jump. */ ADR_METHOD(void) addLoopPoint( int location, int target, int loopCount) = 0; /** * Removes the loop point at index 'index' from the stream. * * @param index index of the loop point to remove */ ADR_METHOD(void) removeLoopPoint(int index) = 0; /** * Returns the number of loop points in this stream. */ ADR_METHOD(int) getLoopPointCount() = 0; /** * Retrieves information about a specific loop point. * * @param index index of the loop point * @param location frame where loop occurs * @param target loop point's target frame * @param loopCount number of times to loop from this particular point * * @return true if the index is valid and information is returned */ ADR_METHOD(bool) getLoopPoint( int index, int& location, int& target, int& loopCount) = 0; }; typedef RefPtr LoopPointSourcePtr; /** * A connection to an audio device. Multiple output streams are * mixed by the audio device to produce the final waveform that the * user hears. * * Each output stream can be independently played and stopped. They * also each have a volume from 0.0 (silence) to 1.0 (maximum volume). */ class OutputStream : public RefCounted { protected: ~OutputStream() { } public: /** * Start playback of the output stream. If the stream is already * playing, this does nothing. */ ADR_METHOD(void) play() = 0; /** * Stop playback of the output stream. If the stream is already * stopped, this does nothing. */ ADR_METHOD(void) stop() = 0; /** * @return true if the output stream is playing, false otherwise */ ADR_METHOD(bool) isPlaying() = 0; /** * Reset the sample source or buffer to the beginning. On seekable * streams, this operation is equivalent to setPosition(0). * * On some output streams, this operation can be moderately slow, as up to * several seconds of PCM buffer must be refilled. */ ADR_METHOD(void) reset() = 0; /** * Set whether the output stream should repeat. * * @param repeat true if the stream should repeat, false otherwise */ ADR_METHOD(void) setRepeat(bool repeat) = 0; /** * @return true if the stream is repeating */ ADR_METHOD(bool) getRepeat() = 0; /** * Sets the stream's volume. * * @param volume 0.0 = silence, 1.0 = maximum volume (default) */ ADR_METHOD(void) setVolume(float volume) = 0; /** * Gets the current volume. * * @return current volume of the output stream */ ADR_METHOD(float) getVolume() = 0; /** * Set current pan. * * @param pan -1.0 = left, 0.0 = center (default), 1.0 = right */ ADR_METHOD(void) setPan(float pan) = 0; /** * Get current pan. */ ADR_METHOD(float) getPan() = 0; /** * Set current pitch shift. * * @param shift can range from 0.5 to 2.0. default is 1.0. */ ADR_METHOD(void) setPitchShift(float shift) = 0; /** * Get current pitch shift. Defaults to 1.0. */ ADR_METHOD(float) getPitchShift() = 0; /** * @return true if the stream is seekable, false otherwise */ ADR_METHOD(bool) isSeekable() = 0; /** * @return number of frames in the stream, or 0 if the stream is not * seekable */ ADR_METHOD(int) getLength() = 0; /** * Sets the current position within the sample source. If the stream * is not seekable, this method does nothing. * * @param position current position in frames */ ADR_METHOD(void) setPosition(int position) = 0; /** * Returns the current position within the sample source. * * @return current position in frames */ ADR_METHOD(int) getPosition() = 0; }; typedef RefPtr OutputStreamPtr; /// An integral code representing a specific type of event. enum EventType { ET_STOP, ///< See StopEvent and StopCallback }; /// Base interface for event-specific data passed to callbacks. class Event : public RefCounted { protected: ~Event() { } public: /// Returns the EventType code for this event. ADR_METHOD(EventType) getType() = 0; }; typedef RefPtr EventPtr; /** * An event object that gets passed to implementations of StopCallback * when a stream has stopped playing. */ class StopEvent : public Event { protected: ~StopEvent() { } public: EventType ADR_CALL getType() { return ET_STOP; } /// A code representing the reason the stream stopped playback. enum Reason { STOP_CALLED, ///< stop() was called from an external source. STREAM_ENDED, ///< The stream reached its end. }; /** * @return Pointer to the OutputStream that stopped playback. */ ADR_METHOD(OutputStream*) getOutputStream() = 0; /** * @return Reason for the stop event. */ ADR_METHOD(Reason) getReason() = 0; }; typedef RefPtr StopEventPtr; /** * Base interface for all callbacks. See specific callback implementations * for descriptions. */ class Callback : public RefCounted { protected: ~Callback() { } public: /** * Returns the event type that this callback knows how to handle. */ ADR_METHOD(EventType) getType() = 0; /** * Actually executes the callback with event-specific data. This is * only called if event->getType() == this->getType(). */ ADR_METHOD(void) call(Event* event) = 0; }; typedef RefPtr CallbackPtr; /** * To listen for stream stopped events on a device, implement this interface * and call registerStopCallback() on the device, passing your * implementation. streamStopped() will be called whenever a stream on that * device stops playback. * * WARNING: StopCallback is called from another thread. Make sure your * callback is thread-safe. */ class StopCallback : public Callback { protected: ~StopCallback() { } public: EventType ADR_CALL getType() { return ET_STOP; } void ADR_CALL call(Event* event) { streamStopped(static_cast(event)); } /** * Called when a stream has stopped. * * @param event Information pertaining to the event. */ ADR_METHOD(void) streamStopped(StopEvent* event) = 0; }; typedef RefPtr StopCallbackPtr; /** * AudioDevice represents a device on the system which is capable * of opening and mixing multiple output streams. In Windows, * DirectSound is such a device. * * This interface is synchronized. update() and openStream() may * be called on different threads. */ class AudioDevice : public RefCounted { protected: ~AudioDevice() { } public: /** * Tell the device to do any internal state updates. Some devices * update on an internal thread. If that is the case, this method * does nothing. */ ADR_METHOD(void) update() = 0; /** * Open an output stream with a given sample source. If the sample * source ever runs out of data, the output stream automatically stops * itself. * * The output stream takes ownership of the sample source, even if * opening the output stream fails (in which case the source is * immediately deleted). * * @param source the source used to feed the output stream with samples * * @return new output stream if successful, 0 if failure */ ADR_METHOD(OutputStream*) openStream(SampleSource* source) = 0; /** * Open a single buffer with the specified PCM data. This is sometimes * more efficient than streaming and works on a larger variety of audio * devices. In some implementations, this may download the audio data * to the sound card's memory itself. * * @param samples Buffer containing sample data. openBuffer() does * not take ownership of the memory. The application * is responsible for freeing it. There must be at * least |frame_count * channel_count * * GetSampleSize(sample_format)| bytes in the buffer. * * @param frame_count Number of frames in the buffer. * * @param channel_count Number of audio channels. 1 = mono, 2 = stereo. * * @param sample_rate Number of samples per second. * * @param sample_format Format of samples in buffer. * * @return new output stream if successful, 0 if failure */ ADR_METHOD(OutputStream*) openBuffer( void* samples, int frame_count, int channel_count, int sample_rate, SampleFormat sample_format) = 0; /** * Gets the name of the audio device. For example "directsound" or "oss". * * @return name of audio device */ ADR_METHOD(const char*) getName() = 0; /** * Registers 'callback' to receive events. Callbacks can be * registered multiple times. */ ADR_METHOD(void) registerCallback(Callback* callback) = 0; /** * Unregisters 'callback' once. If it is registered multiple times, * each unregisterStopCallback call unregisters one of the instances. */ ADR_METHOD(void) unregisterCallback(Callback* callback) = 0; /// Clears all of the callbacks from the device. ADR_METHOD(void) clearCallbacks() = 0; }; typedef RefPtr AudioDevicePtr; /** * A readonly sample container which can open sample streams as iterators * through the buffer. This is commonly used in cases where a very large * sound effect is loaded once into memory and then streamed several times * to the audio device. This is more efficient memory-wise than loading * the effect multiple times. * * @see CreateSampleBuffer */ class SampleBuffer : public RefCounted { protected: ~SampleBuffer() { } public: /** * Return the format of the sample data in the sample buffer. * @see SampleSource::getFormat */ ADR_METHOD(void) getFormat( int& channel_count, int& sample_rate, SampleFormat& sample_format) = 0; /** * Get the length of the sample buffer in frames. */ ADR_METHOD(int) getLength() = 0; /** * Get a readonly pointer to the samples contained within the buffer. The * buffer is |channel_count * frame_count * GetSampleSize(sample_format)| * bytes long. */ virtual const void* ADR_CALL getSamples() = 0; /** * Open a seekable sample source using the samples contained in the * buffer. */ ADR_METHOD(SampleSource*) openStream() = 0; }; typedef RefPtr SampleBufferPtr; /** * Defines the type of SoundEffect objects. @see SoundEffect */ enum SoundEffectType { SINGLE, MULTIPLE, }; /** * SoundEffect is a convenience class which provides a simple * mechanism for basic sound playback. There are two types of sound * effects: SINGLE and MULTIPLE. SINGLE sound effects only allow * the sound to be played once at a time. MULTIPLE sound effects * always open a new stream to the audio device for each time it is * played (cleaning up or reusing old streams if possible). */ class SoundEffect : public RefCounted { protected: ~SoundEffect() { } public: /** * Trigger playback of the sound. If the SoundEffect is of type * SINGLE, this plays the sound if it isn't playing yet, and * starts it again if it is. If the SoundEffect is of type * MULTIPLE, play() simply starts playing the sound again. */ ADR_METHOD(void) play() = 0; /** * If the sound is of type SINGLE, stop the sound. If it is of * type MULTIPLE, stop all playing instances of the sound. */ ADR_METHOD(void) stop() = 0; /** * Sets the sound's volume. * * @param volume 0.0 = silence, 1.0 = maximum volume (default) */ ADR_METHOD(void) setVolume(float volume) = 0; /** * Gets the current volume. * * @return current volume of the output stream */ ADR_METHOD(float) getVolume() = 0; /** * Set current pan. * * @param pan -1.0 = left, 0.0 = center (default), 1.0 = right */ ADR_METHOD(void) setPan(float pan) = 0; /** * Get current pan. */ ADR_METHOD(float) getPan() = 0; /** * Set current pitch shift. * * @param shift can range from 0.5 to 2.0. default is 1.0. */ ADR_METHOD(void) setPitchShift(float shift) = 0; /** * Get current pitch shift. Defaults to 1.0. */ ADR_METHOD(float) getPitchShift() = 0; }; typedef RefPtr SoundEffectPtr; /** * Represents a device capable of playing CD audio. Internally, this * uses the MCI subsystem in windows and libcdaudio on other platforms. * MCI subsystem: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_multimedia_command_strings.asp * libcdaudio: http://cdcd.undergrid.net/libcdaudio/ */ class CDDevice : public RefCounted { protected: virtual ~CDDevice() { } public: /** * Returns the name of this CD Device, often just the device name * it was created with. */ virtual const char* ADR_CALL getName() = 0; /** * Returns the number of audio tracks on the disc. */ ADR_METHOD(int) getTrackCount() = 0; /** * Starts playback of the given track. If another track was * already playing, the previous track is stopped. IMPORTANT: Tracks are * indexed from 0 to getTrackCount() - 1. */ ADR_METHOD(void) play(int track) = 0; /** * Stops the playback, if the playback was already stopped, this * does nothing. */ ADR_METHOD(void) stop() = 0; /** * pauses playback of the track that is currently playing (if any) * This does nothing if no track is playing */ ADR_METHOD(void) pause() = 0; /** * Resumes playback of the track that is currently paused (if any). * This does nothing if no track is paused. */ ADR_METHOD(void) resume() = 0; /** * Returns true if the CD is currently playing a sound, this could * be through us, or through some other program. */ ADR_METHOD(bool) isPlaying() = 0; /** * Returns true if the drive contains a cd. This might be slow * on some systems, use with care. */ ADR_METHOD(bool) containsCD() = 0; /// Returns true if the door is open. ADR_METHOD(bool) isDoorOpen() = 0; /// Opens this device's door. ADR_METHOD(void) openDoor() = 0; /// Closes this device's door. ADR_METHOD(void) closeDoor() = 0; }; typedef RefPtr CDDevicePtr; /** * An opened MIDI song that can be played, stopped, and seeked within. * Uses MCI under Windows and is not supported in other platforms. */ class MIDIStream : public RefCounted { protected: virtual ~MIDIStream() { } public: /** * Begins playback of the song and does nothing if the song is already * playing. */ ADR_METHOD(void) play() = 0; /// Stops playback of the song and seeks to the beginning. ADR_METHOD(void) stop() = 0; /** * Stops playback of the song and does not change its current position. * A subsequent play() will resume the song where it left off. */ ADR_METHOD(void) pause() = 0; /// Returns true if the song is currently playing, false otherwise. ADR_METHOD(bool) isPlaying() = 0; /// Returns the length of the song in milliseconds. ADR_METHOD(int) getLength() = 0; /// Returns the current position of the song in milliseconds. ADR_METHOD(int) getPosition() = 0; /// Sets the current position of the song. ADR_METHOD(void) setPosition(int position) = 0; /// Returns true if this song is set to repeat. ADR_METHOD(bool) getRepeat() = 0; /// Sets whether the song should repeat on completion. Defaults to false. ADR_METHOD(void) setRepeat(bool repeat) = 0; }; typedef RefPtr MIDIStreamPtr; /** * A MIDIDevice must be instantiated in order to open MIDIStreams. */ class MIDIDevice : public RefCounted { protected: virtual ~MIDIDevice() { } public: /** * Returns the name of the device. */ ADR_METHOD(const char*) getName() = 0; /** * openStream() creates and returns a new MIDIStream object from the * file with the specified name, which then can be queried and played. * This method returns NULL if the stream cannot be opened. * * Note: MCI subsystem limitations do not allow loading MIDIStream * objects from an audiere File implementation. This may be addressed * in future versions of this API. */ ADR_METHOD(MIDIStream*) openStream(const char* filename) = 0; }; typedef RefPtr MIDIDevicePtr; /// PRIVATE API - for internal use only namespace hidden { // these are extern "C" so we don't mangle the names ADR_FUNCTION(const char*) AdrGetVersion(); /** * Returns a formatted string that lists the file formats that Audiere * supports. This function is DLL-safe. * * It is formatted in the following way: * * description1:ext1,ext2,ext3;description2:ext1,ext2,ext3 */ ADR_FUNCTION(const char*) AdrGetSupportedFileFormats(); /** * Returns a formatted string that lists the audio devices Audiere * supports. This function is DLL-safe. * * It is formatted in the following way: * * name1:description1;name2:description2;... */ ADR_FUNCTION(const char*) AdrGetSupportedAudioDevices(); ADR_FUNCTION(int) AdrGetSampleSize(SampleFormat format); ADR_FUNCTION(AudioDevice*) AdrOpenDevice( const char* name, const char* parameters); ADR_FUNCTION(SampleSource*) AdrOpenSampleSource( const char* filename, FileFormat file_format); ADR_FUNCTION(SampleSource*) AdrOpenSampleSourceFromFile( File* file, FileFormat file_format); ADR_FUNCTION(SampleSource*) AdrCreateTone(double frequency); ADR_FUNCTION(SampleSource*) AdrCreateSquareWave(double frequency); ADR_FUNCTION(SampleSource*) AdrCreateWhiteNoise(); ADR_FUNCTION(SampleSource*) AdrCreatePinkNoise(); ADR_FUNCTION(LoopPointSource*) AdrCreateLoopPointSource( SampleSource* source); ADR_FUNCTION(OutputStream*) AdrOpenSound( AudioDevice* device, SampleSource* source, bool streaming); ADR_FUNCTION(SampleBuffer*) AdrCreateSampleBuffer( void* samples, int frame_count, int channel_count, int sample_rate, SampleFormat sample_format); ADR_FUNCTION(SampleBuffer*) AdrCreateSampleBufferFromSource( SampleSource* source); ADR_FUNCTION(SoundEffect*) AdrOpenSoundEffect( AudioDevice* device, SampleSource* source, SoundEffectType type); ADR_FUNCTION(File*) AdrOpenFile( const char* name, bool writeable); ADR_FUNCTION(File*) AdrCreateMemoryFile( const void* buffer, int size); ADR_FUNCTION(const char*) AdrEnumerateCDDevices(); ADR_FUNCTION(CDDevice*) AdrOpenCDDevice( const char* name); // Parameters? ADR_FUNCTION(MIDIDevice*) AdrOpenMIDIDevice( const char* name); // Parameters? } /*-------- PUBLIC API FUNCTIONS --------*/ /** * Returns the Audiere version string. * * @return Audiere version information */ inline const char* GetVersion() { return hidden::AdrGetVersion(); } inline void SplitString( std::vector& out, const char* in, char delim) { out.clear(); while (*in) { const char* next = strchr(in, delim); if (next) { out.push_back(std::string(in, next)); } else { out.push_back(in); } in = (next ? next + 1 : ""); } } /// Describes a file format that Audiere supports. struct FileFormatDesc { /// Short description of format, such as "MP3 Files" or "Mod Files" std::string description; /// List of support extensions, such as {"mod", "it", "xm"} std::vector extensions; }; /// Populates a vector of FileFormatDesc structs. inline void GetSupportedFileFormats(std::vector& formats) { std::vector descriptions; SplitString(descriptions, hidden::AdrGetSupportedFileFormats(), ';'); formats.resize(descriptions.size()); for (unsigned i = 0; i < descriptions.size(); ++i) { const char* d = descriptions[i].c_str(); const char* colon = strchr(d, ':'); formats[i].description.assign(d, colon); SplitString(formats[i].extensions, colon + 1, ','); } } /// Describes a supported audio device. struct AudioDeviceDesc { /// Name of device, i.e. "directsound", "winmm", or "oss" std::string name; // Textual description of device. std::string description; }; /// Populates a vector of AudioDeviceDesc structs. inline void GetSupportedAudioDevices(std::vector& devices) { std::vector descriptions; SplitString(descriptions, hidden::AdrGetSupportedAudioDevices(), ';'); devices.resize(descriptions.size()); for (unsigned i = 0; i < descriptions.size(); ++i) { std::vector d; SplitString(d, descriptions[i].c_str(), ':'); devices[i].name = d[0]; devices[i].description = d[1]; } } /** * Get the size of a sample in a specific sample format. * This is commonly used to determine how many bytes a chunk of * PCM data will take. * * @return Number of bytes a single sample in the specified format * takes. */ inline int GetSampleSize(SampleFormat format) { return hidden::AdrGetSampleSize(format); } /** * Open a new audio device. If name or parameters are not specified, * defaults are used. Each platform has its own set of audio devices. * Every platform supports the "null" audio device. * * @param name name of audio device that should be used * @param parameters comma delimited list of audio-device parameters; * for example, "buffer=100,rate=44100" * * @return new audio device object if OpenDevice succeeds, and 0 in case * of failure */ inline AudioDevice* OpenDevice( const char* name = 0, const char* parameters = 0) { return hidden::AdrOpenDevice(name, parameters); } /** * Create a streaming sample source from a sound file. This factory simply * opens a default file from the system filesystem and calls * OpenSampleSource(File*). * * @see OpenSampleSource(File*) */ inline SampleSource* OpenSampleSource( const char* filename, FileFormat file_format = FF_AUTODETECT) { return hidden::AdrOpenSampleSource(filename, file_format); } /** * Opens a sample source from the specified file object. If the sound file * cannot be opened, this factory function returns 0. * * @note Some sound files support seeking, while some don't. * * @param file File object from which to open the decoder * @param file_format Format of the file to load. If FF_AUTODETECT, * Audiere will try opening the file in each format. * * @return new SampleSource if OpenSampleSource succeeds, 0 otherwise */ inline SampleSource* OpenSampleSource( const FilePtr& file, FileFormat file_format = FF_AUTODETECT) { return hidden::AdrOpenSampleSourceFromFile(file.get(), file_format); } /** * Create a tone sample source with the specified frequency. * * @param frequency Frequency of the tone in Hz. * * @return tone sample source */ inline SampleSource* CreateTone(double frequency) { return hidden::AdrCreateTone(frequency); } /** * Create a square wave with the specified frequency. * * @param frequency Frequency of the wave in Hz. * * @return wave sample source */ inline SampleSource* CreateSquareWave(double frequency) { return hidden::AdrCreateSquareWave(frequency); } /** * Create a white noise sample source. White noise is just random * data. * * @return white noise sample source */ inline SampleSource* CreateWhiteNoise() { return hidden::AdrCreateWhiteNoise(); } /** * Create a pink noise sample source. Pink noise is noise with equal * power distribution among octaves (logarithmic), not frequencies. * * @return pink noise sample source */ inline SampleSource* CreatePinkNoise() { return hidden::AdrCreatePinkNoise(); } /** * Create a LoopPointSource from a SampleSource. The SampleSource must * be seekable. If it isn't, or the source isn't valid, this function * returns 0. */ inline LoopPointSource* CreateLoopPointSource( const SampleSourcePtr& source) { return hidden::AdrCreateLoopPointSource(source.get()); } /** * Creates a LoopPointSource from a source loaded from a file. */ inline LoopPointSource* CreateLoopPointSource( const char* filename, FileFormat file_format = FF_AUTODETECT) { return CreateLoopPointSource(OpenSampleSource(filename, file_format)); } /** * Creates a LoopPointSource from a source loaded from a file. */ inline LoopPointSource* CreateLoopPointSource( const FilePtr& file, FileFormat file_format = FF_AUTODETECT) { return CreateLoopPointSource(OpenSampleSource(file, file_format)); } /** * Try to open a sound buffer using the specified AudioDevice and * sample source. If the specified sample source is seekable, it * loads it into memory and uses AudioDevice::openBuffer to create * the output stream. If the stream is not seekable, it uses * AudioDevice::openStream to create the output stream. This means * that certain file types must always be streamed, and therefore, * OpenSound will hold on to the file object. If you must guarantee * that the file on disk is no longer referenced, you must create * your own memory file implementation and load your data into that * before calling OpenSound. * * @param device AudioDevice in which to open the output stream. * * @param source SampleSource used to generate samples for the sound * object. OpenSound takes ownership of source, even * if it returns 0. (In that case, OpenSound immediately * deletes the SampleSource.) * * @param streaming If false or unspecified, OpenSound attempts to * open the entire sound into memory. Otherwise, it * streams the sound from the file. * * @return new output stream if successful, 0 otherwise */ inline OutputStream* OpenSound( const AudioDevicePtr& device, const SampleSourcePtr& source, bool streaming = false) { return hidden::AdrOpenSound(device.get(), source.get(), streaming); } /** * Calls OpenSound(AudioDevice*, SampleSource*) with a sample source * created via OpenSampleSource(const char*). */ inline OutputStream* OpenSound( const AudioDevicePtr& device, const char* filename, bool streaming = false, FileFormat file_format = FF_AUTODETECT) { SampleSource* source = OpenSampleSource(filename, file_format); return OpenSound(device, source, streaming); } /** * Calls OpenSound(AudioDevice*, SampleSource*) with a sample source * created via OpenSampleSource(File* file). */ inline OutputStream* OpenSound( const AudioDevicePtr& device, const FilePtr& file, bool streaming = false, FileFormat file_format = FF_AUTODETECT) { SampleSource* source = OpenSampleSource(file, file_format); return OpenSound(device, source, streaming); } /** * Create a SampleBuffer object using the specified samples and formats. * * @param samples Pointer to a buffer of samples used to initialize the * new object. If this is 0, the sample buffer contains * just silence. * * @param frame_count Size of the sample buffer in frames. * * @param channel_count Number of channels in each frame. * * @param sample_rate Sample rate in Hz. * * @param sample_format Format of each sample. @see SampleFormat. * * @return new SampleBuffer object */ inline SampleBuffer* CreateSampleBuffer( void* samples, int frame_count, int channel_count, int sample_rate, SampleFormat sample_format) { return hidden::AdrCreateSampleBuffer( samples, frame_count, channel_count, sample_rate, sample_format); } /** * Create a SampleBuffer object from a SampleSource. * * @param source Seekable sample source used to create the buffer. * If the source is not seekable, then the function * fails. * * @return new sample buffer if success, 0 otherwise */ inline SampleBuffer* CreateSampleBuffer(const SampleSourcePtr& source) { return hidden::AdrCreateSampleBufferFromSource(source.get()); } /** * Open a SoundEffect object from the given sample source and sound * effect type. @see SoundEffect * * @param device AudioDevice on which the sound is played. * * @param source The sample source used to feed the sound effect * with data. * * @param type The type of the sound effect. If type is MULTIPLE, * the source must be seekable. * * @return new SoundEffect object if successful, 0 otherwise */ inline SoundEffect* OpenSoundEffect( const AudioDevicePtr& device, const SampleSourcePtr& source, SoundEffectType type) { return hidden::AdrOpenSoundEffect(device.get(), source.get(), type); } /** * Calls OpenSoundEffect(AudioDevice*, SampleSource*, * SoundEffectType) with a sample source created from the filename. */ inline SoundEffect* OpenSoundEffect( const AudioDevicePtr& device, const char* filename, SoundEffectType type, FileFormat file_format = FF_AUTODETECT) { SampleSource* source = OpenSampleSource(filename, file_format); return OpenSoundEffect(device, source, type); } /** * Calls OpenSoundEffect(AudioDevice*, SampleSource*, * SoundEffectType) with a sample source created from the file. */ inline SoundEffect* OpenSoundEffect( const AudioDevicePtr& device, const FilePtr& file, SoundEffectType type, FileFormat file_format = FF_AUTODETECT) { SampleSource* source = OpenSampleSource(file, file_format); return OpenSoundEffect(device, source, type); } /** * Opens a default file implementation from the local filesystem. * * @param filename The name of the file on the local filesystem. * @param writeable Whether the writing to the file is allowed. */ inline File* OpenFile(const char* filename, bool writeable) { return hidden::AdrOpenFile(filename, writeable); } /** * Creates a File implementation that reads from a buffer in memory. * It stores a copy of the buffer that is passed in. * * The File object does not take ownership of the memory buffer. * When the file is destroyed, it will not free the memory. * * @param buffer Pointer to the beginning of the data. * @param size Size of the buffer in bytes. * * @return 0 if size is non-zero and buffer is null. Otherwise, * returns a valid File object. */ inline File* CreateMemoryFile(const void* buffer, int size) { return hidden::AdrCreateMemoryFile(buffer, size); } /** * Generates a list of available CD device names. * * @param devices A vector of strings to be filled. */ inline void EnumerateCDDevices(std::vector& devices) { const char* d = hidden::AdrEnumerateCDDevices(); while (d && *d) { devices.push_back(d); d += strlen(d) + 1; } } /** * Opens the specified CD playback device. * * @param device The filesystem device to be played. * e.g. Linux: "/dev/cdrom", Windows: "D:" * * @return 0 if opening device failed, valid CDDrive object otherwise. */ inline CDDevice* OpenCDDevice(const char* device) { return hidden::AdrOpenCDDevice(device); } /** * Opens the specified MIDI synthesizer device. * * @param device The name of the device. Unused for now. * * @return 0 if opening device failed, valid MIDIDevice object otherwise. */ inline MIDIDevice* OpenMIDIDevice(const char* device) { return hidden::AdrOpenMIDIDevice(device); } } #endif