Implemented the MediaPlayer and MediaQueue classes as preparation for native Song playback.

Also added the FrameworkDispatcher calls in the Game class.
Checking for possible fire and forget sound instances to be disposed in the FrameworkDispatcher update chain.
This commit is contained in:
SND\AstrorEnales_cp 2012-09-29 22:01:15 +00:00 committed by Konstantin Koch
parent c5145397bf
commit ef734ddcd3
25 changed files with 638 additions and 639 deletions

View File

@ -446,6 +446,7 @@
<Compile Include="NonXNA\RenderSystem\IOcclusionQuery.cs" /> <Compile Include="NonXNA\RenderSystem\IOcclusionQuery.cs" />
<Compile Include="NonXNA\RenderSystem\VertexTypeHelper.cs" /> <Compile Include="NonXNA\RenderSystem\VertexTypeHelper.cs" />
<Compile Include="NonXNA\SoundSystem\IMicrophone.cs" /> <Compile Include="NonXNA\SoundSystem\IMicrophone.cs" />
<Compile Include="NonXNA\SoundSystem\ISong.cs" />
<Compile Include="NonXNA\ThreadHelper.cs" /> <Compile Include="NonXNA\ThreadHelper.cs" />
<Compile Include="NonXNA\Windows8\AssetsHelper.cs" /> <Compile Include="NonXNA\Windows8\AssetsHelper.cs" />
<Compile Include="NonXNA\Windows8\IServiceProvider.cs" /> <Compile Include="NonXNA\Windows8\IServiceProvider.cs" />

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq;
using ANX.Framework.Audio.XactParser; using ANX.Framework.Audio.XactParser;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using ANX.Framework.NonXNA.Development; using ANX.Framework.NonXNA.Development;
@ -74,9 +75,8 @@ namespace ANX.Framework.Audio
#region GetCategory #region GetCategory
public AudioCategory GetCategory(string name) public AudioCategory GetCategory(string name)
{ {
for (int index = 0; index < generalSettings.Categories.Length; index++) foreach (AudioCategory category in generalSettings.Categories.Where(category => category.Name == name))
if (generalSettings.Categories[index].Name == name) return category;
return generalSettings.Categories[index];
return new AudioCategory(name); return new AudioCategory(name);
} }
@ -85,8 +85,7 @@ namespace ANX.Framework.Audio
#region GetGlobalVariable #region GetGlobalVariable
public float GetGlobalVariable(string name) public float GetGlobalVariable(string name)
{ {
foreach (var variable in generalSettings.Variables) foreach (var variable in generalSettings.Variables.Where(variable => variable.Name == name))
if (variable.Name == name)
return variable.StartingValue; return variable.StartingValue;
return 0f; return 0f;
@ -96,8 +95,7 @@ namespace ANX.Framework.Audio
#region SetGlobalVariable #region SetGlobalVariable
public void SetGlobalVariable(string name, float value) public void SetGlobalVariable(string name, float value)
{ {
foreach (var variable in generalSettings.Variables) foreach (var variable in generalSettings.Variables.Where(variable => variable.Name == name))
if (variable.Name == name)
variable.StartingValue = MathHelper.Clamp(value, variable.MinValue, variable.MaxValue); variable.StartingValue = MathHelper.Clamp(value, variable.MinValue, variable.MaxValue);
} }
#endregion #endregion
@ -112,15 +110,15 @@ namespace ANX.Framework.Audio
#region Dispose #region Dispose
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (IsDisposed == false) if (IsDisposed)
{ return;
if (Disposing != null) if (Disposing != null)
Disposing(this, EventArgs.Empty); Disposing(this, EventArgs.Empty);
IsDisposed = true; IsDisposed = true;
generalSettings = null; generalSettings = null;
} }
}
public void Dispose() public void Dispose()
{ {

View File

@ -17,61 +17,29 @@ namespace ANX.Framework.Audio
public sealed class SoundEffect : IDisposable public sealed class SoundEffect : IDisposable
{ {
#region Static #region Static
#region DistanceScale
public static float DistanceScale public static float DistanceScale
{ {
get get { return GetCreator().DistanceScale; }
{ set { GetCreator().DistanceScale = value; }
return GetCreator().DistanceScale;
} }
set
{
GetCreator().DistanceScale = value;
}
}
#endregion
#region DopplerScale
public static float DopplerScale public static float DopplerScale
{ {
get get { return GetCreator().DopplerScale; }
{ set { GetCreator().DopplerScale = value; }
return GetCreator().DopplerScale;
} }
set
{
GetCreator().DopplerScale = value;
}
}
#endregion
#region MasterVolume
public static float MasterVolume public static float MasterVolume
{ {
get get { return GetCreator().MasterVolume; }
{ set { GetCreator().MasterVolume = value; }
return GetCreator().MasterVolume;
} }
set
{
GetCreator().MasterVolume = value;
}
}
#endregion
#region SpeedOfSound
public static float SpeedOfSound public static float SpeedOfSound
{ {
get get { return GetCreator().SpeedOfSound; }
{ set { GetCreator().SpeedOfSound = value; }
return GetCreator().SpeedOfSound;
} }
set
{
GetCreator().SpeedOfSound = value;
}
}
#endregion
#endregion #endregion
#region Private #region Private
@ -131,11 +99,13 @@ namespace ANX.Framework.Audio
{ {
} }
public SoundEffect(byte[] buffer, int offset, int count, int sampleRate, AudioChannels channels, int loopStart, int loopLength) public SoundEffect(byte[] buffer, int offset, int count, int sampleRate, AudioChannels channels, int loopStart,
int loopLength)
: this() : this()
{ {
var creator = GetCreator(); var creator = GetCreator();
NativeSoundEffect = creator.CreateSoundEffect(this, buffer, offset, count, sampleRate, channels, loopStart, loopLength); NativeSoundEffect = creator.CreateSoundEffect(this, buffer, offset, count, sampleRate, channels, loopStart,
loopLength);
} }
~SoundEffect() ~SoundEffect()
@ -204,9 +174,7 @@ namespace ANX.Framework.Audio
children.Add(new WeakReference(newInstance)); children.Add(new WeakReference(newInstance));
lock (fireAndForgetInstances) lock (fireAndForgetInstances)
{
fireAndForgetInstances.Add(newInstance); fireAndForgetInstances.Add(newInstance);
}
newInstance.Play(); newInstance.Play();
} }
@ -220,6 +188,25 @@ namespace ANX.Framework.Audio
} }
#endregion #endregion
#region RecycleStoppedFireAndForgetInstances
internal static void RecycleStoppedFireAndForgetInstances()
{
lock (fireAndForgetInstances)
{
var instancesToDispose = new List<SoundEffectInstance>();
foreach (SoundEffectInstance current in fireAndForgetInstances)
if (current.State == SoundState.Stopped)
instancesToDispose.Add(current);
foreach (SoundEffectInstance current in instancesToDispose)
{
current.Dispose();
fireAndForgetInstances.Remove(current);
}
}
}
#endregion
#region Dispose #region Dispose
public void Dispose() public void Dispose()
{ {

View File

@ -16,12 +16,7 @@ namespace ANX.Framework.Audio
{ {
#region Private #region Private
private ISoundEffectInstance nativeInstance; private ISoundEffectInstance nativeInstance;
internal bool IsFireAndForget { get; private set; }
internal bool IsFireAndForget
{
get;
private set;
}
#endregion #endregion
#region Public #region Public

View File

@ -10,24 +10,12 @@ namespace ANX.Framework.Audio.XactParser
internal class XactGeneralSettingsRpcCurve internal class XactGeneralSettingsRpcCurve
{ {
// what variable this curve involves // what variable this curve involves
public ushort VariableIndex public ushort VariableIndex { get; private set; }
{
get;
private set;
}
// which parameter the curve affects refer to the above constants // which parameter the curve affects refer to the above constants
public short Parameters public short Parameters { get; private set; }
{
get;
private set;
}
public XactGeneralSettingsRpcCurvePoint[] Points public XactGeneralSettingsRpcCurvePoint[] Points { get; private set; }
{
get;
private set;
}
public XactGeneralSettingsRpcCurve(BinaryReader reader) public XactGeneralSettingsRpcCurve(BinaryReader reader)
{ {

View File

@ -17,29 +17,15 @@ namespace ANX.Framework.Audio.XactParser
SinCos = 0x03, SinCos = 0x03,
} }
public float X public float X { get; private set; }
{ public float Y { get; private set; }
get; public CurveType Type { get; private set; }
private set;
}
public float Y
{
get;
private set;
}
public CurveType Type
{
get;
private set;
}
public XactGeneralSettingsRpcCurvePoint(BinaryReader reader) public XactGeneralSettingsRpcCurvePoint(BinaryReader reader)
{ {
X = reader.ReadSingle(); X = reader.ReadSingle();
Y = reader.ReadSingle(); Y = reader.ReadSingle();
Type = (XactGeneralSettingsRpcCurvePoint.CurveType)reader.ReadByte(); Type = (CurveType)reader.ReadByte();
} }
} }
} }

View File

@ -17,35 +17,15 @@ namespace ANX.Framework.Audio.XactParser
Reserved = 0x08, Reserved = 0x08,
} }
public VariableFlags Flags public VariableFlags Flags { get; private set; }
{ public float StartingValue { get; set; }
get; public float MinValue { get; private set; }
private set; public float MaxValue { get; private set; }
}
public float StartingValue
{
get;
set;
}
public float MinValue
{
get;
private set;
}
public float MaxValue
{
get;
private set;
}
public string Name; public string Name;
public XactGeneralSettingsVariable(BinaryReader reader) public XactGeneralSettingsVariable(BinaryReader reader)
{ {
Flags = (XactGeneralSettingsVariable.VariableFlags)reader.ReadByte(); Flags = (VariableFlags)reader.ReadByte();
StartingValue = reader.ReadSingle(); StartingValue = reader.ReadSingle();
MinValue = reader.ReadSingle(); MinValue = reader.ReadSingle();
MaxValue = reader.ReadSingle(); MaxValue = reader.ReadSingle();

View File

@ -1,4 +1,5 @@
using System; using System;
using ANX.Framework.Audio;
using ANX.Framework.NonXNA.Development; using ANX.Framework.NonXNA.Development;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
@ -18,6 +19,8 @@ namespace ANX.Framework
{ {
if (OnUpdate != null) if (OnUpdate != null)
OnUpdate(); OnUpdate();
SoundEffect.RecycleStoppedFireAndForgetInstances();
} }
} }
} }

