Browse Source

Updated documentation for Audio API

BearishSun 9 years ago
parent
commit
7756e2673d

+ 23 - 2
Source/BansheeCore/Include/BsAudio.h

@@ -11,6 +11,7 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
+	/** Identifier for a device that can be used for playing audio. */
 	struct AudioDevice
 	{
 		WString name;
@@ -22,20 +23,38 @@ namespace BansheeEngine
 	public:
 		virtual ~Audio() { }
 
+		/** Sets global audio volume. In range [0, 1]. */
 		virtual void setVolume(float volume) = 0;
+
+		/** Returns global audio volume. In range [0, 1]. */
 		virtual float getVolume() const = 0;
 
+		/** Pauses audio reproduction globally. */
 		virtual void setPaused(bool paused) = 0;
-		virtual bool isPaused() const = 0;
 
-		virtual void update() = 0;
+		/** Checks is audio reproduction currently paused. */
+		virtual bool isPaused() const = 0;
 
+		/** Changes the device on which is the audio played back on. */
 		virtual void setActiveDevice(const AudioDevice& device) = 0;
+
+		/** Retrieves the identifier of the device that the audio is currently being played back on. */
 		virtual AudioDevice getActiveDevice() const = 0;
 		
+		/** Returns the default audio device identifier. */
 		virtual AudioDevice getDefaultDevice() const = 0;
+
+		/** Returns a list of all available audio devices. */
 		virtual const Vector<AudioDevice>& getAllDevices() const = 0;
 
+		/** @name Internal
+		 *  @{
+		 */
+
+		/** Called once per frame. Queues streaming audio requests. */
+		virtual void _update() = 0;
+
+		/** @} */
 	protected:
 		friend class AudioClip;
 		friend class AudioListener;
@@ -53,8 +72,10 @@ namespace BansheeEngine
 		virtual SPtr<AudioClip> createClip(const SPtr<DataStream>& samples, UINT32 streamSize, UINT32 numSamples,
 			const AUDIO_CLIP_DESC& desc) = 0;
 
+		/** Creates a new AudioListener. */
 		virtual SPtr<AudioListener> createListener() = 0;
 
+		/** Creates a new AudioSource. */
 		virtual SPtr<AudioSource> createSource() = 0;
 	};
 

+ 42 - 1
Source/BansheeCore/Include/BsAudioClip.h

@@ -77,13 +77,36 @@ namespace BansheeEngine
 	public:
 		virtual ~AudioClip() { }
 
+		/** Returns the size of a single sample, in bits. */
 		UINT32 getBitDepth() const { return mDesc.bitDepth; }
+		
+		/** Returns how many samples per second is the audio encoded in. */
 		UINT32 getFrequency() const { return mDesc.frequency; }
+
+		/** Returns the number of channels provided by the clip. */
 		UINT32 getNumChannels() const { return mDesc.numChannels; }
+
+		/** 
+		 * Returns in which format is audio data stored in. 
+		 *
+		 * @see	AudioFormat
+		 */
 		AudioFormat getFormat() const { return mDesc.format; }
+
+		/** 
+		 * Returns how is the audio data read/decoded. 
+		 *
+		 * @see	AudioReadMode
+		 */
 		AudioReadMode getReadMode() const { return mDesc.readMode; }
+
+		/** Returns the length of the audio clip, in seconds. */
 		float getLength() const { return mLength; }
+
+		/** Returns the total number of samples in the clip (includes all channels). */
 		UINT32 getNumSamples() const { return mNumSamples; }
+
+		/** Determines will the clip be played a spatial 3D sound, or as a normal sound (for example music). */
 		bool is3D() const { return mDesc.is3D; }
 
 		/** 
@@ -110,7 +133,19 @@ namespace BansheeEngine
 		 */
 		virtual void seekSamples(UINT32 offset) = 0;
 
