MoonWorks/src/Audio/StreamingSoundOgg.cs

100 lines
2.4 KiB
C#
Raw Normal View History

2022-02-23 05:14:32 +00:00
using System;
using System.IO;
2022-04-07 21:19:43 +00:00
using System.Runtime.InteropServices;
namespace MoonWorks.Audio
{
2022-02-23 05:14:32 +00:00
public class StreamingSoundOgg : StreamingSound
{
// FIXME: what should this value be?
public const int BUFFER_SIZE = 1024 * 128;
2022-04-07 21:19:43 +00:00
private IntPtr VorbisHandle;
private IntPtr FileDataPtr;
private FAudio.stb_vorbis_info Info;
2022-04-07 21:19:43 +00:00
private readonly float[] buffer; // currently decoded bytes
2022-02-23 05:14:32 +00:00
public override SoundState State { get; protected set; }
2022-04-07 21:19:43 +00:00
public static StreamingSoundOgg Load(AudioDevice device, string filePath)
2022-02-23 05:14:32 +00:00
{
2022-04-07 21:19:43 +00:00
var fileData = File.ReadAllBytes(filePath);
var fileDataPtr = Marshal.AllocHGlobal(fileData.Length);
Marshal.Copy(fileData, 0, fileDataPtr, fileData.Length);
2022-04-07 21:19:43 +00:00
var vorbisHandle = FAudio.stb_vorbis_open_memory(fileDataPtr, fileData.Length, out int error, IntPtr.Zero);
2022-02-23 05:14:32 +00:00
if (error != 0)
{
2022-04-07 21:19:43 +00:00
((GCHandle) fileDataPtr).Free();
2022-02-23 05:14:32 +00:00
Logger.LogError("Error opening OGG file!");
Logger.LogError("Error: " + error);
2022-02-23 05:14:32 +00:00
throw new AudioLoadException("Error opening OGG file!");
}
2022-04-07 21:19:43 +00:00
var info = FAudio.stb_vorbis_get_info(vorbisHandle);
2022-02-23 05:14:32 +00:00
return new StreamingSoundOgg(
device,
2022-04-07 21:19:43 +00:00
fileDataPtr,
vorbisHandle,
info
2022-02-23 05:14:32 +00:00
);
}
2022-02-23 05:14:32 +00:00
internal StreamingSoundOgg(
AudioDevice device,
IntPtr fileDataPtr, // MUST BE AN ALLOCHGLOBAL HANDLE!!
2022-04-07 21:19:43 +00:00
IntPtr vorbisHandle,
FAudio.stb_vorbis_info info
) : base(
device,
3, /* float type */
32, /* size of float */
(ushort) (4 * info.channels),
(ushort) info.channels,
2022-04-07 21:19:43 +00:00
info.sample_rate
)
2022-02-23 05:14:32 +00:00
{
2022-04-07 21:19:43 +00:00
FileDataPtr = fileDataPtr;
VorbisHandle = vorbisHandle;
2022-02-23 05:14:32 +00:00
Info = info;
buffer = new float[BUFFER_SIZE];
2022-02-23 05:14:32 +00:00
device.AddDynamicSoundInstance(this);
}
2022-02-23 05:14:32 +00:00
protected override void AddBuffer(
out float[] buffer,
out uint bufferOffset,
out uint bufferLength,
out bool reachedEnd
)
{
buffer = this.buffer;
2022-02-23 05:14:32 +00:00
/* NOTE: this function returns samples per channel, not total samples */
var samples = FAudio.stb_vorbis_get_samples_float_interleaved(
2022-04-07 21:19:43 +00:00
VorbisHandle,
2022-02-23 05:14:32 +00:00
Info.channels,
buffer,
buffer.Length
);
2022-02-23 05:14:32 +00:00
var sampleCount = samples * Info.channels;
bufferOffset = 0;
bufferLength = (uint) sampleCount;
reachedEnd = sampleCount < buffer.Length;
}
2022-02-23 05:14:32 +00:00
protected override void SeekStart()
{
2022-04-07 21:19:43 +00:00
FAudio.stb_vorbis_seek_start(VorbisHandle);
2022-02-23 05:14:32 +00:00
}
2022-02-23 05:14:32 +00:00
protected override void Destroy()
{
2022-04-07 21:19:43 +00:00
FAudio.stb_vorbis_close(VorbisHandle);
Marshal.FreeHGlobal(FileDataPtr);
2022-02-23 05:14:32 +00:00
}
}
}