Переглянути джерело

Add the remaining of the miniaudio API

gingerBill 4 роки тому
батько
коміт
64f5ba6ba1

+ 165 - 0
vendor/miniaudio/decoding.odin

@@ -0,0 +1,165 @@
+package miniaudio
+
+import "core:c"
+
+when ODIN_OS == "windows" { foreign import lib "../lib/miniaudio.lib" }
+
+
+/************************************************************************************************************************************************************
+
+Decoding
+========
+
+Decoders are independent of the main device API. Decoding APIs can be called freely inside the device's data callback, but they are not thread safe unless
+you do your own synchronization.
+
+************************************************************************************************************************************************************/
+
+decoding_backend_config :: struct {
+	preferredFormat: format,
+}
+
+@(default_calling_convention="c", link_prefix="ma_")
+foreign lib {
+	decoding_backend_config_init :: proc(preferredFormat: format) -> decoding_backend_config ---
+}
+
+
+decoding_backend_vtable :: struct {
+	onInit:          proc "c" (pUserData: rawptr, onRead: decoder_read_proc, onSeek: decoder_seek_proc, onTell: decoder_tell_proc, pReadSeekTellUserData: rawptr, pConfig: ^decoding_backend_config, pAllocationCallbacks: ^allocation_callbacks, ppBackend: ^^data_source) -> result,
+	onInitFile:      proc "c" (pUserData: rawptr, pFilePath: cstring, pConfig: ^decoding_backend_config, pAllocationCallbacks: ^allocation_callbacks, ppBackend: ^^data_source) -> result,               /* Optional. */
+	onInitFileW:     proc "c" (pUserData: rawptr, pFilePath: [^]c.wchar_t, pConfig: ^decoding_backend_config, pAllocationCallbacks: ^allocation_callbacks, ppBackend: ^^data_source) -> result,            /* Optional. */
+	onInitMemory:    proc "c" (pUserData: rawptr, pData: rawptr, dataSize: c.size_t, pConfig: ^decoding_backend_config, pAllocationCallbacks: ^allocation_callbacks, ppBackend: ^^data_source) -> result,  /* Optional. */
+	onUninit:        proc "c" (pUserData: rawptr, pBackend: ^data_source, pAllocationCallbacks: ^allocation_callbacks),
+	onGetChannelMap: proc "c" (pUserData: rawptr, pBackend: ^data_source, pChannelMap: ^channel, channelMapCap: c.size_t) -> result,
+}
+
+
+/* TODO: Convert read and seek to be consistent with the VFS API (ma_result return value, bytes read moved to an output parameter). */
+decoder_read_proc :: proc "c" (pDecoder: ^decoder, pBufferOut: rawptr, bytesToRead: c.size_t) -> c.size_t         /* Returns the number of bytes read. */
+decoder_seek_proc :: proc "c" (pDecoder: ^decoder, byteOffset: i64, origin: seek_origin) -> b32
+decoder_tell_proc :: proc "c" (pDecoder: ^decoder, pCursor: ^i64) -> result
+
+decoder_config :: struct {
+	format:     format, /* Set to 0 or ma_format_unknown to use the stream's internal format. */
+	channels:   u32,    /* Set to 0 to use the stream's internal channels. */
+	sampleRate: u32,    /* Set to 0 to use the stream's internal sample rate. */
+	channelMap: [MAX_CHANNELS]channel,
+	channelMixMode: channel_mix_mode,
+	ditherMode: dither_mode,
+	resampling: struct {
+		algorithm: resample_algorithm,
+		linear: struct {
+			lpfOrder: u32,
+		},
+		speex: struct {
+			quality: c.int,
+		},
+	},
+	allocationCallbacks:    allocation_callbacks,
+	encodingFormat:         encoding_format,
+	ppCustomBackendVTables: ^^decoding_backend_vtable,
+	customBackendCount:     u32,
+	pCustomBackendUserData: rawptr,
+}
+
+decoder :: struct  {
+	ds: data_source_base,
+	pBackend: ^data_source,                   /* The decoding backend we'll be pulling data from. */
+	pBackendVTable: ^^decoding_backend_vtable, /* The vtable for the decoding backend. This needs to be stored so we can access the onUninit() callback. */
+	pBackendUserData: rawptr,
+	onRead: decoder_read_proc,
+	onSeek: decoder_seek_proc,
+	onTell: decoder_tell_proc,
+	pUserData: rawptr,
+	readPointerInPCMFrames: u64,      /* In output sample rate. Used for keeping track of how many frames are available for decoding. */
+	outputFormat: format,
+	outputChannels: u32,
+	outputSampleRate: u32,
+	outputChannelMap: [MAX_CHANNELS]channel,
+	converter: data_converter,   /* <-- Data conversion is achieved by running frames through this. */
+	allocationCallbacks: allocation_callbacks,
+	data: struct #raw_union {
+		vfs: struct {
+			pVFS: ^vfs,
+			file: vfs_file,
+		},
+		memory: struct {
+			pData: [^]u8,
+			dataSize: c.size_t,
+			currentReadPos: c.size_t,
+		}, /* Only used for decoders that were opened against a block of memory. */
+	},
+}
+
+@(default_calling_convention="c", link_prefix="ma_")
+foreign lib {
+	decoder_config_init         :: proc(outputFormat: format, outputChannels, outputSampleRate: u32) -> decoder_config ---
+	decoder_config_init_default :: proc() -> decoder_config ---
+
+	decoder_init        :: proc(onRead: decoder_read_proc, onSeek: decoder_seek_proc, pUserData: rawptr, pConfig: ^decoder_config, pDecoder: ^decoder) -> result ---
+	decoder_init_memory :: proc(pData: rawptr, dataSize: c.size_t,   pConfig: ^decoder_config, pDecoder: ^decoder) -> result ---
+	decoder_init_vfs    :: proc(pVFS: ^vfs, pFilePath: cstring,      pConfig: ^decoder_config, pDecoder: ^decoder) -> result ---
+	decoder_init_vfs_w  :: proc(pVFS: ^vfs, pFilePath: [^]c.wchar_t, pConfig: ^decoder_config, pDecoder: ^decoder) -> result ---
+	decoder_init_file   :: proc(pFilePath: cstring,      pConfig: ^decoder_config, pDecoder: ^decoder) -> result ---
+	decoder_init_file_w :: proc(pFilePath: [^]c.wchar_t, pConfig: ^decoder_config, pDecoder: ^decoder) -> result ---
+
+	/*
+	Uninitializes a decoder.
+	*/
+	decoder_uninit :: proc(pDecoder: ^decoder) -> result ---
+
+	/*
+	Retrieves the current position of the read cursor in PCM frames.
+	*/
+	decoder_get_cursor_in_pcm_frames :: proc(pDecoder: ^decoder, pCursor: ^u64) -> result ---
+
+	/*
+	Retrieves the length of the decoder in PCM frames.
+
+	Do not call this on streams of an undefined length, such as internet radio.
+
+	If the length is unknown or an error occurs, 0 will be returned.
+
+	This will always return 0 for Vorbis decoders. This is due to a limitation with stb_vorbis in push mode which is what miniaudio
+	uses internally.
+
+	For MP3's, this will decode the entire file. Do not call this in time critical scenarios.
+
+	This function is not thread safe without your own synchronization.
+	*/
+	decoder_get_length_in_pcm_frames :: proc(pDecoder: ^decoder) -> u64 ---
+
+	/*
+	Reads PCM frames from the given decoder.
+
+	This is not thread safe without your own synchronization.
+	*/
+	decoder_read_pcm_frames :: proc(pDecoder: ^decoder, pFramesOut: rawptr, frameCount: u64) -> u64 ---
+
+	/*
+	Seeks to a PCM frame based on it's absolute index.
+
+	This is not thread safe without your own synchronization.
+	*/
+	decoder_seek_to_pcm_frame :: proc(pDecoder: ^decoder, frameIndex: u64) -> result ---
+
+	/*
+	Retrieves the number of frames that can be read before reaching the end.
+
+	This calls `ma_decoder_get_length_in_pcm_frames()` so you need to be aware of the rules for that function, in
+	particular ensuring you do not call it on streams of an undefined length, such as internet radio.
+
+	If the total length of the decoder cannot be retrieved, such as with Vorbis decoders, `MA_NOT_IMPLEMENTED` will be
+	returned.
+	*/
+	decoder_get_available_frames :: proc(pDecoder: ^decoder, pAvailableFrames: ^u64) -> result ---
+
+	/*
+	Helper for opening and decoding a file into a heap allocated block of memory. Free the returned pointer with ma_free(). On input,
+	pConfig should be set to what you want. On output it will be set to what you got.
+	*/
+	decode_from_vfs :: proc(pVFS: ^vfs, pFilePath: cstring,    pConfig: ^decoder_config, pFrameCountOut: ^u64, ppPCMFramesOut: ^rawptr) -> result ---
+	decode_file     :: proc(pFilePath: cstring,                pConfig: ^decoder_config, pFrameCountOut: ^u64, ppPCMFramesOut: ^rawptr) -> result ---
+	decode_memory   :: proc(pData: rawptr, dataSize: c.size_t, pConfig: ^decoder_config, pFrameCountOut: ^u64, ppPCMFramesOut: ^rawptr) -> result ---
+}

