- The sinc resampler has been removed. This was completely broken and never actually worked properly.
- The linear resampler can now uses low-pass filtering to remove aliasing. The quality of the low-pass filter can be
controlled via the resampler config with the `lpcCount` option, which has a maximum value of MA_MAX_RESAMPLER_LPF_FILTERS.
- Data conversion now supports s16 natively which runs through a fixed point pipeline. Previously everything needed to be
converted to floating point before processing, whereas now both s16 and f32 are natively supported. Other formats still
require conversion to either s16 or f32 prior to processing, however `ma_data_converter` will handle this for you.
This callback allows you to move data straight out of the input buffer and into the output buffer in full-duplex mode. In
playback-only mode, pInput will be null. Likewise, pOutput will be null in capture-only mode. The sample count is no longer
returned from the callback since it's not necessary for miniaudio anymore.
2) The device config needed to change in order to support full-duplex. Full-duplex requires the ability to allow the client
Custom Memory Allocators
to choose a different PCM format for the playback and capture sides. The old ma_device_config object simply did not allow
------------------------
this and needed to change. With these changes you now specify the device ID, format, channels, channel map and share mode
miniaudio has always supported macro level customization to memory allocation via MA_MALLOC, MA_REALLOC and MA_FREE, however
on a per-playback and per-capture basis (see example below). The sample rate must be the same for playback and capture.
some scenarios require more flexibility by allowing a user data pointer to be passed to the custom allocation routines. Support
for this has been added to version 0.10 via the `ma_allocation_callbacks` structure. Anything making use of heap allocations
has been updated to accept this new structure.
Since the device config API has changed I have also decided to take the opportunity to simplify device initialization. Now,
The `ma_device_config` structure has been updated with a new member called `allocationCallbacks`. Leaving this set to it's
the device ID, device type and callback user data are set in the config. ma_device_init() is now simplified down to taking
defaults returned by `ma_device_config_init()` will cause it to use defaults. Likewise, The `ma_decoder_config` structure has
just the context, device config and a pointer to the device object being initialized. The rationale for this change is that
been updated in the same way, and leaving everything as-is after `ma_decoder_config_init()` will cause it to use defaults.
it just makes more sense to me that these are set as part of the config like everything else.
Example device initialization:
The following APIs have been updated to take a pointer to a `ma_allocation_callbacks` object. Setting this parameter to NULL
will cause it to use defaults. Otherwise they will use the relevant callback in the structure.
ma_device_config config = ma_device_config_init(ma_device_type_duplex); // Or ma_device_type_playback or ma_device_type_capture.
- ma_malloc()
config.playback.pDeviceID = &myPlaybackDeviceID; // Or NULL for the default playback device.
- ma_realloc()
config.playback.format = ma_format_f32;
- ma_free()
config.playback.channels = 2;
- ma_aligned_malloc()
config.capture.pDeviceID = &myCaptureDeviceID; // Or NULL for the default capture device.
- ma_aligned_free()
config.capture.format = ma_format_s16;
- ma_rb_init() / ma_rb_init_ex()
config.capture.channels = 1;
- ma_pcm_rb_init() / ma_pcm_rb_init_ex()
config.sampleRate = 44100;
config.dataCallback = data_callback;
config.pUserData = &myUserData;
result = ma_device_init(&myContext, &config, &device);
Note that you can continue to use MA_MALLOC, MA_REALLOC and MA_FREE as per normal. These will continue to be used by default if
if (result != MA_SUCCESS) {
you do not specify custom allocation callbacks.
... handle error ...
}
Note that the "onDataCallback" member of ma_device_config has been renamed to "dataCallback". Also, "onStopCallback" has
been renamed to "stopCallback".
This is the first pass for full-duplex and there is a known bug. You will hear crackling on the following backends when sample
Other API Changes
rate conversion is required for the playback device:
-----------------
- Core Audio
Other less major API changes have also been made in version 0.10.
- JACK
- AAudio
- OpenSL
- WebAudio
In addition to the above, not all platforms have been absolutely thoroughly tested simply because I lack the hardware for such
`ma_sine_wave_read_f32()` and `ma_sine_wave_read_f32_ex()` have been removed and replaced with `ma_sine_wave_process_pcm_frames()`
thorough testing. If you experience a bug, an issue report on GitHub or an email would be greatly appreciated (and a sample
which supports outputting PCM frames in any format (specified by a parameter).
program that reproduces the issue if possible).
`ma_convert_frames()` and `ma_convert_frames_ex()` have been changed. Both of these functions now take a new parameter called
`frameCountOut` which specifies the size of the output buffer in PCM frames. This has been added for safety. In addition to this,
the parameters for `ma_convert_frames_ex()` have changed to take a pointer to a `ma_data_converter_config` object to specify the
input and output formats to convert between. This was done to make it make it more flexible, to prevent the parameter list
getting too long, and to prevent API breakage whenever a new conversion property is added.
Other API Changes
-----------------
In addition to the above, the following API changes have been made:
- The log callback is no longer passed to ma_context_config_init(). Instead you need to set it manually after initialization.
Biquad and Low-Pass Filters
- The onLogCallback member of ma_context_config has been renamed to "logCallback".
---------------------------
- The log callback now takes a logLevel parameter. The new callback looks like: void log_callback(ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message)
A generic biquad filter has been added. This is used via the `ma_biquad` API. The biquad filter is used as the basis for the
- You can use ma_log_level_to_string() to convert the logLevel to human readable text if you want to log it.
low-pass filter. The biquad filter supports 32-bit floating point samples which runs on a floating point pipeline and 16-bit
- Some APIs have been renamed:
signed integer samples which runs on a 32-bit fixed point pipeline. Both formats use transposed direct form 2.
This callback allows you to move data straight out of the input buffer and into the output buffer in full-duplex mode. In
playback-only mode, pInput will be null. Likewise, pOutput will be null in capture-only mode. The sample count is no longer
returned from the callback since it's not necessary for miniaudio anymore.
2) The device config needed to change in order to support full-duplex. Full-duplex requires the ability to allow the client
to choose a different PCM format for the playback and capture sides. The old ma_device_config object simply did not allow
this and needed to change. With these changes you now specify the device ID, format, channels, channel map and share mode
on a per-playback and per-capture basis (see example below). The sample rate must be the same for playback and capture.
Since the device config API has changed I have also decided to take the opportunity to simplify device initialization. Now,
the device ID, device type and callback user data are set in the config. ma_device_init() is now simplified down to taking
just the context, device config and a pointer to the device object being initialized. The rationale for this change is that
it just makes more sense to me that these are set as part of the config like everything else.
Example device initialization:
ma_device_config config = ma_device_config_init(ma_device_type_duplex); // Or ma_device_type_playback or ma_device_type_capture.
config.playback.pDeviceID = &myPlaybackDeviceID; // Or NULL for the default playback device.
config.playback.format = ma_format_f32;
config.playback.channels = 2;
config.capture.pDeviceID = &myCaptureDeviceID; // Or NULL for the default capture device.
config.capture.format = ma_format_s16;
config.capture.channels = 1;
config.sampleRate = 44100;
config.dataCallback = data_callback;
config.pUserData = &myUserData;
result = ma_device_init(&myContext, &config, &device);
if (result != MA_SUCCESS) {
... handle error ...
}
Note that the "onDataCallback" member of ma_device_config has been renamed to "dataCallback". Also, "onStopCallback" has
been renamed to "stopCallback".
This is the first pass for full-duplex and there is a known bug. You will hear crackling on the following backends when sample
rate conversion is required for the playback device:
- Core Audio
- JACK
- AAudio
- OpenSL
- WebAudio
In addition to the above, not all platforms have been absolutely thoroughly tested simply because I lack the hardware for such
thorough testing. If you experience a bug, an issue report on GitHub or an email would be greatly appreciated (and a sample
program that reproduces the issue if possible).
Other API Changes
-----------------
In addition to the above, the following API changes have been made:
- The log callback is no longer passed to ma_context_config_init(). Instead you need to set it manually after initialization.
- The onLogCallback member of ma_context_config has been renamed to "logCallback".
- The log callback now takes a logLevel parameter. The new callback looks like: void log_callback(ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message)
- You can use ma_log_level_to_string() to convert the logLevel to human readable text if you want to log it.