Skip to content

Commit

Permalink
Start Celt wrapping
Browse files Browse the repository at this point in the history
  • Loading branch information
Jklawreszuk committed Nov 7, 2024
1 parent 2a18ab9 commit 22643f4
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 161 deletions.
2 changes: 1 addition & 1 deletion deps/Celt/checkout.bat
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ IF NOT ERRORLEVEL 0 (
ECHO "Could not find git.exe"
EXIT /B %ERRORLEVEL%
)
%GIT_CMD% clone https://git.xiph.org/opus.git -b v1.1.3 ..\..\externals\Celt
git clone https://github.com/xiph/opus -b v1.1.3 ..\..\externals\Celt
if NOT ERRORLEVEL 0 pause
119 changes: 0 additions & 119 deletions sources/engine/Stride.Audio/Layers/Celt.cpp

This file was deleted.

127 changes: 86 additions & 41 deletions sources/engine/Stride.Audio/Layers/Celt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;

namespace Stride.Audio
{
/// <summary>
/// Wrapper around Celt
/// </summary>
internal class Celt : IDisposable
internal unsafe class Celt : IDisposable
{
public int SampleRate { get; set; }

public int BufferSize { get; set; }

public int Channels { get; set; }

private IntPtr celtPtr;
private OpusCustomMode* mode;
private OpusCustomEncoder* encoder;
private OpusCustomDecoder* decoder;

static Celt()
{
Expand All @@ -38,8 +39,8 @@ public Celt(int sampleRate, int bufferSize, int channels, bool decoderOnly)
SampleRate = sampleRate;
BufferSize = bufferSize;
Channels = channels;
celtPtr = xnCeltCreate(sampleRate, bufferSize, channels, decoderOnly);
if (celtPtr == IntPtr.Zero)
var result = xnCeltCreate(sampleRate, bufferSize, channels, decoderOnly);
if (result == false)
{
throw new Exception("Failed to create an instance of the celt encoder/decoder.");
}
Expand All @@ -51,11 +52,15 @@ public Celt(int sampleRate, int bufferSize, int channels, bool decoderOnly)
/// </summary>
public void Dispose()
{
if (celtPtr != IntPtr.Zero)
{
xnCeltDestroy(celtPtr);
celtPtr = IntPtr.Zero;
}
if (encoder != null)
opus_custom_encoder_destroy(encoder);
encoder = null;
if (decoder != null)
opus_custom_decoder_destroy(decoder);
decoder = null;
if (mode != null)
opus_custom_mode_destroy(mode);
mode = null;
}

/// <summary>
Expand All @@ -71,7 +76,7 @@ public unsafe int Decode(byte[] inputBuffer, int inputBufferSize, short[] output
fixed (short* samplesPtr = outputSamples)
fixed (byte* bufferPtr = inputBuffer)
{
return xnCeltDecodeShort(celtPtr, bufferPtr, inputBufferSize, samplesPtr, outputSamples.Length / Channels);
return opus_custom_decode(decoder, bufferPtr, inputBufferSize, samplesPtr, outputSamples.Length / Channels);
}
}

Expand All @@ -87,7 +92,7 @@ public unsafe int Decode(byte[] inputBuffer, int inputBufferSize, short* outputS
Debug.Assert((uint)inputBufferSize <= (uint)inputBuffer.Length);
fixed (byte* bufferPtr = inputBuffer)
{
return xnCeltDecodeShort(celtPtr, bufferPtr, inputBufferSize, outputSamples, BufferSize);
return opus_custom_decode(decoder, bufferPtr, inputBufferSize, outputSamples, BufferSize);
}
}

Expand All @@ -96,7 +101,7 @@ public unsafe int Decode(byte[] inputBuffer, int inputBufferSize, short* outputS
/// </summary>
public void ResetDecoder()
{
xnCeltResetDecoder(celtPtr);
opus_custom_decoder_ctl(decoder, (int)OpusRequest.ResetState);
}

/// <summary>
Expand All @@ -106,7 +111,7 @@ public void ResetDecoder()
public int GetDecoderSampleDelay()
{
var delay = 0;
if (xnCeltGetDecoderSampleDelay(celtPtr, ref delay) != 0)
if (xnCeltGetDecoderSampleDelay(decoder, ref delay) != 0)
delay = 0;
return delay;
}
Expand All @@ -122,7 +127,7 @@ public unsafe int Encode(short[] audioSamples, byte[] outputBuffer)
fixed (short* samplesPtr = audioSamples)
fixed (byte* bufferPtr = outputBuffer)
{
return xnCeltEncodeShort(celtPtr, samplesPtr, audioSamples.Length / Channels, bufferPtr, outputBuffer.Length);
return opus_custom_encode(encoder, samplesPtr, audioSamples.Length / Channels, bufferPtr, outputBuffer.Length);
}
}

Expand All @@ -138,7 +143,7 @@ public unsafe int Decode(byte[] inputBuffer, int inputBufferSize, float[] output
fixed (float* samplesPtr = outputSamples)
fixed (byte* bufferPtr = inputBuffer)
{
return xnCeltDecodeFloat(celtPtr, bufferPtr, inputBufferSize, samplesPtr, outputSamples.Length / Channels);
return opus_custom_decode_float(decoder, bufferPtr, inputBufferSize, samplesPtr, outputSamples.Length / Channels);
}
}

Expand All @@ -153,40 +158,80 @@ public unsafe int Encode(float[] audioSamples, byte[] outputBuffer)
fixed (float* samplesPtr = audioSamples)
fixed (byte* bufferPtr = outputBuffer)
{
return xnCeltEncodeFloat(celtPtr, samplesPtr, audioSamples.Length / Channels, bufferPtr, outputBuffer.Length);
return opus_custom_encode_float(encoder, samplesPtr, audioSamples.Length / Channels, bufferPtr, outputBuffer.Length);
}
}

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr xnCeltCreate(int sampleRate, int bufferSize, int channels, bool decoderOnly);
private bool xnCeltCreate(int sampleRate, int bufferSize, int channels, bool decoderOnly)
{
mode = opus_custom_mode_create(sampleRate, bufferSize, null);
if (mode == null) return false;

decoder = opus_custom_decoder_create(mode, channels, null);
if (decoder == null) return false;

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern void xnCeltDestroy(IntPtr celt);
if (!decoderOnly)
{
encoder = opus_custom_encoder_create(mode, channels, null);
if (encoder == null) return false;
}
return true;
}

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern int xnCeltResetDecoder(IntPtr celt);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern OpusCustomEncoder* opus_custom_encoder_create(OpusCustomMode* mode, int channels, int* error);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern int xnCeltGetDecoderSampleDelay(IntPtr celt, ref int delay);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern OpusCustomDecoder* opus_custom_decoder_create(OpusCustomMode* mode, int channels, int* error);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern unsafe int xnCeltEncodeFloat(IntPtr celt, float* inputSamples, int numberOfInputSamples, byte* outputBuffer, int maxOutputSize);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern OpusCustomMode* opus_custom_mode_create(int sampleRate, int bufferSize, int* error);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern unsafe int xnCeltDecodeFloat(IntPtr celt, byte* inputBuffer, int inputBufferSize, float* outputBuffer, int numberOfOutputSamples);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern int opus_custom_decoder_ctl(OpusCustomDecoder* decoder, int request, params nint[] args);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern unsafe int xnCeltEncodeShort(IntPtr celt, short* inputSamples, int numberOfInputSamples, byte* outputBuffer, int maxOutputSize);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern void opus_custom_encoder_destroy(OpusCustomEncoder* encoder);

[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern void opus_custom_decoder_destroy(OpusCustomDecoder* encoder);

[SuppressUnmanagedCodeSecurity]
[DllImport(NativeInvoke.Library, CallingConvention = CallingConvention.Cdecl)]
private static extern unsafe int xnCeltDecodeShort(IntPtr celt, byte* inputBuffer, int inputBufferSize, short* outputBuffer, int numberOfOutputSamples);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern void opus_custom_mode_destroy(OpusCustomMode* encoder);

[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern int opus_custom_encode_float(OpusCustomEncoder* encoder, float* inputSamples, int numberOfInputSamples, byte* outputBuffer, int maxOutputSize);

[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern int opus_custom_decode_float(OpusCustomDecoder* decoder, byte* inputBuffer, int inputBufferSize, float* outputBuffer, int numberOfOutputSamples);

[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern int opus_custom_encode(OpusCustomEncoder* encoder, short* inputSamples, int numberOfInputSamples, byte* outputBuffer, int maxOutputSize);

[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
private static extern int opus_custom_decode(OpusCustomDecoder* decoder, byte* inputBuffer, int inputBufferSize, short* outputBuffer, int numberOfOutputSamples);

private static int xnCeltGetDecoderSampleDelay(OpusCustomDecoder* decoder, ref int delay)
{
return opus_custom_decoder_ctl(decoder, (int)OpusRequest.LookAhead , delay);
}
}

internal enum OpusRequest
{
LookAhead = 4027,
ResetState = 4028
}

internal class OpusCustomEncoder
{
}

internal class OpusCustomDecoder
{
}

internal class OpusCustomMode
{
}
}

0 comments on commit 22643f4

Please sign in to comment.