+ 51 - 0
vendor/miniaudio/encoding.odin

@@ -0,0 +1,51 @@
+package miniaudio
+
+import "core:c"
+
+when ODIN_OS == "windows" { foreign import lib "../lib/miniaudio.lib" }
+
+/************************************************************************************************************************************************************
+
+Encoding
+========
+
+Encoders do not perform any format conversion for you. If your target format does not support the format, and error will be returned.
+
+************************************************************************************************************************************************************/
+
+encoder_write_proc            :: proc "c" (pEncoder: ^encoder, pBufferIn: rawptr, bytesToWrite: c.size_t) -> c.size_t        /* Returns the number of bytes written. */
+encoder_seek_proc             :: proc "c" (pEncoder: ^encoder, byteOffset: c.int, origin: seek_origin) -> b32
+encoder_init_proc             :: proc "c" (pEncoder: ^encoder) -> result
+encoder_uninit_proc           :: proc "c" (pEncoder: ^encoder)      
+encoder_write_pcm_frames_proc :: proc "c" (pEncoder: ^encoder, pFramesIn: rawptr, frameCount: u64) -> u64
+
+encoder_config :: struct {
+	resourceFormat:      resource_format,
+	format:              format,
+	channels:            u32,
+	sampleRate:          u32,
+	allocationCallbacks: allocation_callbacks,
+}
+
+encoder :: struct {
+	config:           encoder_config,
+	onWrite:          encoder_write_proc,
+	onSeek:           encoder_seek_proc,
+	onInit:           encoder_init_proc,
+	onUninit:         encoder_uninit_proc,
+	onWritePCMFrames: encoder_write_pcm_frames_proc,
+	pUserData:        rawptr,
+	pInternalEncoder: rawptr, /* <-- The drwav/drflac/stb_vorbis/etc. objects. */
+	pFile:            rawptr,    /* FILE*. Only used when initialized with ma_encoder_init_file(). */
+}
+
+@(default_calling_convention="c", link_prefix="ma_")
+foreign lib {
+	encoder_config_init      :: proc(resourceFormat: resource_format, format: format, channels: u32, sampleRate: u32) -> encoder_config ---
+
+	encoder_init             :: proc(onWrite: encoder_write_proc, onSeek: encoder_seek_proc, pUserData: rawptr, pConfig: ^encoder_config, pEncoder: ^encoder) -> result ---
+	encoder_init_file        :: proc(pFilePath: cstring, pConfig: ^encoder_config, pEncoder: ^encoder) -> result ---
+	encoder_init_file_w      :: proc(pFilePath: [^]c.wchar_t, pConfig: ^encoder_config, pEncoder: ^encoder) -> result ---
+	encoder_uninit           :: proc(pEncoder: ^encoder) ---
+	encoder_write_pcm_frames :: proc(pEncoder: ^encoder, FramesIn: rawptr, frameCount: u64) -> u64 ---
+}

