Commit Graph

497 Commits

Author SHA1 Message Date
David Reid d48708d5de Big refactor to the resource manager.
* The data buffers and data streams are now first class data sources.
  * The ma_resource_manager_data_source object is now just a simple
    wrapper around ma_resource_manager_data_buffer and
    ma_resource_manager_data_stream.
  * Unnecessary pResourceManager parameters have been removed.
  * The part of the data buffer that's added to the BST has been split
    out from the main data buffer object so that the main object can be
    owned by the caller.
  * Add ma_resource_manager_data_source_get_available_frames() which is
    used to retrieve the number of frames that can be read at the time
    of calling. This is useful in asynchronous scenarios.
2020-08-02 21:26:34 +10:00
David Reid 5303558ac8 Add ma_resource_manager_data_source_get_available_frames(). 2020-08-02 13:58:36 +10:00
David Reid 0336896c33 Resource Manager: Update some documentation for implementation details. 2020-08-02 12:38:14 +10:00
David Reid 0d8bf45dba Start some documentation for resource management. 2020-07-26 15:41:33 +10:00
David Reid 4fef753432 Resource Manager: Add public APIs for reading and seeking. 2020-07-25 19:49:20 +10:00
David Reid 5eb7761d8e Resource Manager: Rename some APIs for consistency. 2020-07-25 19:19:52 +10:00
David Reid 2a15044ff9 Update resource_manager example. 2020-07-25 18:27:59 +10:00
David Reid 3df4a9e860 Resource Manager: Decode synchronously on the calling thread.
This commit changes synchronous decoding so that the calling thread is
the one which performs the decoding. Previously, decoding was done on
the job threads which was then waited on by an event on the calling
thread. The rationale for this design was to keep decoding on a single
code path, however this creates a problem for programs that would
prefer not to have any asynchronous job threads. In this case, these
synchronously decoded sounds would never get decoded because there
would not be any threads available to actually perform the decoding.

This commit enables the resource manager to be able to be used without
a job thread so long as asynchronous decoding and streaming are not
used. This scenario could be useful for programs that want to pre-load
all of their sounds at load time and save some system resources by not
incurring the overhead of an additional unnecessary thread.
2020-07-25 18:06:48 +10:00
David Reid 24a1108834 Minor updates to the resource_manager example. 2020-07-23 17:01:04 +10:00
David Reid 83178a1dfc Fix a buffer overflow in the mixer. 2020-07-23 09:44:20 +10:00
David Reid 5dda38d417 Add a clarifying comment to the resource_manager example. 2020-07-23 08:02:19 +10:00
David Reid 9972488bde Add some comments to the resource manager example for clarity. 2020-07-22 20:50:57 +10:00
David Reid 3bcdf3942d Add a resource manager example. 2020-07-22 20:35:34 +10:00
David Reid 681d26a557 Fix bugs in the resource manager. 2020-07-22 20:22:44 +10:00
David Reid 77057895a8 Set up some infrastructure for enabling multiple job threads. 2020-07-20 19:15:32 +10:00
David Reid 861f6a23c8 Initial work on a new job system for the high level API.
This new system is used for asynchronous decoding of sound data. The
main improvement with this one over the old one is the ability to do
multi-producer, multi-consumer lock-free posting of messages which
means multiple threads can be used to process jobs simultaneously
rather than a single thread processing all jobs serially.

Decoding is inherently serial which means multiple job threads is only
useful when decoding multiple sounds. Each individual sound will be
decoded serially.

Another change with this commit is the ability for applications to
control whether or not the resource manager manages it's own job
threads. This is useful if an application wants to manage the job queue
themselves if, for example, they want to integrate it more closely with
their existing job system.
2020-07-19 21:56:12 +10:00
David Reid cf14d0773e Experiment with some mitigation for the ABA problem. 2020-07-19 10:43:18 +10:00
David Reid 6f748942e6 Update examples and tests. 2020-06-24 19:37:46 +10:00
David Reid 9467152730 Integrate c89atomic to replace the old atomics API.
This is an internal change and does not affect any public APIs. This
change is in preparation for future lock-free high level APIs.
2020-06-23 17:39:06 +10:00
David Reid 45a12620bf Minor update to test code. 2020-06-22 21:03:07 +10:00
David Reid c92c7764de Experimental work on some lock free queues.
These are completely untested. Nothing here is wired up to the main
system - they're just for experimenting with some ideas.
2020-06-16 21:06:04 +10:00
David Reid a04a318b44 Fix a copy/paste error. 2020-06-14 21:59:42 +10:00
David Reid badb651b79 Add next() and peek() APIs for messages to the resource manager.
This is in preparation for self-managed message handling.
2020-06-14 20:32:52 +10:00
David Reid 4b6c8f555b Add support for configuring thread stack sizes and fix GCC errors.
The thread priority can be set via ma_thread_create() and can be set in
the context config along side the thread priority for configuring the
size of the stack for the audio thread.
2020-06-14 19:27:02 +10:00
David Reid d4cdee82b5 Fix looping with data streams. 2020-06-14 17:24:15 +10:00
David Reid cb5e6f33df Tidy up a few things with the resource manager. 2020-06-14 15:22:11 +10:00
David Reid 9d81823a73 Fix a typo. 2020-06-14 15:20:31 +10:00
David Reid 9cb5ee06ac Comment out some unused functions. 2020-06-14 15:20:13 +10:00
David Reid 5a7c2be726 Update comment. 2020-06-14 13:16:47 +10:00
David Reid 80da67de3b Revert some earlier test code. 2020-06-14 13:04:03 +10:00
David Reid c3e2038c3a Fix a crash trying to seek on a failed async data stream. 2020-06-14 12:54:14 +10:00
David Reid 9be52c7075 Remove a debugging line. 2020-06-14 12:34:16 +10:00
David Reid d2cffd18d6 Add support for streaming data sources.
A streaming data source keeps in memory only two pages of audio data
and dynamically loads data from a background thread. It is essentially
a double buffering system - as one page is playing, the other is being
loaded by the async thread.

