2022-02-23 05:14:32 +00:00
|
|
|
|
using System;
|
2021-01-20 20:39:31 +00:00
|
|
|
|
using System.IO;
|
|
|
|
|
|
|
|
|
|
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;
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
internal IntPtr FileHandle { get; }
|
|
|
|
|
internal FAudio.stb_vorbis_info Info { get; }
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
private readonly float[] buffer;
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
public override SoundState State { get; protected set; }
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
public static StreamingSoundOgg Load(
|
|
|
|
|
AudioDevice device,
|
|
|
|
|
string filePath,
|
|
|
|
|
bool is3D = false,
|
|
|
|
|
bool loop = false
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
var fileHandle = FAudio.stb_vorbis_open_filename(filePath, out var error, IntPtr.Zero);
|
|
|
|
|
if (error != 0)
|
|
|
|
|
{
|
|
|
|
|
Logger.LogError("Error opening OGG file!");
|
|
|
|
|
throw new AudioLoadException("Error opening OGG file!");
|
|
|
|
|
}
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
var info = FAudio.stb_vorbis_get_info(fileHandle);
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
return new StreamingSoundOgg(
|
|
|
|
|
device,
|
|
|
|
|
fileHandle,
|
|
|
|
|
info,
|
|
|
|
|
is3D,
|
|
|
|
|
loop
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
internal StreamingSoundOgg(
|
|
|
|
|
AudioDevice device,
|
|
|
|
|
IntPtr fileHandle,
|
|
|
|
|
FAudio.stb_vorbis_info info,
|
|
|
|
|
bool is3D,
|
|
|
|
|
bool loop
|
2022-04-05 06:33:36 +00:00
|
|
|
|
) : base(
|
|
|
|
|
device,
|
|
|
|
|
3, /* float type */
|
|
|
|
|
32, /* size of float */
|
|
|
|
|
(ushort) (4 * info.channels),
|
|
|
|
|
(ushort) info.channels,
|
|
|
|
|
info.sample_rate,
|
|
|
|
|
is3D,
|
|
|
|
|
loop
|
|
|
|
|
)
|
2022-02-23 05:14:32 +00:00
|
|
|
|
{
|
|
|
|
|
FileHandle = fileHandle;
|
|
|
|
|
Info = info;
|
|
|
|
|
buffer = new float[BUFFER_SIZE];
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
device.AddDynamicSoundInstance(this);
|
|
|
|
|
}
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
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;
|
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(
|
|
|
|
|
FileHandle,
|
|
|
|
|
Info.channels,
|
|
|
|
|
buffer,
|
|
|
|
|
buffer.Length
|
|
|
|
|
);
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
var sampleCount = samples * Info.channels;
|
|
|
|
|
bufferOffset = 0;
|
|
|
|
|
bufferLength = (uint) sampleCount;
|
|
|
|
|
reachedEnd = sampleCount < buffer.Length;
|
|
|
|
|
}
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
protected override void SeekStart()
|
|
|
|
|
{
|
|
|
|
|
FAudio.stb_vorbis_seek_start(FileHandle);
|
|
|
|
|
}
|
2021-01-20 20:39:31 +00:00
|
|
|
|
|
2022-02-23 05:14:32 +00:00
|
|
|
|
protected override void Destroy()
|
|
|
|
|
{
|
|
|
|
|
FAudio.stb_vorbis_close(FileHandle);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-20 20:39:31 +00:00
|
|
|
|
}
|