implement StreamingSoundQoa
parent
2d7bb24b5c
commit
cee218a2dc
|
@ -1 +1 @@
|
|||
Subproject commit c42b6814c2550bd757b25b9387c0881eb4860af7
|
||||
Subproject commit 4f696ab0735927872b8227d3f335040c53876e3a
|
|
@ -0,0 +1,103 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MoonWorks.Audio
|
||||
{
|
||||
public class StreamingSoundQoa : StreamingSoundSeekable
|
||||
{
|
||||
private IntPtr QoaHandle;
|
||||
private IntPtr FileDataPtr;
|
||||
|
||||
protected override int BUFFER_SIZE { get; }
|
||||
public override bool AutoUpdate => true;
|
||||
|
||||
uint Channels;
|
||||
uint FrameSize;
|
||||
uint TotalSamplesPerChannel;
|
||||
|
||||
public unsafe static StreamingSoundQoa Load(AudioDevice device, string filePath)
|
||||
{
|
||||
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 qoaHandle = FAudio.qoa_open((char*) fileDataPtr, fileDataSpan.Length);
|
||||
if (qoaHandle == 0)
|
||||
{
|
||||
NativeMemory.Free(fileDataPtr);
|
||||
Logger.LogError("Error opening QOA file!");
|
||||
throw new AudioLoadException("Error opening QOA file!");
|
||||
}
|
||||
|
||||
FAudio.qoa_attributes(qoaHandle, out var frameSize, out var channels, out var sampleRate, out var totalSamplesPerChannel);
|
||||
|
||||
return new StreamingSoundQoa(
|
||||
device,
|
||||
(IntPtr) fileDataPtr,
|
||||
qoaHandle,
|
||||
channels,
|
||||
sampleRate,
|
||||
frameSize,
|
||||
totalSamplesPerChannel
|
||||
);
|
||||
}
|
||||
|
||||
internal unsafe StreamingSoundQoa(
|
||||
AudioDevice device,
|
||||
IntPtr fileDataPtr, // MUST BE A NATIVE MEMORY HANDLE!!
|
||||
IntPtr qoaHandle,
|
||||
uint channels,
|
||||
uint samplesPerSecond,
|
||||
uint frameSize,
|
||||
uint totalSamplesPerChannel
|
||||
) : base(
|
||||
device,
|
||||
1,
|
||||
16,
|
||||
(ushort) (2 * channels),
|
||||
(ushort) channels,
|
||||
samplesPerSecond
|
||||
) {
|
||||
FileDataPtr = fileDataPtr;
|
||||
QoaHandle = qoaHandle;
|
||||
Channels = channels;
|
||||
FrameSize = frameSize;
|
||||
TotalSamplesPerChannel = totalSamplesPerChannel;
|
||||
}
|
||||
|
||||
public override void Seek(uint sampleFrame)
|
||||
{
|
||||
FAudio.qoa_seek_frame(QoaHandle, (int) sampleFrame);
|
||||
}
|
||||
|
||||
protected override unsafe void FillBuffer(
|
||||
void* buffer,
|
||||
int bufferLengthInBytes,
|
||||
out int filledLengthInBytes,
|
||||
out bool reachedEnd
|
||||
) {
|
||||
var lengthInShorts = bufferLengthInBytes / sizeof(short);
|
||||
|
||||
// NOTE: this function returns samples per channel! */
|
||||
var samples = FAudio.qoa_decode_next_frame(QoaHandle, (short*) buffer);
|
||||
|
||||
var sampleCount = samples * Channels;
|
||||
reachedEnd = sampleCount < lengthInShorts;
|
||||
filledLengthInBytes = (int) (sampleCount * sizeof(short));
|
||||
}
|
||||
|
||||
protected override unsafe void Destroy()
|
||||
{
|
||||
base.Destroy();
|
||||
|
||||
if (!IsDisposed)
|
||||
{
|
||||
FAudio.qoa_close(QoaHandle);
|
||||
NativeMemory.Free((void*) FileDataPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue