2022-02-23 05:14:32 +00:00
|
|
|
|
using System;
|
2021-01-20 20:39:31 +00:00
|
|
|
|
using System.IO;
|
2022-04-07 21:19:43 +00:00
|
|
|
|
using System.Runtime.InteropServices;
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
|
|
|
|
namespace MoonWorks.Audio
|
|
|
|
|
{
|
2022-08-02 21:04:12 +00:00
|
|
|
|
public class StreamingSoundOgg : StreamingSoundSeekable
|
2022-02-23 05:14:32 +00:00
|
|
|
|
{
|
2022-04-07 21:19:43 +00:00
|
|
|
|
private IntPtr VorbisHandle;
|
|
|
|
|
private IntPtr FileDataPtr;
|
|
|
|
|
private FAudio.stb_vorbis_info Info;
|
2023-03-07 23:28:57 +00:00
|
|
|
|
public override bool AutoUpdate => true;
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-08-02 21:04:12 +00:00
|
|
|
|
public unsafe static StreamingSoundOgg Load(AudioDevice device, string filePath)
|
2022-02-23 05:14:32 +00:00
|
|
|
|
{
|
2023-04-05 07:47:02 +00:00
|
|
|
|
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
|
|
|
|
|
var fileDataPtr = NativeMemory.Alloc((nuint) fileStream.Length);
|
|
|
|
|
var fileDataSpan = new Span<byte>(fileDataPtr, (int) fileStream.Length);
|
|
|
|
|
fileStream.ReadExactly(fileDataSpan);
|
|
|
|
|
fileStream.Close();
|
|
|
|
|
|
|
|
|
|
var vorbisHandle = FAudio.stb_vorbis_open_memory((IntPtr) fileDataPtr, fileDataSpan.Length, out int error, IntPtr.Zero);
|
2022-02-23 05:14:32 +00:00
|
|
|
|
if (error != 0)
|
|
|
|
|
{
|
2022-08-02 21:04:12 +00:00
|
|
|
|
NativeMemory.Free(fileDataPtr);
|
2022-02-23 05:14:32 +00:00
|
|
|
|
Logger.LogError("Error opening OGG file!");
|
2022-04-07 22:11:14 +00:00
|
|
|
|
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);
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
return new StreamingSoundOgg(
|
|
|
|
|
device,
|
2022-08-02 21:04:12 +00:00
|
|
|
|
(IntPtr) fileDataPtr,
|
2022-04-07 21:19:43 +00:00
|
|
|
|
vorbisHandle,
|
|
|
|
|
info
|
2022-02-23 05:14:32 +00:00
|
|
|
|
);
|
|
|
|
|
}
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2023-03-07 23:28:57 +00:00
|
|
|
|
internal unsafe StreamingSoundOgg(
|
2022-02-23 05:14:32 +00:00
|
|
|
|
AudioDevice device,
|
2022-08-02 21:04:12 +00:00
|
|
|
|
IntPtr fileDataPtr, // MUST BE A NATIVE MEMORY HANDLE!!
|
2022-04-07 21:19:43 +00:00
|
|
|
|
IntPtr vorbisHandle,
|
2023-05-05 22:26:32 +00:00
|
|
|
|
FAudio.stb_vorbis_info info,
|
|
|
|
|
uint bufferSize = 32768
|
2022-04-05 06:33:36 +00:00
|
|
|
|
) : base(
|
|
|
|
|
device,
|
|
|
|
|
3, /* float type */
|
|
|
|
|
32, /* size of float */
|
|
|
|
|
(ushort) (4 * info.channels),
|
|
|
|
|
(ushort) info.channels,
|
2023-05-05 22:26:32 +00:00
|
|
|
|
info.sample_rate,
|
|
|
|
|
bufferSize
|
2023-03-07 23:28:57 +00:00
|
|
|
|
) {
|
2022-04-07 21:19:43 +00:00
|
|
|
|
FileDataPtr = fileDataPtr;
|
|
|
|
|
VorbisHandle = vorbisHandle;
|
2022-02-23 05:14:32 +00:00
|
|
|
|
Info = info;
|
|
|
|
|
}
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-08-02 21:04:12 +00:00
|
|
|
|
public override void Seek(uint sampleFrame)
|
2022-04-20 21:29:46 +00:00
|
|
|
|
{
|
|
|
|
|
FAudio.stb_vorbis_seek(VorbisHandle, sampleFrame);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-02 21:04:12 +00:00
|
|
|
|
protected unsafe override void FillBuffer(
|
|
|
|
|
void* buffer,
|
|
|
|
|
int bufferLengthInBytes,
|
|
|
|
|
out int filledLengthInBytes,
|
2022-02-23 05:14:32 +00:00
|
|
|
|
out bool reachedEnd
|
2023-03-07 23:28:57 +00:00
|
|
|
|
) {
|
2022-08-02 21:04:12 +00:00
|
|
|
|
var lengthInFloats = bufferLengthInBytes / sizeof(float);
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
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,
|
2022-08-02 21:04:12 +00:00
|
|
|
|
(IntPtr) buffer,
|
|
|
|
|
lengthInFloats
|
2022-02-23 05:14:32 +00:00
|
|
|
|
);
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
var sampleCount = samples * Info.channels;
|
2022-08-02 21:04:12 +00:00
|
|
|
|
reachedEnd = sampleCount < lengthInFloats;
|
|
|
|
|
filledLengthInBytes = sampleCount * sizeof(float);
|
2022-02-23 05:14:32 +00:00
|
|
|
|
}
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-08-02 21:04:12 +00:00
|
|
|
|
protected unsafe override void Destroy()
|
2022-02-23 05:14:32 +00:00
|
|
|
|
{
|
2023-03-07 23:28:57 +00:00
|
|
|
|
base.Destroy();
|
|
|
|
|
|
|
|
|
|
if (!IsDisposed)
|
|
|
|
|
{
|
|
|
|
|
FAudio.stb_vorbis_close(VorbisHandle);
|
|
|
|
|
NativeMemory.Free((void*) FileDataPtr);
|
|
|
|
|
}
|
2022-02-23 05:14:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-20 20:39:31 +00:00
|
|
|
|
}
|