forked from MoonsideGames/MoonWorks
fix static sound loading + window title
parent
adf047955e
commit
ec28d17a75
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace MoonWorks.Audio
|
namespace MoonWorks.Audio
|
||||||
|
@ -17,6 +18,8 @@ namespace MoonWorks.Audio
|
||||||
|
|
||||||
private FAudio.FAudioVoiceSends reverbSends;
|
private FAudio.FAudioVoiceSends reverbSends;
|
||||||
|
|
||||||
|
private readonly List<WeakReference<DynamicSoundInstance>> dynamicSoundInstances = new List<WeakReference<DynamicSoundInstance>>();
|
||||||
|
|
||||||
public unsafe AudioDevice()
|
public unsafe AudioDevice()
|
||||||
{
|
{
|
||||||
FAudio.FAudioCreate(out var handle, 0, 0);
|
FAudio.FAudioCreate(out var handle, 0, 0);
|
||||||
|
@ -177,16 +180,39 @@ namespace MoonWorks.Audio
|
||||||
|
|
||||||
/* Init reverb sends */
|
/* Init reverb sends */
|
||||||
|
|
||||||
reverbSends = new FAudio.FAudioVoiceSends();
|
reverbSends = new FAudio.FAudioVoiceSends
|
||||||
reverbSends.SendCount = 2;
|
{
|
||||||
reverbSends.pSends = Marshal.AllocHGlobal(
|
SendCount = 2,
|
||||||
2 * Marshal.SizeOf<FAudio.FAudioSendDescriptor>()
|
pSends = Marshal.AllocHGlobal(
|
||||||
);
|
2 * Marshal.SizeOf<FAudio.FAudioSendDescriptor>()
|
||||||
|
)
|
||||||
|
};
|
||||||
FAudio.FAudioSendDescriptor* sendDesc = (FAudio.FAudioSendDescriptor*) reverbSends.pSends;
|
FAudio.FAudioSendDescriptor* sendDesc = (FAudio.FAudioSendDescriptor*) reverbSends.pSends;
|
||||||
sendDesc[0].Flags = 0;
|
sendDesc[0].Flags = 0;
|
||||||
sendDesc[0].pOutputVoice = MasteringVoice;
|
sendDesc[0].pOutputVoice = MasteringVoice;
|
||||||
sendDesc[1].Flags = 0;
|
sendDesc[1].Flags = 0;
|
||||||
sendDesc[1].pOutputVoice = ReverbVoice;
|
sendDesc[1].pOutputVoice = ReverbVoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
for (var i = dynamicSoundInstances.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var weakReference = dynamicSoundInstances[i];
|
||||||
|
if (weakReference.TryGetTarget(out var dynamicSoundInstance))
|
||||||
|
{
|
||||||
|
dynamicSoundInstance.Update();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dynamicSoundInstances.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddDynamicSoundInstance(DynamicSoundInstance instance)
|
||||||
|
{
|
||||||
|
dynamicSoundInstances.Add(new WeakReference<DynamicSoundInstance>(instance));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,13 @@ using System.IO;
|
||||||
namespace MoonWorks.Audio
|
namespace MoonWorks.Audio
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For streaming long playback.
|
/// For streaming long playback. Reads an OGG file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DynamicSound : Sound, IDisposable
|
public class DynamicSound : Sound, IDisposable
|
||||||
{
|
{
|
||||||
|
internal override FAudio.FAudioWaveFormatEx Format { get; }
|
||||||
|
|
||||||
|
// FIXME: what should this value be?
|
||||||
public const int BUFFER_SIZE = 1024 * 128;
|
public const int BUFFER_SIZE = 1024 * 128;
|
||||||
|
|
||||||
internal IntPtr FileHandle { get; }
|
internal IntPtr FileHandle { get; }
|
||||||
|
@ -15,9 +18,7 @@ namespace MoonWorks.Audio
|
||||||
|
|
||||||
private bool IsDisposed;
|
private bool IsDisposed;
|
||||||
|
|
||||||
// FIXME: what should this value be?
|
public DynamicSound(AudioDevice device, FileInfo fileInfo) : base(device)
|
||||||
|
|
||||||
public DynamicSound(FileInfo fileInfo, ushort channels, uint samplesPerSecond) : base(channels, samplesPerSecond)
|
|
||||||
{
|
{
|
||||||
FileHandle = FAudio.stb_vorbis_open_filename(fileInfo.FullName, out var error, IntPtr.Zero);
|
FileHandle = FAudio.stb_vorbis_open_filename(fileInfo.FullName, out var error, IntPtr.Zero);
|
||||||
|
|
||||||
|
@ -28,6 +29,26 @@ namespace MoonWorks.Audio
|
||||||
}
|
}
|
||||||
|
|
||||||
Info = FAudio.stb_vorbis_get_info(FileHandle);
|
Info = FAudio.stb_vorbis_get_info(FileHandle);
|
||||||
|
|
||||||
|
var blockAlign = (ushort)(4 * Info.channels);
|
||||||
|
|
||||||
|
Format = new FAudio.FAudioWaveFormatEx
|
||||||
|
{
|
||||||
|
wFormatTag = 3,
|
||||||
|
wBitsPerSample = 32,
|
||||||
|
nChannels = (ushort) Info.channels,
|
||||||
|
nBlockAlign = blockAlign,
|
||||||
|
nSamplesPerSec = Info.sample_rate,
|
||||||
|
nAvgBytesPerSec = blockAlign * Info.sample_rate,
|
||||||
|
cbSize = 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public DynamicSoundInstance CreateInstance()
|
||||||
|
{
|
||||||
|
var instance = new DynamicSoundInstance(Device, this, false);
|
||||||
|
Device.AddDynamicSoundInstance(instance);
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace MoonWorks.Audio
|
||||||
|
|
||||||
public override SoundState State { get; protected set; }
|
public override SoundState State { get; protected set; }
|
||||||
|
|
||||||
public DynamicSoundInstance(
|
internal DynamicSoundInstance(
|
||||||
AudioDevice device,
|
AudioDevice device,
|
||||||
DynamicSound parent,
|
DynamicSound parent,
|
||||||
bool is3D
|
bool is3D
|
||||||
|
@ -26,6 +26,8 @@ namespace MoonWorks.Audio
|
||||||
queuedSizes = new List<uint>();
|
queuedSizes = new List<uint>();
|
||||||
|
|
||||||
buffer = new float[DynamicSound.BUFFER_SIZE];
|
buffer = new float[DynamicSound.BUFFER_SIZE];
|
||||||
|
|
||||||
|
State = SoundState.Stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Play()
|
public void Play()
|
||||||
|
@ -60,7 +62,7 @@ namespace MoonWorks.Audio
|
||||||
ClearBuffers();
|
ClearBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
internal void Update()
|
||||||
{
|
{
|
||||||
if (State != SoundState.Playing)
|
if (State != SoundState.Playing)
|
||||||
{
|
{
|
||||||
|
@ -117,7 +119,7 @@ namespace MoonWorks.Audio
|
||||||
buffer.Length
|
buffer.Length
|
||||||
);
|
);
|
||||||
|
|
||||||
IntPtr next = Marshal.AllocHGlobal(buffer.Length);
|
IntPtr next = Marshal.AllocHGlobal(buffer.Length * sizeof(float));
|
||||||
Marshal.Copy(buffer, 0, next, buffer.Length);
|
Marshal.Copy(buffer, 0, next, buffer.Length);
|
||||||
|
|
||||||
lock (queuedBuffers)
|
lock (queuedBuffers)
|
||||||
|
|
|
@ -2,25 +2,12 @@ namespace MoonWorks.Audio
|
||||||
{
|
{
|
||||||
public abstract class Sound
|
public abstract class Sound
|
||||||
{
|
{
|
||||||
internal FAudio.FAudioWaveFormatEx Format { get; }
|
internal AudioDevice Device { get; }
|
||||||
|
internal abstract FAudio.FAudioWaveFormatEx Format { get; }
|
||||||
|
|
||||||
/* NOTE: we only support float decoding! WAV sucks! */
|
public Sound(AudioDevice device)
|
||||||
public Sound(
|
{
|
||||||
ushort channels,
|
Device = device;
|
||||||
uint samplesPerSecond
|
|
||||||
) {
|
|
||||||
var blockAlign = (ushort) (4 * channels);
|
|
||||||
|
|
||||||
Format = new FAudio.FAudioWaveFormatEx
|
|
||||||
{
|
|
||||||
wFormatTag = 3,
|
|
||||||
wBitsPerSample = 32,
|
|
||||||
nChannels = channels,
|
|
||||||
nBlockAlign = blockAlign,
|
|
||||||
nSamplesPerSec = samplesPerSecond,
|
|
||||||
nAvgBytesPerSec = blockAlign * samplesPerSecond,
|
|
||||||
cbSize = 0
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,15 @@ namespace MoonWorks.Audio
|
||||||
{
|
{
|
||||||
public class StaticSound : Sound, IDisposable
|
public class StaticSound : Sound, IDisposable
|
||||||
{
|
{
|
||||||
|
internal override FAudio.FAudioWaveFormatEx Format { get; }
|
||||||
internal FAudio.FAudioBuffer Handle;
|
internal FAudio.FAudioBuffer Handle;
|
||||||
private bool IsDisposed;
|
|
||||||
|
|
||||||
public uint LoopStart { get; set; } = 0;
|
public uint LoopStart { get; set; } = 0;
|
||||||
public uint LoopLength { get; set; } = 0;
|
public uint LoopLength { get; set; } = 0;
|
||||||
|
|
||||||
public static StaticSound FromOgg(FileInfo fileInfo)
|
private bool IsDisposed;
|
||||||
|
|
||||||
|
public static StaticSound LoadOgg(AudioDevice device, FileInfo fileInfo)
|
||||||
{
|
{
|
||||||
var filePointer = FAudio.stb_vorbis_open_filename(fileInfo.FullName, out var error, IntPtr.Zero);
|
var filePointer = FAudio.stb_vorbis_open_filename(fileInfo.FullName, out var error, IntPtr.Zero);
|
||||||
|
|
||||||
|
@ -21,12 +23,20 @@ namespace MoonWorks.Audio
|
||||||
throw new AudioLoadException("Error loading file!");
|
throw new AudioLoadException("Error loading file!");
|
||||||
}
|
}
|
||||||
var info = FAudio.stb_vorbis_get_info(filePointer);
|
var info = FAudio.stb_vorbis_get_info(filePointer);
|
||||||
var bufferSize = (uint)(info.sample_rate * info.channels);
|
var bufferSize = FAudio.stb_vorbis_stream_length_in_samples(filePointer);
|
||||||
var buffer = new float[bufferSize];
|
var buffer = new float[bufferSize];
|
||||||
|
|
||||||
|
FAudio.stb_vorbis_get_samples_float_interleaved(
|
||||||
|
filePointer,
|
||||||
|
info.channels,
|
||||||
|
buffer,
|
||||||
|
(int) bufferSize
|
||||||
|
);
|
||||||
|
|
||||||
FAudio.stb_vorbis_close(filePointer);
|
FAudio.stb_vorbis_close(filePointer);
|
||||||
|
|
||||||
return new StaticSound(
|
return new StaticSound(
|
||||||
|
device,
|
||||||
buffer,
|
buffer,
|
||||||
0,
|
0,
|
||||||
(ushort) info.channels,
|
(ushort) info.channels,
|
||||||
|
@ -35,25 +45,42 @@ namespace MoonWorks.Audio
|
||||||
}
|
}
|
||||||
|
|
||||||
public StaticSound(
|
public StaticSound(
|
||||||
|
AudioDevice device,
|
||||||
float[] buffer,
|
float[] buffer,
|
||||||
uint bufferOffset,
|
uint bufferOffset,
|
||||||
ushort channels,
|
ushort channels,
|
||||||
uint samplesPerSecond
|
uint samplesPerSecond
|
||||||
) : base(channels, samplesPerSecond) {
|
) : base(device) {
|
||||||
var bufferLength = 4 * buffer.Length;
|
var blockAlign = (ushort)(4 * channels);
|
||||||
|
|
||||||
|
Format = new FAudio.FAudioWaveFormatEx
|
||||||
|
{
|
||||||
|
wFormatTag = 3,
|
||||||
|
wBitsPerSample = 32,
|
||||||
|
nChannels = channels,
|
||||||
|
nBlockAlign = blockAlign,
|
||||||
|
nSamplesPerSec = samplesPerSecond,
|
||||||
|
nAvgBytesPerSec = blockAlign * samplesPerSecond
|
||||||
|
};
|
||||||
|
|
||||||
|
var bufferLengthInBytes = sizeof(float) * buffer.Length;
|
||||||
|
|
||||||
Handle = new FAudio.FAudioBuffer();
|
Handle = new FAudio.FAudioBuffer();
|
||||||
Handle.Flags = FAudio.FAUDIO_END_OF_STREAM;
|
Handle.Flags = FAudio.FAUDIO_END_OF_STREAM;
|
||||||
Handle.pContext = IntPtr.Zero;
|
Handle.pContext = IntPtr.Zero;
|
||||||
Handle.AudioBytes = (uint) bufferLength;
|
Handle.AudioBytes = (uint) bufferLengthInBytes;
|
||||||
Handle.pAudioData = Marshal.AllocHGlobal((int) bufferLength);
|
Handle.pAudioData = Marshal.AllocHGlobal(bufferLengthInBytes);
|
||||||
Marshal.Copy(buffer, (int) bufferOffset, Handle.pAudioData, (int) bufferLength);
|
Marshal.Copy(buffer, (int) bufferOffset, Handle.pAudioData, buffer.Length);
|
||||||
Handle.PlayBegin = 0;
|
Handle.PlayBegin = 0;
|
||||||
Handle.PlayLength = (
|
Handle.PlayLength = 0;
|
||||||
Handle.AudioBytes /
|
|
||||||
(uint) Format.nChannels /
|
LoopStart = 0;
|
||||||
(uint) (Format.wBitsPerSample / 8)
|
LoopLength = 0;
|
||||||
);
|
}
|
||||||
|
|
||||||
|
public StaticSoundInstance CreateInstance()
|
||||||
|
{
|
||||||
|
return new StaticSoundInstance(Device, this, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace MoonWorks.Audio
|
||||||
) : base(device, parent, is3D)
|
) : base(device, parent, is3D)
|
||||||
{
|
{
|
||||||
Loop = loop;
|
Loop = loop;
|
||||||
|
State = SoundState.Stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Play()
|
public void Play()
|
||||||
|
|
|
@ -82,6 +82,7 @@ namespace MoonWorks
|
||||||
HandleSDLEvents();
|
HandleSDLEvents();
|
||||||
|
|
||||||
Input.Update();
|
Input.Update();
|
||||||
|
AudioDevice.Update();
|
||||||
|
|
||||||
Update(timestep);
|
Update(timestep);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace MoonWorks
|
||||||
ScreenMode = windowCreateInfo.ScreenMode;
|
ScreenMode = windowCreateInfo.ScreenMode;
|
||||||
|
|
||||||
Handle = SDL.SDL_CreateWindow(
|
Handle = SDL.SDL_CreateWindow(
|
||||||
"MoonWorks.GraphicsTest",
|
windowCreateInfo.WindowTitle,
|
||||||
SDL.SDL_WINDOWPOS_UNDEFINED,
|
SDL.SDL_WINDOWPOS_UNDEFINED,
|
||||||
SDL.SDL_WINDOWPOS_UNDEFINED,
|
SDL.SDL_WINDOWPOS_UNDEFINED,
|
||||||
(int)windowCreateInfo.WindowWidth,
|
(int)windowCreateInfo.WindowWidth,
|
||||||
|
|
|
@ -2,6 +2,7 @@ namespace MoonWorks
|
||||||
{
|
{
|
||||||
public struct WindowCreateInfo
|
public struct WindowCreateInfo
|
||||||
{
|
{
|
||||||
|
public string WindowTitle;
|
||||||
public uint WindowWidth;
|
public uint WindowWidth;
|
||||||
public uint WindowHeight;
|
public uint WindowHeight;
|
||||||
public ScreenMode ScreenMode;
|
public ScreenMode ScreenMode;
|
||||||
|
|
Loading…
Reference in New Issue