+ 84 - 0
vendor/miniaudio/generation.odin

@@ -0,0 +1,84 @@
+package miniaudio
+
+import "core:c"
+
+when ODIN_OS == "windows" { foreign import lib "../lib/miniaudio.lib" }
+
+waveform_type :: enum c.int {
+	sine,
+	square,
+	triangle,
+	sawtooth,
+}
+
+waveform_config :: struct {
+	format:     format,
+	channels:   u32,
+	sampleRate: u32,
+	type:       waveform_type,
+	amplitude:  f64,
+	frequency:  f64,
+}
+
+
+waveform :: struct {
+	ds:      data_source_base,
+	config:  waveform_config,
+	advance: f64,
+	time:    f64,
+}
+
+
+noise_type :: enum c. int {
+	white,
+	pink,
+	brownian,
+}
+
+noise_config :: struct {
+	format:            format,
+	channels:          u32,
+	type:              noise_type,
+	seed:              i32,
+	amplitude:         f64,
+	duplicateChannels: b32,
+}
+
+noise :: struct {
+	ds:     data_source_vtable,
+	config: noise_config,
+	lcg:    lcg,
+	state: struct #raw_union {
+		pink: struct {
+			bin:          [MAX_CHANNELS][16]f64,
+			accumulation: [MAX_CHANNELS]f64,
+			counter:      [MAX_CHANNELS]u32,
+		},
+		brownian: struct {
+			accumulation: [MAX_CHANNELS]f64,
+		},
+	},
+}
+
+@(default_calling_convention="c", link_prefix="ma_")
+foreign lib {
+	waveform_config_init :: proc(format: format, channels: u32, sampleRate: u32, type: waveform_type, amplitude: f64, frequency: f64) -> waveform_config ---
+
+	waveform_init              :: proc(pConfig: ^waveform_config, pWaveform: ^waveform) -> result ---
+	waveform_uninit            :: proc(pWaveform: ^waveform) ---
+	waveform_read_pcm_frames   :: proc(pWaveform: ^waveform, pFramesOut: rawptr, frameCount: u64) -> u64 ---
+	waveform_seek_to_pcm_frame :: proc(pWaveform: ^waveform, frameIndex: u64) -> result ---
+	waveform_set_amplitude     :: proc(pWaveform: ^waveform, amplitude: f64) -> result ---
+	waveform_set_frequency     :: proc(pWaveform: ^waveform, frequency: f64) -> result ---
+	waveform_set_type          :: proc(pWaveform: ^waveform, type: waveform_type) -> result ---
+	waveform_set_sample_rate   :: proc(pWaveform: ^waveform, sampleRate: u32) -> result ---
+
+	noise_config_init :: proc(format: format, channels: u32, type: noise_type, seed: i32, amplitude: f64) -> noise_config ---
+
+	noise_init            :: proc(pConfig: ^noise_config, pNoise: ^noise) -> result ---
+	noise_uninit          :: proc(pNoise: ^noise) ---
+	noise_read_pcm_frames :: proc(pNoise: ^noise, pFramesOut: rawptr, frameCount: u64) -> u64 ---
+	noise_set_amplitude   :: proc(pNoise: ^noise, amplitude: f64) -> result ---
+	noise_set_seed        :: proc(pNoise: ^noise, seed: i32) -> result ---
+	noise_set_type        :: proc(pNoise: ^noise, type: noise_type) -> result ---
+}

