#region --- License --- /* Licensed under the MIT/X11 license. * Copyright (c) 2006-2008 the OpenTK Team. * This notice may not be removed from any source distribution. * See license.txt for licensing details. */ #endregion using System; using System.Collections.Generic; using System.Text; using System.IO; namespace OpenTK.Audio { /// /// Encapsulates a sound stream and provides decoding and streaming capabilities. /// /// public class AudioReader : IDisposable { static object reader_lock = new object(); static List readers = new List(); bool disposed; Stream stream; AudioReader implementation; #region --- Constructors --- #region static AudioReader() static AudioReader() { // TODO: Plugin architecture for sound formats. This is overkill now that we only have a WaveReader (future proofing). readers.Add(new WaveReader()); } #endregion #region protected AudioReader() protected AudioReader() { } #endregion #region public AudioReader(string filename) /// Creates a new AudioReader that can read the specified sound file. /// The path to the sound file. /// A new OpenTK.Audio.AudioReader, which can be used to read from the specified sound file. public AudioReader(string filename) : this(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { } #endregion #region public AudioReader(Stream s) /// Creates a new AudioReader that can read the specified soundstream. /// The System.IO.Stream to read from. /// A new OpenTK.Audio.AudioReader, which can be used to read from the specified sound stream. public AudioReader(Stream s) { try { lock (reader_lock) { foreach (AudioReader reader in readers) { long pos = s.Position; if (reader.Supports(s)) { s.Position = pos; implementation = (AudioReader) reader.GetType().GetConstructor( System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance, null, new Type[] { typeof(Stream) }, null) .Invoke(new object[] { s }); return; } s.Position = pos; } } } catch (Exception e) { s.Close(); throw; } throw new NotSupportedException("Could not find a decoder for the specified sound stream."); } #endregion #endregion #region --- Public Members --- #region public virtual bool Supports(Stream s) /// When overriden in a derived class, checks if the decoder supports the specified sound stream. /// The System.IO.Stream to check. /// True if the sound stream is supported; false otherwise. public virtual bool Supports(Stream s) { if (implementation != null) return implementation.Supports(s); throw new NotImplementedException(); } #endregion #region public virtual SoundData ReadSamples(long count) /// /// When overriden in a derived class, reads and decodes the specified number of samples from the sound stream. /// /// The number of samples to read and decode. /// An OpenTK.Audio.SoundData object that contains the decoded buffer. public virtual SoundData ReadSamples(long count) { if (implementation != null) return implementation.ReadSamples(count); throw new NotImplementedException(); } #endregion #region public virtual SoundData ReadToEnd() /// /// When overriden in a derived class, reads and decodes the sound stream. /// /// An OpenTK.Audio.SoundData object that contains the decoded buffer. public virtual SoundData ReadToEnd() { if (implementation != null) return implementation.ReadToEnd(); throw new NotImplementedException(); } #endregion #region public virtual int Frequency /// /// /// public virtual int Frequency { get { if (implementation != null) return implementation.Frequency; else throw new NotImplementedException(); } protected set { if (implementation != null) implementation.Frequency = value; else throw new NotImplementedException(); } } #endregion #region public virtual bool EndOfFile public virtual bool EndOfFile { get { if (implementation != null) return implementation.EndOfFile; return this.Stream.Position >= this.Stream.Length; } } #endregion #endregion #region --- Protected Members --- protected virtual Stream Stream { get { return stream; } set { stream = value; } } #endregion #region IDisposable Members /// Closes the underlying Stream and disposes of the AudioReader resources. public virtual void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } void Dispose(bool manual) { if (!disposed) { if (manual) if (this.Stream != null) this.Stream.Close(); disposed = true; } } ~AudioReader() { this.Dispose(false); } #endregion } }