370 lines
13 KiB
C#
370 lines
13 KiB
C#
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using Microsoft.Xna.Framework;
|
|
#if WINDOWS
|
|
using OpenTK.Audio.OpenAL;
|
|
#endif
|
|
using OpenTK.Audio;
|
|
|
|
using System;
|
|
|
|
namespace Subsurface.Sounds
|
|
{
|
|
static class SoundManager
|
|
{
|
|
public const int DefaultSourceCount = 16;
|
|
|
|
private static List<int> alSources = new List<int>();
|
|
private static int[] alBuffers = new int[DefaultSourceCount];
|
|
private static int lowpassFilterId;
|
|
|
|
private static float overrideLowPassGain;
|
|
|
|
public static float OverrideLowPassGain
|
|
{
|
|
get { return overrideLowPassGain; }
|
|
set { overrideLowPassGain = MathHelper.Clamp(overrideLowPassGain, 0.0f, 1.0f); }
|
|
}
|
|
|
|
static AudioContext AC;
|
|
|
|
public static OggStreamer oggStreamer;
|
|
public static OggStream oggStream;
|
|
|
|
public static void Init()
|
|
{
|
|
AC = new AudioContext();
|
|
|
|
for (int i = 0 ; i < DefaultSourceCount; i++)
|
|
{
|
|
alSources.Add(OpenTK.Audio.OpenAL.AL.GenSource());
|
|
}
|
|
|
|
if (ALHelper.Efx.IsInitialized)
|
|
{
|
|
lowpassFilterId = ALHelper.Efx.GenFilter();
|
|
//alFilters.Add(alFilterId);
|
|
ALHelper.Efx.Filter(lowpassFilterId, OpenTK.Audio.OpenAL.EfxFilteri.FilterType, (int)OpenTK.Audio.OpenAL.EfxFilterType.Lowpass);
|
|
|
|
//LowPassHFGain = 1;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//public SoundManager(int bufferCount = DefaultSourceCount)
|
|
//{
|
|
// Stopwatch sw = new Stopwatch();
|
|
// sw.Start();
|
|
|
|
// alSourceId = AL.GenSource();
|
|
// //AL.Source(alSourceId, ALSourcei.Buffer, alBufferId);
|
|
|
|
// Volume = 1;
|
|
|
|
// if (ALHelper.Efx.IsInitialized)
|
|
// {
|
|
// alFilterId = ALHelper.Efx.GenFilter();
|
|
// ALHelper.Efx.Filter(alFilterId, EfxFilteri.FilterType, (int)EfxFilterType.Lowpass);
|
|
// ALHelper.Efx.Filter(alFilterId, EfxFilterf.LowpassGain, 1);
|
|
// LowPassHFGain = 1;
|
|
// }
|
|
|
|
// sw.Stop();
|
|
// System.Diagnostics.Debug.WriteLine("oggsource: "+sw.ElapsedMilliseconds);
|
|
|
|
//}
|
|
|
|
// public static int Play(Sound sound, float volume = 1.0f)
|
|
// {
|
|
// return Play(sound, volume, new Vector2(0.0f, 0.0f));
|
|
//}
|
|
|
|
public static int Play(Sound sound, float volume = 1.0f)
|
|
{
|
|
return Play(sound, Vector2.Zero, volume, 0.0f);
|
|
//for (int i = 2; i < DefaultSourceCount; i++)
|
|
//{
|
|
// AL.SourceStop(alSources[i]);
|
|
// AL.Source(alSources[i], ALSourceb.Looping, false);
|
|
// System.Diagnostics.Debug.WriteLine(i + ": " + AL.GetSourceState(alSources[i]));
|
|
// System.Diagnostics.Debug.WriteLine(AL.GetSourceType(alSources[i]));
|
|
//}
|
|
|
|
//for (int i = 1; i < DefaultSourceCount; i++)
|
|
//{
|
|
// //find a source that's free to use (not playing or paused)
|
|
// if (AL.GetSourceState(alSources[i]) == ALSourceState.Playing
|
|
// || AL.GetSourceState(alSources[i]) == ALSourceState.Paused) continue;
|
|
|
|
// //if (position!=Vector2.Zero)
|
|
// // position /= 1000.0f;
|
|
|
|
// alBuffers[i]=sound.AlBufferId;
|
|
// AL.Source(alSources[i], ALSourceb.Looping, false);
|
|
// AL.Source(alSources[i], ALSource3f.Position, 0.0f, 0.0f, 0.0f);
|
|
// AL.Source(alSources[i], ALSourcei.Buffer, sound.AlBufferId);
|
|
// AL.Source(alSources[i], ALSourcef.Gain, volume);
|
|
// //AL.Source(alSources[i], ALSource3f.Position, position.X, position.Y, 0.0f);
|
|
// AL.SourcePlay(alSources[i]);
|
|
|
|
// //sound.sourceIndex = i;
|
|
|
|
// return i;
|
|
//}
|
|
|
|
//return -1;
|
|
}
|
|
|
|
public static int Play(Sound sound, Vector2 position, float volume = 1.0f, float lowPassGain = 0.0f)
|
|
{
|
|
//for (int i = 2; i < DefaultSourceCount; i++)
|
|
//{
|
|
// AL.SourceStop(alSources[i]);
|
|
// AL.Source(alSources[i], ALSourceb.Looping, false);
|
|
// System.Diagnostics.Debug.WriteLine(i + ": " + AL.GetSourceState(alSources[i]));
|
|
// System.Diagnostics.Debug.WriteLine(AL.GetSourceType(alSources[i]));
|
|
//}
|
|
|
|
|
|
|
|
for (int i = 1; i < DefaultSourceCount; i++)
|
|
{
|
|
//find a source that's free to use (not playing or paused)
|
|
if (OpenTK.Audio.OpenAL.AL.GetSourceState(alSources[i]) == OpenTK.Audio.OpenAL.ALSourceState.Playing
|
|
|| OpenTK.Audio.OpenAL.AL.GetSourceState(alSources[i]) == OpenTK.Audio.OpenAL.ALSourceState.Paused) continue;
|
|
|
|
//if (position!=Vector2.Zero)
|
|
// position /= 1000.0f;
|
|
|
|
alBuffers[i] = sound.AlBufferId;
|
|
OpenTK.Audio.OpenAL.AL.Source(alSources[i], OpenTK.Audio.OpenAL.ALSourceb.Looping, false);
|
|
|
|
position /= 1000.0f;
|
|
|
|
//System.Diagnostics.Debug.WriteLine("updatesoundpos: "+offset);
|
|
OpenTK.Audio.OpenAL.AL.Source(alSources[i], OpenTK.Audio.OpenAL.ALSourcef.Gain, volume);
|
|
OpenTK.Audio.OpenAL.AL.Source(alSources[i], OpenTK.Audio.OpenAL.ALSource3f.Position, position.X, position.Y, 0.0f);
|
|
|
|
OpenTK.Audio.OpenAL.AL.Source(alSources[i], OpenTK.Audio.OpenAL.ALSourcei.Buffer, sound.AlBufferId);
|
|
|
|
ALHelper.Efx.Filter(lowpassFilterId, OpenTK.Audio.OpenAL.EfxFilterf.LowpassGainHF, lowPassHfGain = Math.Min(lowPassGain, overrideLowPassGain));
|
|
ALHelper.Efx.BindFilterToSource(alSources[i], lowpassFilterId);
|
|
ALHelper.Check();
|
|
|
|
//AL.Source(alSources[i], ALSource3f.Position, position.X, position.Y, 0.0f);
|
|
OpenTK.Audio.OpenAL.AL.SourcePlay(alSources[i]);
|
|
|
|
//sound.sourceIndex = i;
|
|
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
public static int Loop(Sound sound, int sourceIndex, float volume = 1.0f)
|
|
{
|
|
return Loop(sound,sourceIndex, Vector2.Zero, volume, 0.0f);
|
|
}
|
|
public static int Loop(Sound sound, int sourceIndex, Vector2 position, float volume = 1.0f, float lowPassGain = 0.0f)
|
|
{
|
|
if (sourceIndex<1)
|
|
{
|
|
sourceIndex = Play(sound, position, volume, lowPassGain);
|
|
if (sourceIndex>0)
|
|
{
|
|
AL.Source(alSources[sourceIndex], ALSourceb.Looping, true);
|
|
AL.Source(alSources[sourceIndex], ALSourcef.Gain, volume);
|
|
}
|
|
ALHelper.Check();
|
|
return sourceIndex;
|
|
}
|
|
else
|
|
{
|
|
AL.Source(alSources[sourceIndex], ALSourceb.Looping, true);
|
|
AL.Source(alSources[sourceIndex], ALSourcef.Gain, volume);
|
|
ALHelper.Check();
|
|
return sourceIndex;
|
|
}
|
|
}
|
|
|
|
//public static int Loop(int sourceIndex, float volume = 1.0f)
|
|
//{
|
|
|
|
// if (sourceIndex > 0 && alSources[sourceIndex]>0)
|
|
// {
|
|
// ALSourceState state = AL.GetSourceState(alSources[sourceIndex]);
|
|
// ALHelper.Check();
|
|
// if (state == ALSourceState.Playing) return sourceIndex;
|
|
// }
|
|
|
|
// int newSourceIndex = Play(sound, volume);
|
|
// AL.Source(alSources[sourceIndex], ALSourceb.Looping, true);
|
|
|
|
// return sourceIndex;
|
|
//}
|
|
|
|
public static void Pause(int sourceIndex)
|
|
{
|
|
if (AL.GetSourceState(alSources[sourceIndex]) != ALSourceState.Playing)
|
|
return;
|
|
|
|
AL.SourcePause(alSources[sourceIndex]);
|
|
ALHelper.Check();
|
|
}
|
|
|
|
public static void Resume(int sourceIndex)
|
|
{
|
|
if (AL.GetSourceState(alSources[sourceIndex]) != ALSourceState.Paused)
|
|
return;
|
|
|
|
Debug.WriteLine("sourceplay");
|
|
AL.SourcePlay(alSources[sourceIndex]);
|
|
ALHelper.Check();
|
|
}
|
|
|
|
public static void Stop(int sourceIndex)
|
|
{
|
|
if (sourceIndex < 1) return;
|
|
|
|
var state = AL.GetSourceState(alSources[sourceIndex]);
|
|
if (state == ALSourceState.Playing || state == ALSourceState.Paused)
|
|
{
|
|
AL.SourceStop(alSources[sourceIndex]);
|
|
AL.Source(alSources[sourceIndex], ALSourceb.Looping, false);
|
|
}
|
|
}
|
|
|
|
public static bool IsPlaying(int sourceIndex)
|
|
{
|
|
if (sourceIndex < 1 || sourceIndex>alSources.Count-1) return false;
|
|
var state = AL.GetSourceState(alSources[sourceIndex]);
|
|
return (state == ALSourceState.Playing);
|
|
}
|
|
|
|
public static void Volume(int sourceIndex, float volume)
|
|
{
|
|
AL.Source(alSources[sourceIndex], ALSourcef.Gain, volume);
|
|
ALHelper.Check();
|
|
}
|
|
|
|
//int alFilterId;
|
|
|
|
static float lowPassHfGain;
|
|
public static float LowPassHFGain
|
|
{
|
|
get { return lowPassHfGain; }
|
|
set
|
|
{
|
|
if (ALHelper.Efx.IsInitialized)
|
|
{
|
|
overrideLowPassGain = value;
|
|
for (int i = 0; i < DefaultSourceCount; i++)
|
|
{
|
|
//find a source that's free to use (not playing or paused)
|
|
if (OpenTK.Audio.OpenAL.AL.GetSourceState(alSources[i]) != OpenTK.Audio.OpenAL.ALSourceState.Playing
|
|
&& OpenTK.Audio.OpenAL.AL.GetSourceState(alSources[i])!= OpenTK.Audio.OpenAL.ALSourceState.Paused) continue;
|
|
|
|
ALHelper.Efx.Filter(lowpassFilterId, OpenTK.Audio.OpenAL.EfxFilterf.LowpassGainHF, lowPassHfGain = value);
|
|
ALHelper.Efx.BindFilterToSource(alSources[i], lowpassFilterId);
|
|
ALHelper.Check();
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//float volume;
|
|
//public float Volume
|
|
//{
|
|
// get { return volume; }
|
|
// set
|
|
// {
|
|
// AL.Source(alSourceId, ALSourcef.Gain, volume = value);
|
|
// ALHelper.Check();
|
|
// }
|
|
//}
|
|
|
|
public static void UpdateSoundPosition(int sourceIndex, Vector2 position, float baseVolume = 1.0f, float lowPassGain = 0.0f)
|
|
{
|
|
if (sourceIndex < 1) return;
|
|
|
|
//Resume(sourceIndex);
|
|
|
|
position/= 1000.0f;
|
|
|
|
//System.Diagnostics.Debug.WriteLine("updatesoundpos: "+offset);
|
|
OpenTK.Audio.OpenAL.AL.Source(alSources[sourceIndex], OpenTK.Audio.OpenAL.ALSourcef.Gain, baseVolume);
|
|
OpenTK.Audio.OpenAL.AL.Source(alSources[sourceIndex], OpenTK.Audio.OpenAL.ALSource3f.Position, position.X, position.Y, 0.0f);
|
|
|
|
ALHelper.Efx.Filter(lowpassFilterId, OpenTK.Audio.OpenAL.EfxFilterf.LowpassGainHF, lowPassHfGain = Math.Min(lowPassGain, overrideLowPassGain));
|
|
ALHelper.Efx.BindFilterToSource(alSources[sourceIndex], lowpassFilterId);
|
|
ALHelper.Check();
|
|
}
|
|
|
|
public static OggStream StartStream(string file, float volume = 1.0f)
|
|
{
|
|
if (oggStreamer == null)
|
|
oggStreamer = new OggStreamer();
|
|
|
|
oggStream = new OggStream(file);
|
|
|
|
oggStreamer.AddStream(oggStream);
|
|
|
|
oggStream.Volume = volume;
|
|
|
|
oggStream.Play();
|
|
|
|
return oggStream;
|
|
}
|
|
|
|
public static void StopStream()
|
|
{
|
|
if (oggStream!=null) oggStream.Stop();
|
|
}
|
|
|
|
public static void ClearAlSource(int bufferId)
|
|
{
|
|
for (int i = 1; i < DefaultSourceCount; i++)
|
|
{
|
|
if (alBuffers[i] == bufferId)
|
|
{
|
|
OpenTK.Audio.OpenAL.AL.Source(alSources[i], OpenTK.Audio.OpenAL.ALSourcei.Buffer, 0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
public static void Dispose()
|
|
{
|
|
if (ALHelper.Efx.IsInitialized)
|
|
ALHelper.Efx.DeleteFilter(lowpassFilterId);
|
|
|
|
for (int i = 0; i < DefaultSourceCount; i++)
|
|
{
|
|
var state = OpenTK.Audio.OpenAL.AL.GetSourceState(alSources[i]);
|
|
if (state == OpenTK.Audio.OpenAL.ALSourceState.Playing || state == OpenTK.Audio.OpenAL.ALSourceState.Paused)
|
|
Stop(i);
|
|
|
|
OpenTK.Audio.OpenAL.AL.DeleteSource(alSources[i]);
|
|
|
|
ALHelper.Check();
|
|
}
|
|
|
|
if (oggStream!=null)
|
|
{
|
|
oggStream.Stop();
|
|
oggStream.Dispose();
|
|
}
|
|
|
|
if (oggStreamer != null)
|
|
oggStreamer.Dispose();
|
|
}
|
|
|
|
}
|
|
}
|