#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)
{
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
///
/// Returns true if the AudioReader has reached the end of the file.
///
public virtual bool EndOfFile
{
get
{
if (implementation != null)
return implementation.EndOfFile;
return this.Stream.Position >= this.Stream.Length;
}
}
#endregion
#endregion
#region --- Protected Members ---
///
/// Gets or sets the input of the AudioReader.
///
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;
}
}
///
/// Finalizes this AudioReader.
///
~AudioReader()
{
this.Dispose(false);
}
#endregion
}
}