-		static HAudioClip create(UINT32 streamSize, UINT32 numSamples, const AUDIO_CLIP_DESC& desc);
+		/**
+		 * Creates a new AudioClip and populates it with provided samples.
+		 *
+		 * @param[in]	samples		Data streams containing the samples to load. Data will be read starting from the current
+		 *							position in the stream. The samples should be in audio format as specified in the 
+		 *							@p desc parameter.
+		 * @param[in]	streamSize	Number of bytes to read from the @p samples stream.
+		 * @param[in]	numSamples	Total number of samples (including all channels).
+		 * @param[in]	desc		Descriptor containing meta-data for the provided samples.
+		 *
+		 * @note	If the provided samples are in PCM format, they should be unsigned for 8-bit data, and signed for
+		 *			higher bit depths.
+		 */
 		static HAudioClip create(const SPtr<DataStream>& samples, UINT32 streamSize, UINT32 numSamples,
 			const AUDIO_CLIP_DESC& desc); // Note that ownership of stream is taken by the AudioClip
 
@@ -119,6 +154,7 @@ namespace BansheeEngine
 		 *  @{
 		 */
 
+		/** Creates a new AudioClip without initializing it. Use create() for normal use. */
 		static SPtr<AudioClip> _createPtr(const SPtr<DataStream>& samples, UINT32 streamSize, UINT32 numSamples, 
 			const AUDIO_CLIP_DESC& desc);
 
@@ -148,6 +184,11 @@ namespace BansheeEngine
 		static RTTITypeBase* getRTTIStatic();
 		RTTITypeBase* getRTTI() const override;
 
+		/** 
+		 * Creates an AudioClip with no samples. You must populate its data manually followed by a call to initialize().
+		 *
+		 * @note	For serialization use only.
+		 */
 		static SPtr<AudioClip> createEmpty();
 	};
 

+ 15 - 0
Source/BansheeCore/Include/BsAudioClipImportOptions.h

