PageRenderTime 48ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  1. using System;
  2. using System.IO;
  3. using Delta.Multimedia.BaseOpenAL;
  4. using Delta.Utilities;
  5. using Delta.Utilities.Helpers;
  6. using OpenTK.Audio.OpenAL;
  7. namespace Delta.Multimedia.OpenTK
  8. {
  9. /// <summary>
  10. /// OGG music data
  11. /// </summary>
  12. internal class OggMusicData
  13. {
  14. #region Constants
  15. /// <summary>
  16. /// Size of a stream buffer in bytes.
  17. /// </summary>
  18. private const int BufferSize = 4096 * 8;
  19. #endregion
  20. #region Format (Public)
  21. /// <summary>
  22. /// Format
  23. /// </summary>
  24. public ALFormat Format
  25. {
  26. get;
  27. private set;
  28. }
  29. #endregion
  30. #region SampleRate (Public)
  31. /// <summary>
  32. /// Sample rate
  33. /// </summary>
  34. public int SampleRate
  35. {
  36. get;
  37. private set;
  38. }
  39. #endregion
  40. #region BufferHandles (Public)
  41. /// <summary>
  42. /// OpenAL buffers for music streaming.
  43. /// </summary>
  44. public int[] BufferHandles
  45. {
  46. get;
  47. private set;
  48. }
  49. #endregion
  50. #region Handle (Public)
  51. /// <summary>
  52. /// OpenAL source handle.
  53. /// </summary>
  54. public int Handle
  55. {
  56. get;
  57. private set;
  58. }
  59. #endregion
  60. #region Private
  61. #region oggFileStream (Private)
  62. /// <summary>
  63. /// The direct stream to the OGG file that we store for later disposing.
  64. /// </summary>
  65. private Stream oggFileStream;
  66. #endregion
  67. #region oggStream (Private)
  68. /// <summary>
  69. /// Decoding OGG input stream for loading the music data.
  70. /// </summary>
  71. private OggInputStream oggStream;
  72. #endregion
  73. #region contentPath (Private)
  74. /// <summary>
  75. /// The path to the music content file.
  76. /// </summary>
  77. private readonly string contentPath;
  78. #endregion
  79. #endregion
  80. #region Constructors
  81. /// <summary>
  82. /// Create OGG music data
  83. /// </summary>
  84. /// <param name="relativeFilePath">
  85. /// The path to the music content file.
  86. /// </param>
  87. public OggMusicData(string relativeFilePath)
  88. {
  89. contentPath = relativeFilePath;
  90. oggFileStream = FileHelper.OpenFileAsStream(contentPath);
  91. oggStream = new OggInputStream(oggFileStream);
  92. Format = oggStream.Format;
  93. SampleRate = oggStream.SampleRate;
  94. if (SampleRate == 0)
  95. {
  96. Log.Warning(
  97. "Loading Ogg music file '" + contentPath +
  98. "' failed, nothing found to play back, the file is probably not " +
  99. "in the ogg format! Try to upload it again and test with the " +
  100. "ContentManager to make sure the music file works correctly.");
  101. }
  102. BufferHandles = OpenALBinding.GenBuffers(2);
  103. Handle = OpenALBinding.GenSource();
  104. OpenALBinding.CheckError();
  105. if (Handle == MathHelper.InvalidIndex)
  106. {
  107. Log.Warning(
  108. "OggMusicData failed to load the music file '" + contentPath + "'");
  109. }
  110. }
  111. #endregion
  112. #region Rewind (Public)
  113. /// <summary>
  114. /// Rewind the music stream to the start position, used for looping and
  115. /// called when the music finished playing.
  116. /// </summary>
  117. public void Rewind()
  118. {
  119. oggFileStream.Close();
  120. oggFileStream = FileHelper.OpenFileAsStream(contentPath);
  121. oggStream = new OggInputStream(oggFileStream);
  122. }
  123. #endregion
  124. #region Stream (Public)
  125. /// <summary>
  126. /// Stream
  127. /// </summary>
  128. /// <param name="bufferHandle">The buffer handle.</param>
  129. /// <returns>
  130. /// amount of buffered bytes
  131. /// </returns>
  132. public bool Stream(int bufferHandle)
  133. {
  134. byte[] data = new byte[BufferSize];
  135. int size = 0;
  136. int result;
  137. while (size < BufferSize)
  138. {
  139. result = oggStream.Read(data, size, BufferSize - size);
  140. if (result > 0)
  141. {
  142. size += result;
  143. }
  144. else if (result < 0)
  145. {
  146. throw new Exception("Stream Error: " + result);
  147. }
  148. else
  149. {
  150. break;
  151. }
  152. }
  153. bool dataAvailable = (size > 0);
  154. if (dataAvailable)
  155. {
  156. OpenALBinding.BufferData(bufferHandle, Format, data, SampleRate);
  157. }
  158. return dataAvailable;
  159. }
  160. #endregion
  161. #region Dispose (Public)
  162. /// <summary>
  163. /// Dispose the source and all buffers of the ogg music.
  164. /// </summary>
  165. public void Dispose()
  166. {
  167. // Nothing to do if this was already disposed
  168. if (Handle == MathHelper.InvalidIndex)
  169. {
  170. return;
  171. }
  172. if (oggFileStream != null)
  173. {
  174. oggFileStream.Close();
  175. }
  176. oggStream = null;
  177. // Otherwise do the normal disposing. First stop the source playback
  178. OpenALBinding.StopSource(Handle);
  179. OpenALBinding.CheckError();
  180. // and empty the buffer queue.
  181. int queued = OpenALBinding.GetBuffersQueued(Handle);
  182. while (queued-- != 0)
  183. {
  184. OpenALBinding.SourceUnqueueBuffers(Handle, 1);
  185. }
  186. // Delete the music source
  187. OpenALBinding.DeleteSource(Handle);
  188. Handle = MathHelper.InvalidIndex;
  189. // And finally delete the buffers
  190. OpenALBinding.DeleteBuffers(BufferHandles);
  191. OpenALBinding.CheckError();
  192. }
  193. #endregion
  194. }
  195. }