/Multimedia/OpenTK/OggMusicData.cs
C# | 221 lines | 143 code | 26 blank | 52 comment | 15 complexity | 54d1197c9af37bb9fbf39a0973ff6962 MD5 | raw file
Possible License(s): Apache-2.0
- using System;
- using System.IO;
- using Delta.Multimedia.BaseOpenAL;
- using Delta.Utilities;
- using Delta.Utilities.Helpers;
- using OpenTK.Audio.OpenAL;
-
- namespace Delta.Multimedia.OpenTK
- {
- /// <summary>
- /// OGG music data
- /// </summary>
- internal class OggMusicData
- {
- #region Constants
- /// <summary>
- /// Size of a stream buffer in bytes.
- /// </summary>
- private const int BufferSize = 4096 * 8;
- #endregion
-
- #region Format (Public)
- /// <summary>
- /// Format
- /// </summary>
- public ALFormat Format
- {
- get;
- private set;
- }
- #endregion
-
- #region SampleRate (Public)
- /// <summary>
- /// Sample rate
- /// </summary>
- public int SampleRate
- {
- get;
- private set;
- }
- #endregion
-
- #region BufferHandles (Public)
- /// <summary>
- /// OpenAL buffers for music streaming.
- /// </summary>
- public int[] BufferHandles
- {
- get;
- private set;
- }
- #endregion
-
- #region Handle (Public)
- /// <summary>
- /// OpenAL source handle.
- /// </summary>
- public int Handle
- {
- get;
- private set;
- }
- #endregion
-
- #region Private
-
- #region oggFileStream (Private)
- /// <summary>
- /// The direct stream to the OGG file that we store for later disposing.
- /// </summary>
- private Stream oggFileStream;
- #endregion
-
- #region oggStream (Private)
- /// <summary>
- /// Decoding OGG input stream for loading the music data.
- /// </summary>
- private OggInputStream oggStream;
- #endregion
-
- #region contentPath (Private)
- /// <summary>
- /// The path to the music content file.
- /// </summary>
- private readonly string contentPath;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create OGG music data
- /// </summary>
- /// <param name="relativeFilePath">
- /// The path to the music content file.
- /// </param>
- public OggMusicData(string relativeFilePath)
- {
- contentPath = relativeFilePath;
- oggFileStream = FileHelper.OpenFileAsStream(contentPath);
- oggStream = new OggInputStream(oggFileStream);
-
- Format = oggStream.Format;
- SampleRate = oggStream.SampleRate;
-
- if (SampleRate == 0)
- {
- Log.Warning(
- "Loading Ogg music file '" + contentPath +
- "' failed, nothing found to play back, the file is probably not " +
- "in the ogg format! Try to upload it again and test with the " +
- "ContentManager to make sure the music file works correctly.");
- }
-
- BufferHandles = OpenALBinding.GenBuffers(2);
- Handle = OpenALBinding.GenSource();
- OpenALBinding.CheckError();
-
- if (Handle == MathHelper.InvalidIndex)
- {
- Log.Warning(
- "OggMusicData failed to load the music file '" + contentPath + "'");
- }
- }
- #endregion
-
- #region Rewind (Public)
- /// <summary>
- /// Rewind the music stream to the start position, used for looping and
- /// called when the music finished playing.
- /// </summary>
- public void Rewind()
- {
- oggFileStream.Close();
- oggFileStream = FileHelper.OpenFileAsStream(contentPath);
- oggStream = new OggInputStream(oggFileStream);
- }
- #endregion
-
- #region Stream (Public)
- /// <summary>
- /// Stream
- /// </summary>
- /// <param name="bufferHandle">The buffer handle.</param>
- /// <returns>
- /// amount of buffered bytes
- /// </returns>
- public bool Stream(int bufferHandle)
- {
- byte[] data = new byte[BufferSize];
- int size = 0;
- int result;
-
- while (size < BufferSize)
- {
- result = oggStream.Read(data, size, BufferSize - size);
- if (result > 0)
- {
- size += result;
- }
- else if (result < 0)
- {
- throw new Exception("Stream Error: " + result);
- }
- else
- {
- break;
- }
- }
-
- bool dataAvailable = (size > 0);
- if (dataAvailable)
- {
- OpenALBinding.BufferData(bufferHandle, Format, data, SampleRate);
- }
-
- return dataAvailable;
- }
- #endregion
-
- #region Dispose (Public)
- /// <summary>
- /// Dispose the source and all buffers of the ogg music.
- /// </summary>
- public void Dispose()
- {
- // Nothing to do if this was already disposed
- if (Handle == MathHelper.InvalidIndex)
- {
- return;
- }
-
- if (oggFileStream != null)
- {
- oggFileStream.Close();
- }
- oggStream = null;
-
- // Otherwise do the normal disposing. First stop the source playback
- OpenALBinding.StopSource(Handle);
- OpenALBinding.CheckError();
-
- // and empty the buffer queue.
- int queued = OpenALBinding.GetBuffersQueued(Handle);
- while (queued-- != 0)
- {
- OpenALBinding.SourceUnqueueBuffers(Handle, 1);
- }
-
- // Delete the music source
- OpenALBinding.DeleteSource(Handle);
- Handle = MathHelper.InvalidIndex;
-
- // And finally delete the buffers
- OpenALBinding.DeleteBuffers(BufferHandles);
- OpenALBinding.CheckError();
- }
- #endregion
- }
- }