fix static sound loading + window title

pull/14/head
cosmonaut 2021-01-19 21:33:25 -08:00
parent adf047955e
commit ec28d17a75
9 changed files with 110 additions and 44 deletions

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace MoonWorks.Audio
@ -17,6 +18,8 @@ namespace MoonWorks.Audio
private FAudio.FAudioVoiceSends reverbSends;
private readonly List<WeakReference<DynamicSoundInstance>> dynamicSoundInstances = new List<WeakReference<DynamicSoundInstance>>();
public unsafe AudioDevice()
{
FAudio.FAudioCreate(out var handle, 0, 0);
@ -177,16 +180,39 @@ namespace MoonWorks.Audio
/* Init reverb sends */
reverbSends = new FAudio.FAudioVoiceSends();
reverbSends.SendCount = 2;
reverbSends.pSends = Marshal.AllocHGlobal(
2 * Marshal.SizeOf<FAudio.FAudioSendDescriptor>()
);
reverbSends = new FAudio.FAudioVoiceSends
{
SendCount = 2,
pSends = Marshal.AllocHGlobal(
2 * Marshal.SizeOf<FAudio.FAudioSendDescriptor>()
)
};
FAudio.FAudioSendDescriptor* sendDesc = (FAudio.FAudioSendDescriptor*) reverbSends.pSends;
sendDesc[0].Flags = 0;
sendDesc[0].pOutputVoice = MasteringVoice;
sendDesc[1].Flags = 0;
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));
}
}
}

View File

@ -4,10 +4,13 @@ using System.IO;
namespace MoonWorks.Audio
{
/// <summary>
/// For streaming long playback.
/// For streaming long playback. Reads an OGG file.
/// </summary>
public class DynamicSound : Sound, IDisposable
{
internal override FAudio.FAudioWaveFormatEx Format { get; }
// FIXME: what should this value be?
public const int BUFFER_SIZE = 1024 * 128;
internal IntPtr FileHandle { get; }
@ -15,9 +18,7 @@ namespace MoonWorks.Audio
private bool IsDisposed;
// FIXME: what should this value be?
public DynamicSound(FileInfo fileInfo, ushort channels, uint samplesPerSecond) : base(channels, samplesPerSecond)
public DynamicSound(AudioDevice device, FileInfo fileInfo) : base(device)
{
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);
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)

View File

@ -16,7 +16,7 @@ namespace MoonWorks.Audio
public override SoundState State { get; protected set; }
public DynamicSoundInstance(
internal DynamicSoundInstance(
AudioDevice device,
DynamicSound parent,
bool is3D
@ -26,6 +26,8 @@ namespace MoonWorks.Audio
queuedSizes = new List<uint>();
buffer = new float[DynamicSound.BUFFER_SIZE];
State = SoundState.Stopped;
}
public void Play()
@ -60,7 +62,7 @@ namespace MoonWorks.Audio
ClearBuffers();
}
private void Update()
internal void Update()
{
if (State != SoundState.Playing)
{
@ -117,7 +119,7 @@ namespace MoonWorks.Audio
buffer.Length
);
IntPtr next = Marshal.AllocHGlobal(buffer.Length);
IntPtr next = Marshal.AllocHGlobal(buffer.Length * sizeof(float));
Marshal.Copy(buffer, 0, next, buffer.Length);
lock (queuedBuffers)

View File

@ -2,25 +2,12 @@ namespace MoonWorks.Audio
{
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(
ushort channels,
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
};
public Sound(AudioDevice device)
{
Device = device;
}
}
}

View File

@ -6,13 +6,15 @@ namespace MoonWorks.Audio
{
public class StaticSound : Sound, IDisposable
{
internal override FAudio.FAudioWaveFormatEx Format { get; }
internal FAudio.FAudioBuffer Handle;
private bool IsDisposed;
public uint LoopStart { 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);
@ -21,12 +23,20 @@ namespace MoonWorks.Audio
throw new AudioLoadException("Error loading file!");
}
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];
FAudio.stb_vorbis_get_samples_float_interleaved(
filePointer,
info.channels,
buffer,
(int) bufferSize
);
FAudio.stb_vorbis_close(filePointer);
return new StaticSound(
device,
buffer,
0,
(ushort) info.channels,
@ -35,25 +45,42 @@ namespace MoonWorks.Audio
}
public StaticSound(
AudioDevice device,
float[] buffer,
uint bufferOffset,
ushort channels,
uint samplesPerSecond
) : base(channels, samplesPerSecond) {
var bufferLength = 4 * buffer.Length;
) : base(device) {
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.Flags = FAudio.FAUDIO_END_OF_STREAM;
Handle.pContext = IntPtr.Zero;
Handle.AudioBytes = (uint) bufferLength;
Handle.pAudioData = Marshal.AllocHGlobal((int) bufferLength);
Marshal.Copy(buffer, (int) bufferOffset, Handle.pAudioData, (int) bufferLength);
Handle.AudioBytes = (uint) bufferLengthInBytes;
Handle.pAudioData = Marshal.AllocHGlobal(bufferLengthInBytes);
Marshal.Copy(buffer, (int) bufferOffset, Handle.pAudioData, buffer.Length);
Handle.PlayBegin = 0;
Handle.PlayLength = (
Handle.AudioBytes /
(uint) Format.nChannels /
(uint) (Format.wBitsPerSample / 8)
);
Handle.PlayLength = 0;
LoopStart = 0;
LoopLength = 0;
}
public StaticSoundInstance CreateInstance()
{
return new StaticSoundInstance(Device, this, false, true);
}
protected virtual void Dispose(bool disposing)

View File

@ -38,6 +38,7 @@ namespace MoonWorks.Audio
) : base(device, parent, is3D)
{
Loop = loop;
State = SoundState.Stopped;
}
public void Play()

View File

@ -82,6 +82,7 @@ namespace MoonWorks
HandleSDLEvents();
Input.Update();
AudioDevice.Update();
Update(timestep);

View File

@ -24,7 +24,7 @@ namespace MoonWorks
ScreenMode = windowCreateInfo.ScreenMode;
Handle = SDL.SDL_CreateWindow(
"MoonWorks.GraphicsTest",
windowCreateInfo.WindowTitle,
SDL.SDL_WINDOWPOS_UNDEFINED,
SDL.SDL_WINDOWPOS_UNDEFINED,
(int)windowCreateInfo.WindowWidth,

View File

@ -2,6 +2,7 @@ namespace MoonWorks
{
public struct WindowCreateInfo
{
public string WindowTitle;
public uint WindowWidth;
public uint WindowHeight;
public ScreenMode ScreenMode;