+ 7 - 7
vendor/miniaudio/utilities.odin

@@ -196,18 +196,18 @@ foreign lib {
 
 
 audio_buffer_config :: struct {
-	format: format,
-	channels: u32,
-	sizeInFrames: u64,
-	pData: rawptr,  /* If set to NULL, will allocate a block of memory for you. */
+	format:              format,
+	channels:            u32,
+	sizeInFrames:        u64,
+	pData:               rawptr,  /* If set to NULL, will allocate a block of memory for you. */
 	allocationCallbacks: allocation_callbacks,
 }
 
 audio_buffer :: struct {
-	ref: audio_buffer_ref,
+	ref:                 audio_buffer_ref,
 	allocationCallbacks: allocation_callbacks,
-	ownsData: b32,             /* Used to control whether or not miniaudio owns the data buffer. If set to true, pData will be freed in ma_audio_buffer_uninit(). */
-	_pExtraData: [1]u8,        /* For allocating a buffer with the memory located directly after the other memory of the structure. */
+	ownsData:            b32,             /* Used to control whether or not miniaudio owns the data buffer. If set to true, pData will be freed in ma_audio_buffer_uninit(). */
+	_pExtraData:         [1]u8,        /* For allocating a buffer with the memory located directly after the other memory of the structure. */
 }
 
 @(default_calling_convention="c", link_prefix="ma_")

+ 78 - 0
vendor/miniaudio/vfs.odin

@@ -0,0 +1,78 @@
+package miniaudio
+
+import "core:c"
+
+when ODIN_OS == "windows" { foreign import lib "../lib/miniaudio.lib" }
+
+/************************************************************************************************************************************************************
+
+VFS
+===
+
+The VFS object (virtual file system) is what's used to customize file access. This is useful in cases where stdio FILE* based APIs may not be entirely
+appropriate for a given situation.
+
+************************************************************************************************************************************************************/
+vfs :: struct {}
+vfs_file :: distinct handle
+
+OPEN_MODE_READ  :: 0x00000001
+OPEN_MODE_WRITE :: 0x00000002
+
+seek_origin :: enum c.int {
+	start,
+	current,
+	end,  /* Not used by decoders. */
+}
+
+file_info :: struct {
+	sizeInBytes: u64,
+}
+
+vfs_callbacks :: struct {
+	onOpen:  proc "c" (pVFS: ^vfs, pFilePath: cstring,      openMode: u32, pFile: ^vfs_file) -> result,
+	onOpenW: proc "c" (pVFS: ^vfs, pFilePath: [^]c.wchar_t, openMode: u32, pFile: ^vfs_file) -> result,
+	onClose: proc "c" (pVFS: ^vfs, file: vfs_file) -> result,
+	onRead:  proc "c" (pVFS: ^vfs, file: vfs_file, pDst: rawptr, sizeInBytes: c.size_t, pBytesRead: ^c.size_t) -> result,
+	onWrite: proc "c" (pVFS: ^vfs, file: vfs_file, pSrc: rawptr, sizeInBytes: c.size_t, pBytesWritten: ^c.size_t) -> result,
+	onSeek:  proc "c" (pVFS: ^vfs, file: vfs_file, offset: i64, origin: seek_origin) -> result,
+	onTell:  proc "c" (pVFS: ^vfs, file: vfs_file, pCursor: ^i64) -> result,
+	onInfo:  proc "c" (pVFS: ^vfs, file: vfs_file, pInfo: ^file_info) -> result,
+}
+
+default_vfs :: struct {
+	cb: vfs_callbacks,
+	allocationCallbacks: allocation_callbacks, /* Only used for the wchar_t version of open() on non-Windows platforms. */
+}
+
+ma_read_proc :: proc "c" (pUserData: rawptr, pBufferOut: rawptr, bytesToRead: c.size_t, pBytesRead: ^c.size_t) -> result
+ma_seek_proc :: proc "c" (pUserData: rawptr, offset: i64, origin: seek_origin) -> result
+ma_tell_proc :: proc "c" (pUserData: rawptr, pCursor: ^i64) -> result
+
+
+@(default_calling_convention="c", link_prefix="ma_")
+foreign lib {
+	vfs_open               :: proc(pVFS: ^vfs, pFilePath: cstring,      openMode: u32, pFile: ^vfs_file) -> result ---
+	vfs_open_w             :: proc(pVFS: ^vfs, pFilePath: [^]c.wchar_t, openMode: u32, pFile: ^vfs_file) -> result ---
+	vfs_close              :: proc(pVFS: ^vfs, file: vfs_file) -> result ---
+	vfs_read               :: proc(pVFS: ^vfs, file: vfs_file, pDst: rawptr, sizeInBytes: c.size_t, pBytesRead: ^c.size_t) -> result ---
+	vfs_write              :: proc(pVFS: ^vfs, file: vfs_file, pSrc: rawptr, sizeInBytes: c.size_t, pBytesWritten: ^c.size_t) -> result ---
+	vfs_seek               :: proc(pVFS: ^vfs, file: vfs_file, offset: i64, origin: seek_origin) -> result ---
+	vfs_tell               :: proc(pVFS: ^vfs, file: vfs_file, pCursor: ^i64) -> result ---
+	vfs_info               :: proc(pVFS: ^vfs, file: vfs_file, pInfo: ^file_info) -> result ---
+	vfs_open_and_read_file :: proc(pVFS: ^vfs, pFilePath: cstring, ppData: ^rawptr, pSize: ^c.size_t, pAllocationCallbacks: ^allocation_callbacks) -> result ---
+
+	default_vfs_init       :: proc(pVFS: ^default_vfs, pAllocationCallbacks: ^allocation_callbacks) -> result ---
+}
+
+resource_format :: enum c.int {
+	wav,
+}
+
+encoding_format :: enum c.int {
+	unknown = 0,
+	wav,
+	flac,
+	mp3,
+	vorbis,
+}