@@ -16,16 +16,31 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT AudioClipImportOptions : public ImportOptions
 	{
 	public:
+		/** Returns the audio format to import the audio clip as. */
 		AudioFormat getFormat() const { return mFormat; }
+
+		/** Sets the audio format to import the audio clip as. */
 		void setFormat(AudioFormat format) { mFormat = format; }
 
+		/** Returns read mode that determines how is audio data loaded into memory. */
 		AudioReadMode getReadMode() const { return mReadMode; }
+
+		/** Sets read mode that determines how is audio data loaded into memory. */
 		void setReadMode(AudioReadMode readMode) { mReadMode = readMode; }
 
+		/** Checks should the clip be played as spatial (3D) audio or as normal audio. */
 		bool getIs3D() const { return mIs3D; }
+
+		/** 
+		 * Sets whether the clip should be played as spatial (3D) audio or as normal audio. 3D clips will be converted
+		 * to mono on import.
+		 */
 		void setIs3D(bool is3d) { mIs3D = is3d; }
 
+		/** Returns the size of a single sample in bits. */
 		UINT32 getBitDepth() const { return mBitDepth; }
+
+		/** Sets the size of a single sample in bits. The clip will be converted to this bit depth on import. */
 		void setBitDepth(UINT32 bitDepth) { mBitDepth = bitDepth; }
 
 		// Note: Add options to resample to a different frequency, reduce/increase bit depth

+ 17 - 0
Source/BansheeCore/Include/BsAudioListener.h

@@ -11,23 +11,40 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
+	/** 
+	 * Represents a listener that hears audio sources. For spatial audio the volume and pitch of played audio is determined
+	 * by the distance, orientation and velocity differences between the source and the listener.
+	 */
 	class BS_CORE_EXPORT AudioListener
 	{
 	public:
 		virtual ~AudioListener() {}
 
+		/** Sets the position of the listener in world space. */
 		virtual void setPosition(const Vector3& position);
+
+		/** Retrieves the position of the listener in world space. */
 		Vector3 getPosition() const { return mPosition; }
 
+		/** Sets the forward direction of the listener in world space. */
 		virtual void setDirection(const Vector3& direction);
+
+		/** Retrieves the forward direction of the listener in world space. */
 		Vector3 getDirection() const { return mDirection; }
 
+		/** Sets the up direction of the listener in world space. */
 		virtual void setUp(const Vector3& up);
+
+		/** Retrieves the up direction of the listener in world space. */
 		Vector3 getUp() const { return mUp; }
 
+		/** Sets the velocity of the listener. */
 		virtual void setVelocity(const Vector3& velocity);
+
+		/** Retrieves the velocity of the listener. */
 		Vector3 getVelocity() const { return mVelocity; }
 
+		/** Creates a new audio listener. */
 		static SPtr<AudioListener> create();
 
 	protected:

+ 67 - 4
Source/BansheeCore/Include/BsAudioSource.h

@@ -11,51 +11,114 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
+	/** Valid states for AudioSource. */
 	enum class AudioSourceState
 	{
-		Playing,
-		Paused,
-		Stopped
+		Playing, /**< Source is currently playing. */
+		Paused, /**< Source is currently paused (play will resume from paused point). */
+		Stopped /**< Source is currently stopped (play will resume from start). */
 	};
 
+	/** 
+	 * Represents a source for emitting audio. Audio can be played spatially (gun shot), or normally (music). Each audio
+	 * source must have an AudioClip to play-back, and it can also have a position in the case of spatial (3D) audio. 
+	 *
+	 * Whether or not an audio source is spatial is controlled by the assigned AudioClip. The volume and the pitch of a
+	 * spatial audio source is controlled by its position and the AudioListener's position/direction/Velocity.
+	 */
 	class BS_CORE_EXPORT AudioSource
 	{
 	public:
 		virtual ~AudioSource() { }
 
+		/** Sets the audio clip to play. */
 		virtual void setClip(const HAudioClip& clip);
+
+		/** Returns the attached audio clip. */
 		HAudioClip getClip() const { return mAudioClip; }
 
+		/** Sets the world position of the source. Only relevant for spatial (3D) sources. */
 		virtual void setPosition(const Vector3& position);
+
+		/** Returns the world position of the source. Only relevant for spatial (3D) sources. */
 		Vector3 getPosition() const { return mPosition; }
 
+		/** Sets the velocity of the source. Only relevant for spatial (3D) sources. */
 		virtual void setVelocity(const Vector3& velocity);
+
+		/** Gets the velocity of the source. Only relevant for spatial (3D) sources. */
 		Vector3 getVelocity() const { return mVelocity; }
 
-		virtual void setVolume(float volume); // [0, 1] range
+		/** Sets the volume of the audio source, in [0, 1] range. */
+		virtual void setVolume(float volume);
+
+		/** Retrieves the volume of the audio source, in [0, 1] range. */
 		float getVolume() const { return mVolume; }
 
+		/** Sets the pitch of the audio source. */
 		virtual void setPitch(float pitch);
+
+		/** Gets the pitch of the audio source. */
 		float getPitch() const { return mPitch; }
 
+		/** Sets whether the audio clip should loop when it finishes playing. */
 		virtual void setIsLooping(bool loop);
+
+		/** Gets whether the audio clip should loop when it finishes playing. */
 		bool getIsLooping() const { return mLoop; }
 
+		/** 
+		 * Sets the priority of the audio source. If more audio sources are playing than supported by the hardware, some
+		 * might get disabled. By setting a higher priority the audio source is guaranteed to be disabled after sources
+		 * with lower priority.
+		 */
 		virtual void setPriority(UINT32 priority);
+
+		/**
+		 * Gets the priority of the audio source. 
+		 *
+		 * @see	setPriority
+		 */
 		UINT32 getPriority() const { return mPriority; }
 
+		/** 
+		 * Returns the minimum distance at which audio attenuation starts. When the listener is closer to the source
+		 * than this value, audio is heard at full volume. Once farther away the audio starts attenuating.
+		 */
 		virtual void setMinDistance(float distance);
+
+		/** 
+		 * Gets the minimum distance at which audio attenuation starts. 
+		 *
+		 * @see	setMinDistance
+		 */
 		float getMinDistance() const { return mMinDistance; }
 
+		/**
+		 * Sets attenuation that controls how quickly does audio volume drop off as the listener moves further from the 
+		 * source.
+		 */
 		virtual void setAttenuation(float attenuation);
+
+		/** 
+		 * Gets attenuation that controls how quickly does audio volume drop off as the listener moves further from the 
+		 * source.
+		 */
 		float getAttenuation() const { return mAttenuation; }
 
+		/** Starts playing the currently assigned audio clip. */
 		virtual void play();
+
+		/** Pauses the audio playback. */
 		virtual void pause();
+
+		/** Stops audio playback, rewinding it to the start. */
 		virtual void stop();
 
+		/** Returns the current state of the audio playback (playing/paused/stopped). */
 		AudioSourceState getState() const { return mState; }
 
+		/** Creates a new audio source. */
 		static SPtr<AudioSource> create();
 
 	protected:

+ 0 - 5
Source/BansheeCore/Source/BsAudioClip.cpp

@@ -25,11 +25,6 @@ namespace BansheeEngine
 		Resource::initialize();
 	}
 
-	HAudioClip AudioClip::create(UINT32 streamSize, UINT32 numSamples, const AUDIO_CLIP_DESC& desc)
-	{
-		return static_resource_cast<AudioClip>(gResources()._createResourceHandle(_createPtr(nullptr, streamSize, numSamples, desc)));
-	}
-
 	HAudioClip AudioClip::create(const SPtr<DataStream>& samples, UINT32 streamSize, UINT32 numSamples, const AUDIO_CLIP_DESC& desc)
 	{
 		return static_resource_cast<AudioClip>(gResources()._createResourceHandle(_createPtr(samples, streamSize, numSamples, desc)));

+ 1 - 1
Source/BansheeCore/Source/BsCoreApplication.cpp

@@ -218,7 +218,7 @@ namespace BansheeEngine
 			preUpdate();
 
 			PROFILE_CALL(gCoreSceneManager()._update(), "SceneManager");
-			gAudio().update();
+			gAudio()._update();
 			gPhysics().update();
 
 			// Update plugins

+ 21 - 1
Source/BansheeOpenAudio/Include/BsOAAudio.h

@@ -12,6 +12,7 @@ namespace BansheeEngine
 	 *  @{
 	 */
 	
+	/** Global manager for the audio implementation using OpenAL as the backend. */
 	class BS_OA_EXPORT OAAudio : public Audio
 	{
 	public:
@@ -31,7 +32,7 @@ namespace BansheeEngine
 		bool isPaused() const override;
 
 		/** @copydoc Audio::update */
-		void update() override;
+		void _update() override;
 
 		/** @copydoc Audio::setActiveDevice */
 		void setActiveDevice(const AudioDevice& device) override;
@@ -49,16 +50,27 @@ namespace BansheeEngine
 		 *  @{
 		 */
 
+		/** Checks is a specific OpenAL extension supported. */
 		bool _isExtensionSupported(const String& extension) const;
 
+		/** Registers a new AudioListener. Should be called on listener creation. */
 		void _registerListener(OAAudioListener* listener);
+
+		/** Unregisters an existing AudioListener. Should be called before listener destruction. */
 		void _unregisterListener(OAAudioListener* listener);
 
+		/** Registers a new AudioSource. Should be called on source creation. */
 		void _registerSource(OAAudioSource* source);
+
+		/** Unregisters an existing AudioSource. Should be called before source destruction. */
 		void _unregisterSource(OAAudioSource* source);
 
+		/** Returns a list of all OpenAL contexts. Each listener has its own context. */
 		const Vector<ALCcontext*>& _getContexts() const { return mContexts; }
 
+		/** Returns an OpenAL context assigned to the provided listener. */
+		ALCcontext* _getContext(const OAAudioListener* listener) const;
+
 		/** @} */
 
 	private:
@@ -72,7 +84,15 @@ namespace BansheeEngine
 		/** @copydoc Audio::createSource */
 		SPtr<AudioSource> createSource() override;
 
+		/** 
+		 * Delete all existing contexts and rebuild them according to the listener list. All audio sources will be rebuilt
+		 * as well.
+		 *
+		 * This should be called when listener count changes, or audio device is changed.
+		 */
 		void rebuildContexts();
+
+		/** Delete all existing OpenAL contexts. */
 		void clearContexts();
 
 		float mVolume;

+ 1 - 0
Source/BansheeOpenAudio/Include/BsOAAudioClip.h

@@ -12,6 +12,7 @@ namespace BansheeEngine
 	 *  @{
 	 */
 	
+	/** OpenAudio implementation of an AudioClip. */
 	class BS_OA_EXPORT OAAudioClip : public AudioClip
 	{
 	public:

+ 11 - 0
Source/BansheeOpenAudio/Include/BsOAAudioListener.h

@@ -11,6 +11,7 @@ namespace BansheeEngine
 	 *  @{
 	 */
 	
+	/** OpenAL implementation of an AudioListener. */
 	class BS_OA_EXPORT OAAudioListener : public AudioListener
 	{
 	public:
@@ -32,12 +33,22 @@ namespace BansheeEngine
 	private:
 		friend class OAAudio;
 
+		/** Re-applies stored properties to the listener. */
 		void rebuild();
 
+		/** Returns forward and up direction as a single vector. */
 		inline std::array<float, 6> getOrientation() const;
+
+		/** Updates internal position of the listener. */
 		inline void updatePosition();
+
+		/** Updates internal forward and up directions of the listener. */
 		inline void updateOrientation(const std::array<float, 6>& orientation);
+
+		/** Updates internal velocity of the listener. */
 		inline void updateVelocity();
+
+		/** Updates internal volume of the listener. */
 		inline void updateVolume(float volume);
 	};
 

+ 4 - 0
Source/BansheeOpenAudio/Include/BsOAAudioSource.h

@@ -11,6 +11,7 @@ namespace BansheeEngine
 	 *  @{
 	 */
 	
+	/** OpenAL implementation of an AudioSource. */
 	class BS_OA_EXPORT OAAudioSource : public AudioSource
 	{
 	public:
@@ -56,7 +57,10 @@ namespace BansheeEngine
 	private:
 		friend class OAAudio;
 
+		/** Destroys the internal representation of the audio source. */
 		void clear();
+
+		/** Rebuilds the internal representation of an audio source. */
 		void rebuild();
 
 		Vector<UINT32> mSourceIDs;

+ 1 - 0
Source/BansheeOpenAudio/Include/BsOAFLACReader.h

@@ -42,6 +42,7 @@ namespace BansheeEngine
 		/** @copydoc OAFileReader::isValid */
 		bool isValid(const SPtr<DataStream>& stream) override;
 	private:
+		/** Cleans up the FLAC decoder. */
 		void close();
 
 		FLAC__StreamDecoder* mDecoder;

+ 38 - 1
Source/BansheeOpenAudio/Include/BsOAOggVorbisWriter.h

@@ -18,14 +18,51 @@ namespace BansheeEngine
 		OAOggVorbisWriter();
 		~OAOggVorbisWriter();
 
+		/** 
+		 * Sets up the writer. Should be called before calling write(). 
+		 *
+		 * @param[in]	writeCallback	Callback that will be triggered when the writer is ready to output some data.
+		 *								The callback should copy the provided data into its own buffer.
+		 * @param[in]	sampleRate		Determines how many samples per second the written data will have.
+		 * @param[in]	bitDepth		Determines the size of a single sample, in bits.
+		 * @param[in]	numChannels		Determines the number of audio channels. Channel data will be output interleaved
+		 *								in the output buffer.
+		 */
 		bool open(std::function<void(UINT8*, UINT32)> writeCallback, UINT32 sampleRate, UINT32 bitDepth, UINT32 numChannels);
 
-		void write(UINT8* samples, UINT32 numSamples); // 8-bit samples should be unsigned, but higher bit depths signed
+		/** 
+		 * Writes a new set of samples and converts them to Ogg Vorbis. 
+		 *
+		 * @param[in]	samples		Samples in PCM format. 8-bit samples should be unsigned, but higher bit depths signed.
+		 *							Each sample is assumed to be the bit depth that was provided to the open() method.
+		 * @param[in]	numSamples	Number of samples to encode.
+		 */
+		void write(UINT8* samples, UINT32 numSamples);
+
+		/** 
+		 * Flushes the last of the data into the write buffer (triggers the write callback). This is called automatically
+		 * when the writer is closed or goes out of scope.
+		 */
 		void flush();
+
+		/** 
+		 * Closes the encoder and flushes the last of the data into the write buffer (triggers the write callback). This is
+		 * called automatically when the writer goes out of scope.
+		 */
 		void close();
 
+		/** 
+		 * Helper method that allows you to quickly convert PCM to Ogg Vorbis data. 
+		 * 
+		 * @param[in]	samples		Buffer containing samples in PCM format. 8-bit samples should be unsigned, but higher
+		 *							bit depths signed.
+		 * @param[in]	info		Meta-data describing the provided samples.
+		 * @param[out]	size		Number of bytes written to the output buffer.
+		 * @return					Buffer containing the encoded samples, allocated using the general allocator.
+		 */
 		static UINT8* PCMToOggVorbis(UINT8* samples, const AudioFileInfo& info, UINT32& size);
 	private:
+		/** Writes Vorbis blocks into Ogg packets. */
 		void writeBlocks();
 
 		static const UINT32 BUFFER_SIZE = 4096;

+ 1 - 0
Source/BansheeOpenAudio/Include/BsOAWaveReader.h

@@ -29,6 +29,7 @@ namespace BansheeEngine
 		/** @copydoc OAFileReader::isValid */
 		bool isValid(const SPtr<DataStream>& stream) override;
 	private:
+		/** Parses the WAVE header and output audio file meta-data. Returns false if the header is not valid. */
 		bool parseHeader(AudioFileInfo& info);
 
 		SPtr<DataStream> mStream;

+ 24 - 4
Source/BansheeOpenAudio/Source/BsOAAudio.cpp

@@ -95,7 +95,7 @@ namespace BansheeEngine
 		return false;
 	}
 
-	void OAAudio::update()
+	void OAAudio::_update()
 	{
 		// TODO
 	}
@@ -155,6 +155,26 @@ namespace BansheeEngine
 		mSources.erase(source);
 	}
 
+	ALCcontext* OAAudio::_getContext(const OAAudioListener* listener) const
+	{
+		if (mListeners.size() > 0)
+		{
+			assert(mListeners.size() == mContexts.size());
+
+			UINT32 numContexts = (UINT32)mContexts.size();
+			for(UINT32 i = 0; i < numContexts; i++)
+			{
+				if (mListeners[i] == listener)
+					return mContexts[i];
+			}
+		}
+		else
+			return mContexts[0];
+
+		LOGERR("Unable to find context for an audio listener.");
+		return nullptr;
+	}
+
 	SPtr<AudioClip> OAAudio::createClip(const SPtr<DataStream>& samples, UINT32 streamSize, UINT32 numSamples,
 		const AUDIO_CLIP_DESC& desc)
 	{
@@ -173,14 +193,14 @@ namespace BansheeEngine
 
 	void OAAudio::rebuildContexts()
 	{
+		for (auto& source : mSources)
+			source->clear();
+
 		clearContexts();
 
 		UINT32 numListeners = (UINT32)mListeners.size();
 		UINT32 numContexts = numListeners > 1 ? numListeners : 1;
 
-		for (auto& source : mSources)
-			source->clear();
-
 		for(UINT32 i = 0; i < numContexts; i++)
 		{
 			ALCcontext* context = alcCreateContext(mDevice, nullptr);

+ 10 - 10
Source/BansheeOpenAudio/Source/BsOAAudioListener.cpp

@@ -77,21 +77,21 @@ namespace BansheeEngine
 
 	void OAAudioListener::rebuild()
 	{
-		auto& contexts = gOAAudio()._getContexts();
-
+		auto contexts = gOAAudio()._getContexts();
+		
 		float globalVolume = gAudio().getVolume();
 		std::array<float, 6> orientation = getOrientation();
 
-		for (auto& context : contexts)
+		if (contexts.size() > 1) // If only one context is available it is guaranteed it is always active, so we can avoid setting it
 		{
-			if (contexts.size() > 1) // If only one context is available it is guaranteed it is always active, so we can avoid setting it
-				alcMakeContextCurrent(context);
-
-			updatePosition();
-			updateOrientation(orientation);
-			updateVelocity();
-			updateVolume(globalVolume);
+			auto context = gOAAudio()._getContext(this);
+			alcMakeContextCurrent(context);
 		}
+
+		updatePosition();
+		updateOrientation(orientation);
+		updateVelocity();
+		updateVolume(globalVolume);
 	}
 
 	std::array<float, 6> OAAudioListener::getOrientation() const