The size of a single page is defined by the following macro:

    MA_RESOURCE_MANAGER_PAGE_SIZE_IN_MILLISECONDS

By default this is currently set to 1 second of audio data. This means
each page has 1 second to load which should be plenty of time. If you
need additional time, the only way to do it is increase the size of the
page by changing the value of the above macro.
2020-06-14 10:39:41 +10:00
David Reid 33aec2fcf9 Clean up and bug fixes to the resource manager.
* ma_resource_manager_uninit() has been implemented.
  * Bug fixes and inserting and removing data buffers from the BST.
  * Some old experimental code has been removed.
  * Minor whitespace clean up.
2020-06-13 10:40:04 +10:00
David Reid 96da8dd4bd Add ma_swap_endian_uint32() in preparation for future work. 2020-06-13 09:19:36 +10:00
David Reid 373234255a Add ma_decode_from_vfs(). 2020-06-13 09:15:47 +10:00
David Reid f38dcab0f2 Rename data nodes to data buffers in the resource manager. 2020-06-13 08:44:15 +10:00
David Reid 213ee9dc52 Introduce paged decoding to the resource manager in the high level API.
This enables early playback of the sound while the remainder of the
sound is loaded in the background. When the first page is loaded, the
sound can start playback. While it's playing, the rest of the sound is
loaded in a background thread. In addition, sounds no longer need to
wait for every sound prior to it in the queue to fully decode before it
is able to start - it only needs to wait for the first page of each of
the queued sounds to decode. This enables much fairer prioritization of
asynchronously loaded sounds.

This paged decoding system is *not* a true streaming solution for long
sounds. Support for true streaming will be added in future commits.
This commit is only concerned with filling in-memory buffers containing
the whole sound in an asynchronous manner.
2020-06-12 21:47:49 +10:00
David Reid 8734e8f578 Work in progress on the new high level API.
* Early work on asynchronously decoding into a memory buffer. This is
    just an early implementation - there are still issues needing to be
    figured out. In particular, sounds do not automatically start until
    the entire file has been decoded. It would be good if they could
    start as soon as the first second or so of data has been decoded.
2020-06-10 22:07:16 +10:00
David Reid 95ded1d57c Fix sound uninitialization. 2020-06-07 15:33:49 +10:00
David Reid ce4d4b359f More work on the new high level API:
* Implement the notion of a virtual file system (VFS) which is used
    by the resource manager for loading sound files. The idea is that
    the application can implement these to support loading from custom
    packages, archives, etc.
  * Add a helper API for decoding a file from a VFS and a file name.
  * Add some symbols representing allocation types. These are not
    currently used, but I've added them in preparation for changes to
    the allocation callbacks. The idea is that an allocation type will
    be passed to the callbacks to give the allocator better intel as to
    what it's allocating which will give it a chance to optimize.
  * Add some placeholders for flags for controlling how to load a data
    source. Currently only MA_DATA_SOURCE_FLAG_DECODE is implemented
    which is used to indicate to the resource manager that it should
    store the decoded contents of the sound file in memory rather than
    the raw (encoded) file data.
  * Support has been added to the resource manager to load audio data
    into memory rather than naively reading straight from disk. This
    eliminates file IO from the audio thread, but comes at the expense
    of extra memory usage. Support for streaming is not implemented as
    of this commit. Early (largely untested) work has been implemented
    to avoid loading sound files multiple times. This is a simple ref
    count system for now, with hashed files paths being used for the
    key into a binary search tree. The BST is not fully tested and
    likely has bugs which will be ironed out in future commits.
  * Support has been added for configuring the stereo pan effect. Most
    audio engines use a simple balancing technique to implement the
    pan effect, but a true pan should "move" one side to the other
    rather than just simply making one side quieter. With this commit,
    the ma_panner effect can support both modes. The default mode will
    be set to ma_pan_mode_balance which is just a simple balancing and
    is consistent with most other audio engines. A true pan can be used
    by setting the mode to ma_pan_mode_pan.
2020-06-07 12:09:39 +10:00
David Reid 99fea233e8 Fix a bug when mixing a data source using mmap mode.
This was causing mmaped data sources to not loop if they coincidentally
reached the end at the same time as the final output frame was written.
2020-06-07 11:51:59 +10:00
David Reid b287d94fe8 Rename some functions for consistency. 2020-06-03 21:25:57 +10:00
David Reid fe06814325 Don't do filtering when pitch shifting for now.
This may be changed back to a first order LPF later on.
2020-06-03 20:50:44 +10:00
David Reid 31f08287da Have decoders use their native channel count in the high level API.
This is required so we can do different spatialization logic depending
on the channel count of the audio source.
2020-06-03 17:01:39 +10:00
David Reid cc8201738b Optimization to stereo panner. 2020-06-01 20:47:34 +10:00
David Reid 4d5433ae58 Use first order LPF for pitch shifting by default.
There is a bug that's causing glitches which appears to be something to
do with the second order LPF.
2020-06-01 20:38:37 +10:00
David Reid 54adbc3dfc Fix a possible infinite loop. 2020-06-01 18:03:43 +10:00
David Reid 32e240d4ec Fix a bug when mixing a data source. 2020-06-01 01:05:01 +10:00
David Reid 1c26893930 Add initial implementation of stereo panning to the ma_engine API.
This currently only supports f32, but support for more formats will be
coming soon.
2020-05-31 23:54:29 +10:00