PageRenderTime 42ms CodeModel.GetById 30ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/Multimedia/OpenTK/OggMusicData.cs

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