Created
January 25, 2020 20:54
-
-
Save ForeverZer0/1d66f9c4660fe106475f0be9e7078657 to your computer and use it in GitHub Desktop.
Minimal bindings for the libsndfile library.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics.CodeAnalysis; | |
using System.IO; | |
using System.Runtime.InteropServices; | |
using System.Security; | |
using System.Text; | |
namespace SndFile | |
{ | |
[SuppressUnmanagedCodeSecurity] | |
[SuppressMessage("ReSharper", "InconsistentNaming")] | |
[SuppressMessage("ReSharper", "IdentifierTypo")] | |
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] | |
public static class libsndfile | |
{ | |
private const string LIBRARY = "sndfile"; | |
public delegate sf_count_t sf_vio_get_filelen(IntPtr user); | |
public delegate sf_count_t sf_vio_seek(sf_count_t offset, SeekOrigin whence, IntPtr user); | |
public delegate sf_count_t sf_vio_read(IntPtr ptr, sf_count_t count, IntPtr user); | |
public delegate sf_count_t sf_vio_write(IntPtr ptr, sf_count_t count, IntPtr user); | |
public delegate sf_count_t sf_vio_tell(IntPtr user); | |
[StructLayout(LayoutKind.Sequential)] | |
public struct sf_count_t | |
{ | |
private readonly UIntPtr value; | |
public sf_count_t(int value) | |
{ | |
if (value < 0) | |
throw new ArgumentOutOfRangeException(nameof(value), "Size must be 0 or greater."); | |
this.value = new UIntPtr((uint) value); | |
} | |
public sf_count_t(long value) | |
{ | |
if (value < 0) | |
throw new ArgumentOutOfRangeException(nameof(value), "Size must be 0 or greater."); | |
this.value = new UIntPtr((ulong) value); | |
} | |
[CLSCompliant(false)] | |
public sf_count_t(uint value) | |
{ | |
this.value = new UIntPtr(value); | |
} | |
[CLSCompliant(false)] | |
public sf_count_t(ulong value) | |
{ | |
this.value = new UIntPtr(value); | |
} | |
public long Value => Convert.ToInt64(value.ToUInt64()); | |
} | |
public struct SF_VIRTUAL_IO | |
{ | |
sf_vio_get_filelen get_filelen; | |
sf_vio_seek seek; | |
sf_vio_read read; | |
sf_vio_write write; | |
sf_vio_tell tell; | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
public struct SF_INFO | |
{ | |
public readonly sf_count_t frames; | |
public readonly int samplerate; | |
public readonly int channels; | |
public readonly int format; | |
public readonly int sections; | |
public readonly int seekable; | |
} | |
/// <summary> | |
/// Opaque type used as a handle to a native audio stream. | |
/// </summary> | |
[StructLayout(LayoutKind.Sequential)] | |
public struct SNDFILE | |
{ | |
/// <summary> | |
/// The native handle, used to enforce pointer size for the structure to use without ref | |
/// </summary> | |
private readonly IntPtr handle; | |
} | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
private static extern SNDFILE sf_open(byte[] path, FileAccess mode, out SF_INFO info); // TODO: Mode | |
public static SNDFILE sf_open(string path, FileAccess mode, out SF_INFO info) | |
{ | |
var bytes = Encoding.UTF8.GetBytes(path); | |
return sf_open(bytes, mode, out info); | |
} | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern SNDFILE sf_open_virtual(SF_VIRTUAL_IO io, FileAccess mode, out SF_INFO info, IntPtr user); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool sf_format_check(ref SF_INFO info); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_seek(SNDFILE sndfile, sf_count_t frames, SeekOrigin whence); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern SF_ERROR sf_error(SNDFILE sndfile); // TODO: Error Code | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern int sf_close(SNDFILE sndfile); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl, EntryPoint = "sf_strerror")] | |
private static extern IntPtr sf_strerror_ptr(SNDFILE sndfile); | |
public static string sf_strerror(SNDFILE sndfile) => Marshal.PtrToStringUTF8(sf_strerror_ptr(sndfile)); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl, EntryPoint = "sf_error_number")] | |
private static extern IntPtr sf_error_number_ptr(int error); | |
public static string sf_error_number(SF_ERROR error) => | |
Marshal.PtrToStringUTF8(sf_error_number_ptr((int) error)); | |
public static string sf_error_number(int error) => Marshal.PtrToStringUTF8(sf_error_number_ptr(error)); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern void sf_write_sync(SNDFILE sndfile); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_read_short(SNDFILE sndfile, IntPtr ptr, sf_count_t items); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_read_int(SNDFILE sndfile, IntPtr ptr, sf_count_t items); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_read_float(SNDFILE sndfile, IntPtr ptr, sf_count_t items); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_read_double(SNDFILE sndfile, IntPtr ptr, sf_count_t items); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_readf_short(SNDFILE sndfile, IntPtr ptr, sf_count_t frames); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_readf_int(SNDFILE sndfile, IntPtr ptr, sf_count_t frames); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_readf_float(SNDFILE sndfile, IntPtr ptr, sf_count_t frames); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_readf_double(SNDFILE sndfile, IntPtr ptr, sf_count_t frames); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_write_short(SNDFILE sndfile, IntPtr ptr, sf_count_t items); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_write_int(SNDFILE sndfile, IntPtr ptr, sf_count_t items); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_write_float(SNDFILE sndfile, IntPtr ptr, sf_count_t items); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_write_double(SNDFILE sndfile, IntPtr ptr, sf_count_t items); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_writef_short(SNDFILE sndfile, IntPtr ptr, sf_count_t frames); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_writef_int(SNDFILE sndfile, IntPtr ptr, sf_count_t frames); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_writef_float(SNDFILE sndfile, IntPtr ptr, sf_count_t frames); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_writef_double(SNDFILE sndfile, IntPtr ptr, sf_count_t frames); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_read_raw(SNDFILE sndfile, IntPtr ptr, sf_count_t bytes); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern sf_count_t sf_write_raw(SNDFILE sndfile, IntPtr ptr, sf_count_t bytes); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl, EntryPoint = "sf_get_string")] | |
private static extern IntPtr sf_get_string_ptr(SNDFILE sndfile, int type); | |
public static string sf_get_string(SNDFILE sndfile, int type) => | |
Marshal.PtrToStringUTF8(sf_get_string_ptr(sndfile, type)); | |
public static string sf_get_string(SNDFILE sndfile, SF_STR type) => | |
Marshal.PtrToStringUTF8(sf_get_string_ptr(sndfile, (int) type)); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl, EntryPoint = "sf_set_string")] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool sf_set_string_ptr(SNDFILE file, int type, byte[] str); | |
public static bool sf_set_string(SNDFILE file, int type, string str) | |
{ | |
var bytes = Encoding.UTF8.GetBytes(str); | |
return sf_set_string_ptr(file, type, bytes); | |
} | |
public static bool sf_set_string(SNDFILE file, SF_STR type, string str) => sf_set_string(file, (int) type, str); | |
[DllImport(LIBRARY, CallingConvention = CallingConvention.Cdecl)] | |
public static extern int sf_command(SNDFILE sndfile, int cmd, IntPtr data, int datasize); | |
public enum SFC_COMMAND | |
{ | |
SFC_GET_LIB_VERSION = 0x1000, | |
SFC_GET_LOG_INFO = 0x1001, | |
SFC_GET_CURRENT_SF_INFO = 0x1002, | |
SFC_GET_NORM_DOUBLE = 0x1010, | |
SFC_GET_NORM_FLOAT = 0x1011, | |
SFC_SET_NORM_DOUBLE = 0x1012, | |
SFC_SET_NORM_FLOAT = 0x1013, | |
SFC_SET_SCALE_FLOAT_INT_READ = 0x1014, | |
SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015, | |
SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, | |
SFC_GET_SIMPLE_FORMAT = 0x1021, | |
SFC_GET_FORMAT_INFO = 0x1028, | |
SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, | |
SFC_GET_FORMAT_MAJOR = 0x1031, | |
SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, | |
SFC_GET_FORMAT_SUBTYPE = 0x1033, | |
SFC_CALC_SIGNAL_MAX = 0x1040, | |
SFC_CALC_NORM_SIGNAL_MAX = 0x1041, | |
SFC_CALC_MAX_ALL_CHANNELS = 0x1042, | |
SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, | |
SFC_GET_SIGNAL_MAX = 0x1044, | |
SFC_GET_MAX_ALL_CHANNELS = 0x1045, | |
SFC_SET_ADD_PEAK_CHUNK = 0x1050, | |
SFC_UPDATE_HEADER_NOW = 0x1060, | |
SFC_SET_UPDATE_HEADER_AUTO = 0x1061, | |
SFC_FILE_TRUNCATE = 0x1080, | |
SFC_SET_RAW_START_OFFSET = 0x1090, | |
SFC_SET_DITHER_ON_WRITE = 0x10A0, | |
SFC_SET_DITHER_ON_READ = 0x10A1, | |
SFC_GET_DITHER_INFO_COUNT = 0x10A2, | |
SFC_GET_DITHER_INFO = 0x10A3, | |
SFC_GET_EMBED_FILE_INFO = 0x10B0, | |
SFC_SET_CLIPPING = 0x10C0, | |
SFC_GET_CLIPPING = 0x10C1, | |
SFC_GET_CUE_COUNT = 0x10CD, | |
SFC_GET_CUE = 0x10CE, | |
SFC_SET_CUE = 0x10CF, | |
SFC_GET_INSTRUMENT = 0x10D0, | |
SFC_SET_INSTRUMENT = 0x10D1, | |
SFC_GET_LOOP_INFO = 0x10E0, | |
SFC_GET_BROADCAST_INFO = 0x10F0, | |
SFC_SET_BROADCAST_INFO = 0x10F1, | |
SFC_GET_CHANNEL_MAP_INFO = 0x1100, | |
SFC_SET_CHANNEL_MAP_INFO = 0x1101, | |
SFC_RAW_DATA_NEEDS_ENDSWAP = 0x1110, | |
/* Support for Wavex Ambisonics Format */ | |
SFC_WAVEX_SET_AMBISONIC = 0x1200, | |
SFC_WAVEX_GET_AMBISONIC = 0x1201, | |
/* | |
** RF64 files can be set so that on-close, writable files that have less | |
** than 4GB of data in them are converted to RIFF/WAV, as per EBU | |
** recommendations. | |
*/ | |
SFC_RF64_AUTO_DOWNGRADE = 0x1210, | |
SFC_SET_VBR_ENCODING_QUALITY = 0x1300, | |
SFC_SET_COMPRESSION_LEVEL = 0x1301, | |
/* Cart Chunk support */ | |
SFC_SET_CART_INFO = 0x1400, | |
SFC_GET_CART_INFO = 0x1401, | |
/* Opus files original samplerate metadata */ | |
SFC_SET_ORIGINAL_SAMPLERATE = 0x1500, | |
SFC_GET_ORIGINAL_SAMPLERATE = 0x1501, | |
/* Following commands for testing only. */ | |
SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, | |
/* | |
** These SFC_SET_ADD_* values are deprecated and will disappear at some | |
** time in the future. They are guaranteed to be here up to and | |
** including version 1.0.8 to avoid breakage of existing software. | |
** They currently do nothing and will continue to do nothing. | |
*/ | |
SFC_SET_ADD_HEADER_PAD_CHUNK = 0x1051, | |
SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, | |
SFC_SET_ADD_DITHER_ON_READ = 0x1071 | |
} | |
public enum SF_STR | |
{ | |
SF_STR_TITLE, | |
SF_STR_COPYRIGHT, | |
SF_STR_SOFTWARE, | |
SF_STR_ARTIST, | |
SF_STR_COMMENT, | |
SF_STR_DATE, | |
SF_STR_ALBUM, | |
SF_STR_LICENSE, | |
SF_STR_TRACKNUMBER, | |
SF_STR_GENRE | |
} | |
public enum SF_ERROR | |
{ | |
SF_ERR_NO_ERROR = 0, | |
SF_ERR_UNRECOGNISED_FORMAT = 1, | |
SF_ERR_SYSTEM = 2, | |
SF_ERR_MALFORMED_FILE = 3, | |
SF_ERR_UNSUPPORTED_ENCODING = 4 | |
} | |
public enum SF_FORMAT | |
{ | |
/* Major formats. */ | |
SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian). */ | |
SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ | |
SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ | |
SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ | |
SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ | |
SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ | |
SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ | |
SF_FORMAT_VOC = 0x080000, /* VOC files. */ | |
SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ | |
SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ | |
SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ | |
SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ | |
SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ | |
SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ | |
SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ | |
SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */ | |
SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */ | |
SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */ | |
SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */ | |
SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */ | |
SF_FORMAT_CAF = 0x180000, /* Core Audio File format */ | |
SF_FORMAT_WVE = 0x190000, /* Psion WVE format */ | |
SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */ | |
SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */ | |
SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */ | |
/* Subtypes from here on. */ | |
SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ | |
SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ | |
SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ | |
SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ | |
SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ | |
SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ | |
SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ | |
SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ | |
SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ | |
SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ | |
SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ | |
SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ | |
SF_FORMAT_VOX_ADPCM = 0x0021, /* Oki Dialogic ADPCM encoding. */ | |
SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ | |
SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ | |
SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ | |
SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ | |
SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ | |
SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ | |
SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ | |
SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ | |
SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ | |
SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */ | |
/* Endian-ness options. */ | |
SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ | |
SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ | |
SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ | |
SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ | |
SF_FORMAT_SUBMASK = 0x0000FFFF, | |
SF_FORMAT_TYPEMASK = 0x0FFF0000, | |
SF_FORMAT_ENDMASK = 0x30000000 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment