97 lines
4 KiB
C#
97 lines
4 KiB
C#
|
using System;
|
|||
|
using Normal.Realtime.Native;
|
|||
|
|
|||
|
namespace Normal.Realtime.Native {
|
|||
|
public class AudioOutputStream : IDisposable {
|
|||
|
// Pointer to native class
|
|||
|
private IntPtr _nativeAudioOutputStream = IntPtr.Zero;
|
|||
|
private IntPtr _nativeAudioOutputStreamIdentifier = IntPtr.Zero;
|
|||
|
public bool AudioOutputStreamMatchesIdentifier(IntPtr nativeAudioOutputStreamIdentifier) {
|
|||
|
return _nativeAudioOutputStreamIdentifier != IntPtr.Zero && nativeAudioOutputStreamIdentifier == _nativeAudioOutputStreamIdentifier;
|
|||
|
}
|
|||
|
|
|||
|
// Instance
|
|||
|
public AudioOutputStream(IntPtr nativeAudioOutputStream, IntPtr nativeAudioOutputStreamIdentifier) {
|
|||
|
_nativeAudioOutputStream = nativeAudioOutputStream;
|
|||
|
_nativeAudioOutputStreamIdentifier = nativeAudioOutputStreamIdentifier;
|
|||
|
}
|
|||
|
|
|||
|
// NOTE: This may not be called on the same thread that we created the native room with. It's recommended Dispose() is called manually to prevent any issues.
|
|||
|
~AudioOutputStream() {
|
|||
|
// Clean up unmanaged code
|
|||
|
Dispose(false);
|
|||
|
}
|
|||
|
|
|||
|
// Ideally called whenever someone is done using an audio source.
|
|||
|
public void Dispose() {
|
|||
|
Dispose(true);
|
|||
|
GC.SuppressFinalize(this);
|
|||
|
}
|
|||
|
|
|||
|
void Dispose(bool disposing) {
|
|||
|
if (_nativeAudioOutputStream != IntPtr.Zero) {
|
|||
|
Plugin.ClientDeleteAudioOutputStream(_nativeAudioOutputStream);
|
|||
|
_nativeAudioOutputStream = IntPtr.Zero;
|
|||
|
_nativeAudioOutputStreamIdentifier = IntPtr.Zero;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public bool nativePointerIsNull { get { return _nativeAudioOutputStream == IntPtr.Zero; } }
|
|||
|
|
|||
|
// Metadata
|
|||
|
public int ClientID() {
|
|||
|
if (_nativeAudioOutputStream == IntPtr.Zero)
|
|||
|
throw RealtimeNativeException.NativePointerIsNull("AudioOutputStream");
|
|||
|
|
|||
|
// TODO: It might be worth caching this if the calls are expensive
|
|||
|
return Plugin.AudioOutputStreamGetClientID(_nativeAudioOutputStream);
|
|||
|
}
|
|||
|
|
|||
|
public int StreamID() {
|
|||
|
if (_nativeAudioOutputStream == IntPtr.Zero)
|
|||
|
throw RealtimeNativeException.NativePointerIsNull("AudioOutputStream");
|
|||
|
|
|||
|
// TODO: It might be worth caching this if the calls are expensive
|
|||
|
return Plugin.AudioOutputStreamGetStreamID(_nativeAudioOutputStream);
|
|||
|
}
|
|||
|
|
|||
|
public int SampleRate() {
|
|||
|
if (_nativeAudioOutputStream == IntPtr.Zero)
|
|||
|
throw RealtimeNativeException.NativePointerIsNull("AudioOutputStream");
|
|||
|
|
|||
|
return Plugin.AudioOutputStreamGetSampleRate(_nativeAudioOutputStream);
|
|||
|
}
|
|||
|
|
|||
|
// Set desired sample rate. Native plugin will resample to it automatically.
|
|||
|
// Set to 0.0f to reset it back to the sample rate that's sent from the server.
|
|||
|
public void SetSampleRate(int sampleRate) {
|
|||
|
if (_nativeAudioOutputStream == IntPtr.Zero)
|
|||
|
throw RealtimeNativeException.NativePointerIsNull("AudioOutputStream");
|
|||
|
|
|||
|
Plugin.AudioOutputStreamSetSampleRate(_nativeAudioOutputStream, sampleRate);
|
|||
|
}
|
|||
|
|
|||
|
public int Channels() {
|
|||
|
if (_nativeAudioOutputStream == IntPtr.Zero)
|
|||
|
throw RealtimeNativeException.NativePointerIsNull("AudioOutputStream");
|
|||
|
|
|||
|
return Plugin.AudioOutputStreamGetChannels(_nativeAudioOutputStream);
|
|||
|
}
|
|||
|
|
|||
|
public bool IsOpen() {
|
|||
|
if (_nativeAudioOutputStream == IntPtr.Zero)
|
|||
|
return false;
|
|||
|
|
|||
|
return Plugin.AudioOutputStreamGetIsOpen(_nativeAudioOutputStream) != 0;
|
|||
|
}
|
|||
|
|
|||
|
public bool GetAudioData(float[] audioData) {
|
|||
|
if (_nativeAudioOutputStream == IntPtr.Zero)
|
|||
|
throw RealtimeNativeException.NativePointerIsNull("AudioOutputStream");
|
|||
|
|
|||
|
// TODO: Fix this
|
|||
|
return Plugin.AudioOutputStreamGetAudioData(_nativeAudioOutputStream, audioData, audioData.Length) > 0;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|