View File

@ -6,6 +6,7 @@ using ANX.Framework.Graphics;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using ANX.Framework.NonXNA.Development; using ANX.Framework.NonXNA.Development;
using ANX.Framework.NonXNA.PlatformSystem; using ANX.Framework.NonXNA.PlatformSystem;
using ANX.Framework.NonXNA.SoundSystem;
#endregion // Using Statements #endregion // Using Statements
@ -78,6 +79,8 @@ namespace ANX.Framework
AddSystemCreator<ISoundSystemCreator>(); AddSystemCreator<ISoundSystemCreator>();
AddSystemCreator<IRenderSystemCreator>(); AddSystemCreator<IRenderSystemCreator>();
FrameworkDispatcher.Update();
CreateGameHost(); CreateGameHost();
Logger.Info("creating ContentManager"); Logger.Info("creating ContentManager");
@ -151,6 +154,8 @@ namespace ANX.Framework
updateable.Update(gameTime); updateable.Update(gameTime);
} }
} }
FrameworkDispatcher.Update();
} }
protected virtual void Draw(GameTime gameTime) protected virtual void Draw(GameTime gameTime)

View File

@ -1,4 +1,5 @@
using System; using System;
using ANX.Framework.NonXNA.Development;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
@ -6,6 +7,9 @@ using System;
namespace ANX.Framework.Media namespace ANX.Framework.Media
{ {
[PercentageComplete(100)]
[TestState(TestStateAttribute.TestState.Untested)]
[Developer("AstrorEnales")]
public static class MediaPlayer public static class MediaPlayer
{ {
#region Events #region Events
@ -13,118 +17,71 @@ namespace ANX.Framework.Media
public static event EventHandler<EventArgs> MediaStateChanged; public static event EventHandler<EventArgs> MediaStateChanged;
#endregion #endregion
#region Public private static bool isRepeating;
#region IsShuffled (TODO) private static float volume;
public static bool IsShuffled private static MediaState currentState;
internal static float VolumeToUse
{ {
get get { return IsMuted ? 0f : volume; }
{
throw new NotImplementedException();
} }
set
{
throw new NotImplementedException();
}
}
#endregion
#region IsRepeating (TODO) #region Public
public static bool IsShuffled { get; set; }
public static bool IsRepeating public static bool IsRepeating
{ {
get get { return isRepeating; }
{ set { isRepeating = value; }
throw new NotImplementedException();
} }
set
{
throw new NotImplementedException();
}
}
#endregion
#region Volume (TODO)
public static float Volume public static float Volume
{ {
get get { return volume; }
{ set { volume = MathHelper.Clamp(value, 0f, 1f); }
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
#endregion
#region IsMuted (TODO)
public static bool IsMuted
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
#endregion
#region IsVisualizationEnabled (TODO)
public static bool IsVisualizationEnabled
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
#endregion
public static MediaQueue Queue
{
get;
private set;
} }
#region State (TODO) public static bool IsVisualizationEnabled { get; set; }
public static bool IsMuted { get; set; }
public static MediaQueue Queue { get; private set; }
public static MediaState State public static MediaState State
{ {
get get { return currentState; }
private set
{ {
throw new NotImplementedException(); if (currentState == value)
} return;
}
#endregion currentState = value;
MediaStateChanged(null, EventArgs.Empty);
}
}
#region PlayPosition (TODO)
public static TimeSpan PlayPosition public static TimeSpan PlayPosition
{ {
get get
{ {
throw new NotImplementedException(); return Queue.ActiveSong == null
? TimeSpan.Zero : Queue.ActiveSong.NativeSong.PlayPosition;
} }
} }
#endregion
#region GameHasControl (TODO)
public static bool GameHasControl public static bool GameHasControl
{ {
get get { return true; }
{
throw new NotImplementedException();
} }
}
#endregion
#endregion #endregion
#region Constructor #region Constructor
static MediaPlayer() static MediaPlayer()
{ {
currentState = MediaState.Stopped;
volume = 1f;
isRepeating = false;
IsMuted = false;
IsVisualizationEnabled = false;
IsShuffled = false;
Queue = new MediaQueue(); Queue = new MediaQueue();
FrameworkDispatcher.OnUpdate += Tick;
} }
#endregion #endregion
@ -133,47 +90,45 @@ namespace ANX.Framework.Media
{ {
Queue.Play(song); Queue.Play(song);
} }
#endregion
#region Play
public static void Play(SongCollection songCollection) public static void Play(SongCollection songCollection)
{ {
Queue.Play(songCollection); Queue.Play(songCollection);
} }
#endregion
#region Play (TODO)
public static void Play(SongCollection songCollection, int index) public static void Play(SongCollection songCollection, int index)
{ {
throw new NotImplementedException(); Queue.Play(songCollection, index);
} }
#endregion #endregion
#region Pause (TODO) #region Pause
public static void Pause() public static void Pause()
{ {
throw new NotImplementedException(); if (Queue.ActiveSong != null)
Queue.ActiveSong.Pause();
} }
#endregion #endregion
#region Resume (TODO) #region Resume
public static void Resume() public static void Resume()
{ {
throw new NotImplementedException(); if (Queue.ActiveSong != null)
Queue.ActiveSong.Resume();
} }
#endregion #endregion
#region Stop (TODO) #region Stop
public static void Stop() public static void Stop()
{ {
throw new NotImplementedException(); Queue.Stop();
} }
#endregion #endregion
#region MoveNext #region MoveNext
public static void MoveNext() public static void MoveNext()
{ {
Queue.MoveNext(); Queue.MoveNext(false);
} }
#endregion #endregion
@ -184,10 +139,37 @@ namespace ANX.Framework.Media
} }
#endregion #endregion
#region GetVisualizationData (TODO) #region Tick
public static void GetVisualizationData(VisualizationData data) private static void Tick()
{ {
throw new NotImplementedException(); if (Queue.ActiveSong == null)
{
State = MediaState.Stopped;
return;
}
State = Queue.ActiveSong.State;
if (Queue.ActiveSong.State != MediaState.Stopped)
return;
if (Queue.MoveNext(isRepeating))
State = MediaState.Playing;
ActiveSongChanged(null, EventArgs.Empty);
}
#endregion
#region GetVisualizationData
public static void GetVisualizationData(VisualizationData visualizationData)
{
if (visualizationData == null)
throw new ArgumentNullException("visualizationData");
if (IsVisualizationEnabled == false)
return;
if(Queue.ActiveSong != null)
Queue.ActiveSong.NativeSong.GetVisualizationData(visualizationData);
} }
#endregion #endregion
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ANX.Framework.NonXNA.Development;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
@ -7,41 +8,29 @@ using System.Collections.Generic;
namespace ANX.Framework.Media namespace ANX.Framework.Media
{ {
[PercentageComplete(100)]
[TestState(TestStateAttribute.TestState.Untested)]
[Developer("AstrorEnales")]
public sealed class MediaQueue public sealed class MediaQueue
{ {
#region Private private readonly List<Song> queue;
private List<Song> queue;
#endregion
#region Public #region Public
public int Count public int Count
{ {
get get { return queue.Count; }
{
return queue.Count;
}
} }
public int ActiveSongIndex public int ActiveSongIndex { get; set; }
{
get;
set;
}
public Song ActiveSong public Song ActiveSong
{ {
get get { return queue.Count <= 0 ? null : queue[ActiveSongIndex]; }
{
return queue[ActiveSongIndex];
}
} }
public Song this[int index] public Song this[int index]
{ {
get get { return queue[index]; }
{
return queue[index];
}
} }
#endregion #endregion
@ -50,14 +39,22 @@ namespace ANX.Framework.Media
{ {
queue = new List<Song>(); queue = new List<Song>();
} }
~MediaQueue()
{
queue.Clear();
}
#endregion #endregion
#region Play
internal void Play(Song song) internal void Play(Song song)
{ {
if (song == null) if (song == null)
throw new ArgumentNullException("song"); throw new ArgumentNullException("song");
Clear();
queue.Add(song); queue.Add(song);
ActiveSong.Play();
} }
internal void Play(SongCollection songCollection) internal void Play(SongCollection songCollection)
@ -65,29 +62,93 @@ namespace ANX.Framework.Media
if (songCollection == null) if (songCollection == null)
throw new ArgumentNullException("songCollection"); throw new ArgumentNullException("songCollection");
Clear();
queue.AddRange(songCollection); queue.AddRange(songCollection);
// TODO: check if the shuffle is calculated after each finished song or like this!
if (MediaPlayer.IsShuffled)
Shuffle();
ActiveSong.Play();
} }
internal void MoveNext() internal void Play(SongCollection songCollection, int index)
{ {
if (Count > 0) if (songCollection == null)
throw new ArgumentNullException("songCollection");
Clear();
ActiveSongIndex = index;
queue.AddRange(songCollection);
// TODO: check if the shuffle is calculated after each finished song or like this!
if (MediaPlayer.IsShuffled)
Shuffle();
ActiveSong.Play();
}
#endregion
private void Clear()
{ {
Stop();
ActiveSongIndex = 0;
queue.Clear();
}
internal void Stop()
{
if(ActiveSong != null)
ActiveSong.Stop();
}
private void Shuffle()
{
var rand = new Random();
int n = queue.Count;
while (n > 1)
{
int k = rand.Next(n);
n--;
Song value = queue[k];
queue[k] = queue[n];
queue[n] = value;
}
}
#region MoveNext
internal bool MoveNext(bool stopIfEnded)
{
if (Count <= 0)
return false;
ActiveSong.Stop();
if (ActiveSongIndex < Count - 1) if (ActiveSongIndex < Count - 1)
ActiveSongIndex++; ActiveSongIndex++;
else else
{
ActiveSongIndex = 0; ActiveSongIndex = 0;
} if (stopIfEnded)
return false;
} }
ActiveSong.Play();
return true;
}
#endregion
#region MovePrevious
internal void MovePrevious() internal void MovePrevious()
{ {
if (Count > 0) if (Count <= 0)
{ return;
ActiveSong.Stop();
if (ActiveSongIndex > 0) if (ActiveSongIndex > 0)
ActiveSongIndex--; ActiveSongIndex--;
else else
ActiveSongIndex = Count - 1; ActiveSongIndex = Count - 1;
}
} ActiveSong.Play();
}
#endregion
} }
} }

View File

@ -1,4 +1,7 @@
using System; using System;
using ANX.Framework.NonXNA;
using ANX.Framework.NonXNA.SoundSystem;
using ANX.Framework.NonXNA.Development;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
@ -6,26 +9,20 @@ using System;
namespace ANX.Framework.Media namespace ANX.Framework.Media
{ {
[PercentageComplete(50)]
[Developer("AstrorEnales")]
public sealed class Song : IEquatable<Song>, IDisposable public sealed class Song : IEquatable<Song>, IDisposable
{ {
public bool IsDisposed internal ISong NativeSong { get; private set; }
{ internal MediaState State { get { return NativeSong.State; } }
get;
private set;
}
public string Name #region Public
{ public bool IsDisposed { get; private set; }
get; public string Name { get; private set; }
private set;
}
public bool IsRated public bool IsRated
{ {
get get { return Rating > 0; }
{
return Rating > 0;
}
} }
public Artist Artist public Artist Artist
@ -54,10 +51,7 @@ namespace ANX.Framework.Media
public TimeSpan Duration public TimeSpan Duration
{ {
get get { return NativeSong.Duration; }
{
throw new NotImplementedException();
}
} }
public int Rating public int Rating
@ -91,10 +85,12 @@ namespace ANX.Framework.Media
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
#endregion
#region Constructor #region Constructor
internal Song(string setName) internal Song(string setName, Uri uri)
{ {
NativeSong = AddInSystemFactory.Instance.GetDefaultCreator<ISoundSystemCreator>().CreateSong(this, uri);
Name = setName; Name = setName;
IsDisposed = false; IsDisposed = false;
} }
@ -105,9 +101,9 @@ namespace ANX.Framework.Media
} }
#endregion #endregion
public Song FromUri(string name, Uri uri) public static Song FromUri(string name, Uri uri)
{ {
throw new NotImplementedException(); return new Song(name, uri);
} }
public bool Equals(Song other) public bool Equals(Song other)
@ -125,11 +121,34 @@ namespace ANX.Framework.Media
public void Dispose() public void Dispose()
{ {
if (IsDisposed == false) if (IsDisposed)
{ return;
IsDisposed = true; IsDisposed = true;
throw new NotImplementedException();
if(NativeSong != null)
NativeSong.Dispose();
NativeSong = null;
} }
internal void Play()
{
NativeSong.Play();
}
internal void Stop()
{
NativeSong.Stop();
}
internal void Pause()
{
NativeSong.Pause();
}
internal void Resume()
{
NativeSong.Resume();
} }
#region ToString #region ToString
@ -149,12 +168,12 @@ namespace ANX.Framework.Media
#region Operator overloading #region Operator overloading
public static bool operator ==(Song first, Song second) public static bool operator ==(Song first, Song second)
{ {
return first.Equals(second); return first != null && first.Equals(second);
} }
public static bool operator !=(Song first, Song second) public static bool operator !=(Song first, Song second)
{ {
return first.Equals(second) == false; return first == null || first.Equals(second) == false;
} }
#endregion #endregion
} }

View File

@ -1,4 +1,3 @@
using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
@ -9,20 +8,23 @@ namespace ANX.Framework.Media
{ {
public class VisualizationData public class VisualizationData
{ {
internal readonly float[] FrequencyData;
internal readonly float[] SampleData;
public ReadOnlyCollection<float> Frequencies public ReadOnlyCollection<float> Frequencies
{ {
get get { return new ReadOnlyCollection<float>(FrequencyData); }
{
throw new NotImplementedException();
}
} }
public ReadOnlyCollection<float> Samples public ReadOnlyCollection<float> Samples
{ {
get get { return new ReadOnlyCollection<float>(SampleData); }
}
public VisualizationData()
{ {
throw new NotImplementedException(); FrequencyData = new float[256];
} SampleData = new float[256];
} }
} }
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using ANX.Framework.NonXNA.PlatformSystem; using ANX.Framework.NonXNA.PlatformSystem;
using ANX.Framework.NonXNA.Reflection; using ANX.Framework.NonXNA.Reflection;
using ANX.Framework.NonXNA.SoundSystem;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.

View File

@ -0,0 +1,19 @@
using System;
using ANX.Framework.Media;
namespace ANX.Framework.NonXNA.SoundSystem
{
public interface ISong : IDisposable
{
TimeSpan Duration { get; }
TimeSpan PlayPosition { get; }
MediaState State { get; }
void Play();
void Stop();
void Pause();
void Resume();
void Update();
void GetVisualizationData(VisualizationData data);
}
}

View File

@ -1,39 +1,21 @@
using System;
using System.IO; using System.IO;
using ANX.Framework.Audio; using ANX.Framework.Audio;
using ANX.Framework.NonXNA.SoundSystem;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using ANX.Framework.Media;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license // For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.NonXNA namespace ANX.Framework.NonXNA.SoundSystem
{ {
public interface ISoundSystemCreator : ICreator public interface ISoundSystemCreator : ICreator
{ {
float DistanceScale float DistanceScale { get; set; }
{ float DopplerScale { get; set; }
get; float MasterVolume { get; set; }
set; float SpeedOfSound { get; set; }
}
float DopplerScale
{
get;
set;
}
float MasterVolume
{
get;
set;
}
float SpeedOfSound
{
get;
set;
}
IAudioListener CreateAudioListener(); IAudioListener CreateAudioListener();
@ -52,5 +34,7 @@ namespace ANX.Framework.NonXNA
ReadOnlyCollection<Microphone> GetAllMicrophones(); ReadOnlyCollection<Microphone> GetAllMicrophones();
int GetDefaultMicrophone(ReadOnlyCollection<Microphone> allMicrophones); int GetDefaultMicrophone(ReadOnlyCollection<Microphone> allMicrophones);
ISong CreateSong(Song parentSong, Uri uri);
} }
} }

View File

@ -39,17 +39,17 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo("ANX.RenderSystem.Windows.Metro")] [assembly: InternalsVisibleTo("ANX.RenderSystem.Windows.Metro")]
[assembly: InternalsVisibleTo("ANX.RenderSystem.GL3")] [assembly: InternalsVisibleTo("ANX.RenderSystem.GL3")]
[assembly: InternalsVisibleTo("ANX.RenderSystem.Windows.PsVita")] [assembly: InternalsVisibleTo("ANX.RenderSystem.Windows.PsVita")]
[assembly: InternalsVisibleTo("ANX.Framework.Windows.Kinect")]
[assembly: InternalsVisibleTo("ANX.Framework.Windows.XInput")]
[assembly: InternalsVisibleTo("ANX.Framework.Windows.XAudio")]
[assembly: InternalsVisibleTo("ANX.InputSystem.Recording")] [assembly: InternalsVisibleTo("ANX.InputSystem.Recording")]
[assembly: InternalsVisibleTo("ANX.InputDevices.PsVita")] [assembly: InternalsVisibleTo("ANX.InputDevices.PsVita")]
[assembly: InternalsVisibleTo("ANX.InputDevices.Test")] [assembly: InternalsVisibleTo("ANX.InputDevices.Test")]
[assembly: InternalsVisibleTo("ANX.InputDevices.Windows.Kinect")]
[assembly: InternalsVisibleTo("ANX.InputDevices.Windows.XInput")] [assembly: InternalsVisibleTo("ANX.InputDevices.Windows.XInput")]
[assembly: InternalsVisibleTo("ANX.InputDevices.Windows.ModernUI")] [assembly: InternalsVisibleTo("ANX.InputDevices.Windows.ModernUI")]
[assembly: InternalsVisibleTo("ANX.PlatformSystem.Windows")] [assembly: InternalsVisibleTo("ANX.PlatformSystem.Windows")]
[assembly: InternalsVisibleTo("ANX.PlatformSystem.Linux")] [assembly: InternalsVisibleTo("ANX.PlatformSystem.Linux")]
[assembly: InternalsVisibleTo("ANX.PlatformSystem.Metro")] [assembly: InternalsVisibleTo("ANX.PlatformSystem.Metro")]
[assembly: InternalsVisibleTo("ANX.PlatformSystem.PsVita")] [assembly: InternalsVisibleTo("ANX.PlatformSystem.PsVita")]
[assembly: InternalsVisibleTo("ANX.SoundSystem.Windows.XAudio")]
[assembly: InternalsVisibleTo("ANX.SoundSystem.Windows.OpenAL")]
[assembly: InternalsVisibleTo("ANX.Tools.XNBInspector")] [assembly: InternalsVisibleTo("ANX.Tools.XNBInspector")]
[assembly: InternalsVisibleTo("ANX.Framework.Content.Pipeline")] [assembly: InternalsVisibleTo("ANX.Framework.Content.Pipeline")]

View File

@ -42,25 +42,17 @@ namespace ANX.RenderSystem.GL3
{ {
get get
{ {
return (Current == null || Current.nativeContext == null) ? false : Current.nativeContext.IsCurrent; return (Current != null && Current.nativeContext != null) && Current.nativeContext.IsCurrent;
} }
} }
#endregion #endregion
#region Public #region Public
#region VSync
public bool VSync public bool VSync
{ {
get get { return nativeContext.VSync; }
{ set { nativeContext.VSync = value; }
return nativeContext.VSync;
} }
set
{
nativeContext.VSync = value;
}
}
#endregion
#endregion #endregion
#region Constructor #region Constructor

View File

@ -1,10 +1,10 @@
using System;
using System.Threading;
using System.Windows; using System.Windows;
using System.Windows.Threading;
using ANX.Framework; using ANX.Framework;
using ANX.Framework.Graphics; using ANX.Framework.Graphics;
using System.Windows.Interop; using ANX.Framework.NonXNA;
using System;
using System.Windows.Threading;
using System.Threading;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
@ -12,13 +12,18 @@ using System.Threading;
namespace WpfEditor namespace WpfEditor
{ {
public partial class MainWindow : Window public partial class MainWindow
{ {
private GraphicsDevice device; private GraphicsDevice device;
private readonly ThreadStart emptyThreadStart;
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
emptyThreadStart = delegate { };
//AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "OpenGL3");
AddInSystemFactory.Instance.SetPreferredSystem(AddInType.RenderSystem, "DirectX10");
} }
protected override void OnActivated(EventArgs e) protected override void OnActivated(EventArgs e)
@ -30,10 +35,7 @@ namespace WpfEditor
while (IsVisible) while (IsVisible)
{ {
if (Application.Current != null) if (Application.Current != null)
{ Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, emptyThreadStart);
Application.Current.Dispatcher.Invoke(
DispatcherPriority.Background, new ThreadStart(delegate { }));
}
Tick(); Tick();
} }
@ -41,13 +43,11 @@ namespace WpfEditor
public void Initialize() public void Initialize()
{ {
device = new GraphicsDevice( device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, GraphicsProfile.HiDef,
GraphicsAdapter.DefaultAdapter,
GraphicsProfile.HiDef,
new PresentationParameters new PresentationParameters
{ {
BackBufferWidth = (int)GamePanel.Width, BackBufferWidth = GamePanel.Width,
BackBufferHeight = (int)GamePanel.Height, BackBufferHeight = GamePanel.Height,
BackBufferFormat = SurfaceFormat.Color, BackBufferFormat = SurfaceFormat.Color,
DeviceWindowHandle = GamePanel.Handle, DeviceWindowHandle = GamePanel.Handle,
PresentationInterval = PresentInterval.Default, PresentationInterval = PresentInterval.Default,

View File

@ -107,6 +107,10 @@
<Project>{49066074-3B7B-4A55-B122-6BD33AB73558}</Project> <Project>{49066074-3B7B-4A55-B122-6BD33AB73558}</Project>
<Name>ANX.InputSystem.Standard</Name> <Name>ANX.InputSystem.Standard</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\..\RenderSystems\ANX.Framework.GL3\ANX.RenderSystem.GL3.csproj">
<Project>{EB8258E0-6741-4DB9-B756-1EBDF67B1ED6}</Project>
<Name>ANX.RenderSystem.GL3</Name>
</ProjectReference>
<ProjectReference Include="..\..\RenderSystems\ANX.RenderSystem.Windows.DX10\ANX.RenderSystem.Windows.DX10.csproj"> <ProjectReference Include="..\..\RenderSystems\ANX.RenderSystem.Windows.DX10\ANX.RenderSystem.Windows.DX10.csproj">
<Project>{5BE49183-2F6F-4527-AC90-D816911FCF90}</Project> <Project>{5BE49183-2F6F-4527-AC90-D816911FCF90}</Project>
<Name>ANX.RenderSystem.Windows.DX10</Name> <Name>ANX.RenderSystem.Windows.DX10</Name>

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using ANX.Framework.Audio; using ANX.Framework.Audio;
using ANX.Framework.Media;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using ANX.Framework.NonXNA.SoundSystem; using ANX.Framework.NonXNA.SoundSystem;
using OpenTK; using OpenTK;
@ -15,21 +16,18 @@ namespace ANX.SoundSystem.OpenAL
{ {
public class Creator : ISoundSystemCreator public class Creator : ISoundSystemCreator
{ {
private float currentDistanceScale;
private float currentMasterVolume;
#region Public #region Public
public string Name public string Name
{ {
get get { return "OpenAL"; }
{
return "OpenAL";
}
} }
public int Priority public int Priority
{ {
get get { return 100; }
{
return 100;
}
} }
public bool IsSupported public bool IsSupported
@ -45,75 +43,55 @@ namespace ANX.SoundSystem.OpenAL
public float DistanceScale public float DistanceScale
{ {
get get { return currentDistanceScale; }
{
return 1f;
//throw new NotImplementedException();
}
set set
{ {
//throw new NotImplementedException(); currentDistanceScale = value;
// TODO: set actual property
} }
} }
public float DopplerScale public float DopplerScale
{ {
get get { return AL.Get(ALGetFloat.DopplerFactor); }
{ set { AL.DopplerFactor(value); }
return AL.Get(ALGetFloat.DopplerFactor);
}
set
{
AL.DopplerFactor(value);
}
} }
public float MasterVolume public float MasterVolume
{ {
get get { return currentMasterVolume; }
{
return 1f;
//throw new NotImplementedException();
}
set set
{ {
//throw new NotImplementedException(); currentMasterVolume = value;
// TODO: set actual property
} }
} }
public float SpeedOfSound public float SpeedOfSound
{ {
get get { return AL.Get(ALGetFloat.SpeedOfSound); }
{ set { AL.SpeedOfSound(value); }
return AL.Get(ALGetFloat.SpeedOfSound);
}
set
{
AL.SpeedOfSound(value);
}
} }
#endregion #endregion
public Creator() public Creator()
{ {
currentDistanceScale = 1f;
currentMasterVolume = 1f;
Init(); Init();
} }
private void Init() private static void Init()
{ {
IntPtr deviceHandle;
ContextHandle context = Alc.GetCurrentContext(); ContextHandle context = Alc.GetCurrentContext();
if (context.Handle != IntPtr.Zero) if (context.Handle == IntPtr.Zero)
{ {
deviceHandle = Alc.GetContextsDevice(context); string deviceName = Alc.GetString(IntPtr.Zero, AlcGetString.DefaultDeviceSpecifier);
} IntPtr deviceHandle = Alc.OpenDevice(deviceName);
else
{
deviceHandle = Alc.OpenDevice(Alc.GetString(IntPtr.Zero, AlcGetString.DefaultDeviceSpecifier));
context = Alc.CreateContext(deviceHandle, new int[0]); context = Alc.CreateContext(deviceHandle, new int[0]);
} }
bool isNowCurrent = Alc.MakeContextCurrent(context); Alc.MakeContextCurrent(context);
} }
#region CreateSoundEffectInstance #region CreateSoundEffectInstance
@ -181,7 +159,13 @@ namespace ANX.SoundSystem.OpenAL
} }
#endregion #endregion
private void PreventSystemChange() public ISong CreateSong(Song parentSong, Uri uri)
{
PreventSystemChange();
throw new NotImplementedException();
}
private static void PreventSystemChange()
{ {
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem); AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
} }

View File

@ -12,8 +12,8 @@ namespace ANX.SoundSystem.OpenAL
public class OpenALSoundEffectInstance : ISoundEffectInstance public class OpenALSoundEffectInstance : ISoundEffectInstance
{ {
#region Private #region Private
private OpenALSoundEffect parent; private readonly OpenALSoundEffect parent;
private float currentPan;
private int handle; private int handle;
#endregion #endregion
@ -26,22 +26,16 @@ namespace ANX.SoundSystem.OpenAL
AL.GetSource(handle, ALSourceb.Looping, out result); AL.GetSource(handle, ALSourceb.Looping, out result);
return result; return result;
} }
set set { AL.Source(handle, ALSourceb.Looping, value); }
{
AL.Source(handle, ALSourceb.Looping, value);
}
} }
public float Pan public float Pan
{ {
get get { return currentPan; }
{
return 0f;
//throw new NotImplementedException();
}
set set
{ {
//throw new NotImplementedException(); currentPan = value;
// TODO: set actual parameter
} }
} }
@ -53,17 +47,10 @@ namespace ANX.SoundSystem.OpenAL
AL.GetSource(handle, ALSourcef.Pitch, out result); AL.GetSource(handle, ALSourcef.Pitch, out result);
return result; return result;
} }
set set { AL.Source(handle, ALSourcef.Pitch, value); }
{
AL.Source(handle, ALSourcef.Pitch, value);
}
} }
public SoundState State public SoundState State { get; private set; }
{
get;
private set;
}
public float Volume public float Volume
{ {
@ -73,10 +60,7 @@ namespace ANX.SoundSystem.OpenAL
AL.GetSource(handle, ALSourcef.Gain, out result); AL.GetSource(handle, ALSourcef.Gain, out result);
return result; return result;
} }
set set { AL.Source(handle, ALSourcef.Gain, value); }
{
AL.Source(handle, ALSourcef.Gain, value);
}
} }
#endregion #endregion
@ -84,15 +68,13 @@ namespace ANX.SoundSystem.OpenAL
internal OpenALSoundEffectInstance(OpenALSoundEffect setParent) internal OpenALSoundEffectInstance(OpenALSoundEffect setParent)
{ {
parent = setParent; parent = setParent;
State = SoundState.Stopped; State = SoundState.Stopped;
handle = AL.GenSource(); handle = AL.GenSource();
AL.Source(handle, ALSourcei.Buffer, parent.bufferHandle); AL.Source(handle, ALSourcei.Buffer, parent.bufferHandle);
IsLooped = false; IsLooped = false;
Pitch = 1f; Pitch = 1f;
Volume = 1f; Volume = 1f;
// TODO: Pan = 0f; Pan = 0f;
ALError error = AL.GetError(); ALError error = AL.GetError();
if (error != ALError.NoError) if (error != ALError.NoError)
@ -103,48 +85,45 @@ namespace ANX.SoundSystem.OpenAL
#region Play #region Play
public void Play() public void Play()
{ {
if (State != SoundState.Playing) if (State == SoundState.Playing)
{ return;
State = SoundState.Playing; State = SoundState.Playing;
AL.SourcePlay(handle); AL.SourcePlay(handle);
} }
}
#endregion #endregion
#region Pause #region Pause
public void Pause() public void Pause()
{ {
if (State != SoundState.Paused) if (State == SoundState.Paused)
{ return;
State = SoundState.Paused; State = SoundState.Paused;
AL.SourcePause(handle); AL.SourcePause(handle);
} }
}
#endregion #endregion
#region Stop #region Stop
public void Stop(bool immediate) public void Stop(bool immediate)
{ {
if (State == SoundState.Stopped) if (State == SoundState.Stopped || immediate == false)
return; return;
if (immediate)
{
State = SoundState.Stopped; State = SoundState.Stopped;
AL.SourceStop(handle); AL.SourceStop(handle);
} }
}
#endregion #endregion
#region Resume #region Resume
public void Resume() public void Resume()
{ {
if (State != SoundState.Playing) if (State == SoundState.Playing)
{ return;
State = SoundState.Playing; State = SoundState.Playing;
AL.SourcePlay(handle); AL.SourcePlay(handle);
} }
}
#endregion #endregion
#region Apply3D (TODO) #region Apply3D (TODO)

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using ANX.Framework.Audio; using ANX.Framework.Audio;
using ANX.Framework.Media;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using ANX.Framework.NonXNA.SoundSystem; using ANX.Framework.NonXNA.SoundSystem;
@ -164,5 +165,11 @@ namespace ANX.SoundSystem.PsVita
throw new NotImplementedException(); throw new NotImplementedException();
} }
#endregion #endregion
public ISong CreateSong(Song parentSong, Uri uri)
{
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
throw new NotImplementedException();
}
} }
} }

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using ANX.Framework.Audio; using ANX.Framework.Audio;
using ANX.Framework.Media;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using ANX.Framework.NonXNA.SoundSystem; using ANX.Framework.NonXNA.SoundSystem;
using SharpDX.XAudio2; using SharpDX.XAudio2;
@ -86,7 +87,10 @@ namespace ANX.SoundSystem.Windows.XAudio
~Creator() ~Creator()
{ {
if (MasteringVoice != null) if (MasteringVoice != null)
{
MasteringVoice.DestroyVoice();
MasteringVoice.Dispose(); MasteringVoice.Dispose();
}
if (device != null) if (device != null)
device.Dispose(); device.Dispose();
@ -144,6 +148,12 @@ namespace ANX.SoundSystem.Windows.XAudio
} }
public int GetDefaultMicrophone(ReadOnlyCollection<Microphone> allMicrophones) public int GetDefaultMicrophone(ReadOnlyCollection<Microphone> allMicrophones)
{
PreventSystemChange();
throw new NotImplementedException();
}
public ISong CreateSong(Song parentSong, Uri uri)
{ {
PreventSystemChange(); PreventSystemChange();
throw new NotImplementedException(); throw new NotImplementedException();

View File

@ -74,11 +74,17 @@ namespace ANX.SoundSystem.Windows.XAudio
currentPan = 0f; currentPan = 0f;
currentPitch = 1f; currentPitch = 1f;
State = SoundState.Stopped; State = SoundState.Stopped;
source = new SourceVoice(device, setParent.WaveFormat); source = new SourceVoice(device, setParent.WaveFormat, true);
source.SubmitSourceBuffer(setParent.AudioBuffer, setParent.DecodedPacketsInfo); source.SubmitSourceBuffer(setParent.AudioBuffer, setParent.DecodedPacketsInfo);
source.StreamEnd += StreamEnd;
} }
#endregion #endregion
private void StreamEnd()
{
State = SoundState.Stopped;
}
#region Play #region Play
public void Play() public void Play()
{ {
@ -94,6 +100,7 @@ namespace ANX.SoundSystem.Windows.XAudio
public void Pause() public void Pause()
{ {
State = SoundState.Paused; State = SoundState.Paused;
throw new NotImplementedException();
} }
#endregion #endregion
@ -115,6 +122,7 @@ namespace ANX.SoundSystem.Windows.XAudio
public void Resume() public void Resume()
{ {
State = SoundState.Playing; State = SoundState.Playing;
throw new NotImplementedException();
} }
#endregion #endregion
@ -182,7 +190,11 @@ namespace ANX.SoundSystem.Windows.XAudio
public void Dispose() public void Dispose()
{ {
if (source != null) if (source != null)
{
source.StreamEnd -= StreamEnd;
source.DestroyVoice();
source.Dispose(); source.Dispose();
}
source = null; source = null;
} }
#endregion #endregion