mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 09:14:04 +02:00
Remove ma_effect.
This commit is contained in:
@@ -948,62 +948,6 @@ MA_API void ma_splitter_node_uninit(ma_splitter_node* pSplitterNode, const ma_al
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Effects
|
|
||||||
=======
|
|
||||||
The `ma_effect` API is a mid-level API for chaining together effects. This is a wrapper around lower level APIs which you can continue to use by themselves if
|
|
||||||
this API does not work for you.
|
|
||||||
|
|
||||||
Effects can be linked together as a chain, with one input and one output. When processing audio data through an effect, it starts at the top of the chain and
|
|
||||||
works it's way down.
|
|
||||||
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
To apply the effect to some audio data, do something like the following:
|
|
||||||
|
|
||||||
```c
|
|
||||||
ma_uint64 framesToProcessIn = availableInputFrameCount;
|
|
||||||
ma_uint64 framesToProcessOut = frameCountOut;
|
|
||||||
ma_result result = ma_effect_process_pcm_frames(pEffect, pFramesIn, &framesToProcessIn, pFramesOut, &framesToProcessOut);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
// Error.
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point framesToProcessIn contains the number of input frames that were consumed and framesToProcessOut contains the number of output frames that
|
|
||||||
// were processed.
|
|
||||||
```
|
|
||||||
|
|
||||||
Some effects can change the sample rate, which means the number of output frames may be different to the number of input frames consumed. Therefore they both
|
|
||||||
need to be specified when processing a chunk of audio data.
|
|
||||||
*/
|
|
||||||
#define MA_EFFECT_MIN_INPUT_STREAM_COUNT 1
|
|
||||||
#define MA_EFFECT_MAX_INPUT_STREAM_COUNT 4
|
|
||||||
|
|
||||||
typedef void ma_effect;
|
|
||||||
|
|
||||||
typedef struct ma_effect_base ma_effect_base;
|
|
||||||
struct ma_effect_base
|
|
||||||
{
|
|
||||||
ma_result (* onProcessPCMFrames)(ma_effect* pEffect, ma_uint32 inputStreamCount, const void** ppFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut);
|
|
||||||
ma_uint64 (* onGetRequiredInputFrameCount)(ma_effect* pEffect, ma_uint64 outputFrameCount);
|
|
||||||
ma_uint64 (* onGetExpectedOutputFrameCount)(ma_effect* pEffect, ma_uint64 inputFrameCount);
|
|
||||||
ma_result (* onGetInputDataFormat)(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate);
|
|
||||||
ma_result (* onGetOutputDataFormat)(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate);
|
|
||||||
};
|
|
||||||
|
|
||||||
MA_API ma_result ma_effect_process_pcm_frames(ma_effect* pEffect, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut);
|
|
||||||
MA_API ma_result ma_effect_process_pcm_frames_ex(ma_effect* pEffect, ma_uint32 inputStreamCount, const void** ppFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut);
|
|
||||||
MA_API ma_result ma_effect_process_pcm_frames_with_conversion(ma_effect* pEffect, ma_uint32 inputStreamCount, const void** ppFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut, ma_format formatIn, ma_uint32 channelsIn, ma_format formatOut, ma_uint32 channelsOut);
|
|
||||||
MA_API ma_uint64 ma_effect_get_required_input_frame_count(ma_effect* pEffect, ma_uint64 outputFrameCount);
|
|
||||||
MA_API ma_uint64 ma_effect_get_expected_output_frame_count(ma_effect* pEffect, ma_uint64 inputFrameCount);
|
|
||||||
MA_API ma_result ma_effect_get_output_data_format(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate);
|
|
||||||
MA_API ma_result ma_effect_get_input_data_format(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Resource Manager Data Source Flags
|
Resource Manager Data Source Flags
|
||||||
==================================
|
==================================
|
||||||
@@ -3714,247 +3658,6 @@ static ma_uint32 ma_ffs_32(ma_uint32 x)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
MA_API ma_result ma_effect_process_pcm_frames(ma_effect* pEffect, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
|
|
||||||
{
|
|
||||||
return ma_effect_process_pcm_frames_ex(pEffect, 1, &pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
MA_API ma_result ma_effect_process_pcm_frames_ex(ma_effect* pEffect, ma_uint32 inputStreamCount, const void** ppFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
|
|
||||||
{
|
|
||||||
ma_effect_base* pBase = (ma_effect_base*)pEffect;
|
|
||||||
|
|
||||||
if (pEffect == NULL || pBase->onProcessPCMFrames == NULL) {
|
|
||||||
return MA_INVALID_ARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pBase->onProcessPCMFrames(pEffect, inputStreamCount, ppFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
MA_API ma_result ma_effect_process_pcm_frames_with_conversion(ma_effect* pEffect, ma_uint32 inputStreamCount, const void** ppFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut, ma_format formatIn, ma_uint32 channelsIn, ma_format formatOut, ma_uint32 channelsOut)
|
|
||||||
{
|
|
||||||
ma_result result;
|
|
||||||
ma_format effectFormatIn;
|
|
||||||
ma_uint32 effectChannelsIn;
|
|
||||||
ma_format effectFormatOut;
|
|
||||||
ma_uint32 effectChannelsOut;
|
|
||||||
|
|
||||||
if (inputStreamCount < MA_EFFECT_MIN_INPUT_STREAM_COUNT || inputStreamCount > MA_EFFECT_MAX_INPUT_STREAM_COUNT) {
|
|
||||||
return MA_INVALID_ARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First thing to retrieve the effect's input and output format to determine if conversion is necessary. */
|
|
||||||
result = ma_effect_get_input_data_format(pEffect, &effectFormatIn, &effectChannelsIn, NULL);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = ma_effect_get_output_data_format(pEffect, &effectFormatOut, &effectChannelsOut, NULL);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (effectFormatIn == formatIn && effectChannelsIn == channelsIn && effectFormatOut == formatOut && effectChannelsOut == channelsOut) {
|
|
||||||
/* Fast path. No need for any data conversion. */
|
|
||||||
return ma_effect_process_pcm_frames_ex(pEffect, inputStreamCount, ppFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
|
||||||
} else {
|
|
||||||
/* Slow path. Getting here means we need to do pre- and/or post-data conversion. */
|
|
||||||
ma_uint8 effectInBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
|
||||||
ma_uint32 effectInBufferCap = sizeof(effectInBuffer) / ma_get_bytes_per_frame(effectFormatIn, effectChannelsIn) / inputStreamCount;
|
|
||||||
ma_uint8 effectOutBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
|
||||||
ma_uint32 effectOutBufferCap = sizeof(effectOutBuffer) / ma_get_bytes_per_frame(effectFormatOut, effectChannelsOut);
|
|
||||||
ma_uint64 totalFramesProcessedIn = 0;
|
|
||||||
ma_uint64 totalFramesProcessedOut = 0;
|
|
||||||
ma_uint64 frameCountIn = *pFrameCountIn;
|
|
||||||
ma_uint64 frameCountOut = *pFrameCountOut;
|
|
||||||
|
|
||||||
while (totalFramesProcessedIn < frameCountIn && totalFramesProcessedOut < frameCountOut) {
|
|
||||||
ma_uint32 iInputStream;
|
|
||||||
ma_uint64 framesToProcessThisIterationIn;
|
|
||||||
ma_uint64 framesToProcessThisIterationOut;
|
|
||||||
const void* ppRunningFramesIn[MA_EFFECT_MAX_INPUT_STREAM_COUNT];
|
|
||||||
/* */ void* pRunningFramesOut = ma_offset_ptr(pFramesOut, totalFramesProcessedOut * ma_get_bytes_per_frame(formatOut, channelsOut));
|
|
||||||
|
|
||||||
for (iInputStream = 0; iInputStream < inputStreamCount; iInputStream += 1) {
|
|
||||||
ppRunningFramesIn[iInputStream] = ma_offset_ptr(ppFramesIn[iInputStream], totalFramesProcessedIn * ma_get_bytes_per_frame(formatIn, channelsIn));
|
|
||||||
}
|
|
||||||
|
|
||||||
framesToProcessThisIterationOut = frameCountOut - totalFramesProcessedOut;
|
|
||||||
if (framesToProcessThisIterationOut > effectOutBufferCap) {
|
|
||||||
framesToProcessThisIterationOut = effectOutBufferCap;
|
|
||||||
}
|
|
||||||
|
|
||||||
framesToProcessThisIterationIn = ma_effect_get_required_input_frame_count(pEffect, framesToProcessThisIterationOut);
|
|
||||||
if (framesToProcessThisIterationIn > (frameCountIn - totalFramesProcessedIn)) {
|
|
||||||
framesToProcessThisIterationIn = (frameCountIn - totalFramesProcessedIn);
|
|
||||||
}
|
|
||||||
if (framesToProcessThisIterationIn > effectInBufferCap) {
|
|
||||||
framesToProcessThisIterationIn = effectInBufferCap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* At this point our input data has been converted to the effect's input format, so now we need to run the effect, making sure we output to the intermediary buffer. */
|
|
||||||
if (effectFormatIn == formatIn && effectChannelsIn == channelsIn) {
|
|
||||||
/* Fast path. No input conversion required. */
|
|
||||||
if (effectFormatOut == formatOut && effectChannelsOut == channelsOut) {
|
|
||||||
/* Fast path. Neither input nor output data conversion required. */
|
|
||||||
ma_effect_process_pcm_frames_ex(pEffect, inputStreamCount, ppRunningFramesIn, &framesToProcessThisIterationIn, pRunningFramesOut, &framesToProcessThisIterationOut);
|
|
||||||
} else {
|
|
||||||
/* Slow path. Output conversion required. */
|
|
||||||
ma_effect_process_pcm_frames_ex(pEffect, inputStreamCount, ppRunningFramesIn, &framesToProcessThisIterationIn, effectOutBuffer, &framesToProcessThisIterationOut);
|
|
||||||
ma_convert_pcm_frames_format_and_channels(pRunningFramesOut, formatOut, channelsOut, effectOutBuffer, effectFormatOut, effectChannelsOut, framesToProcessThisIterationOut, ma_dither_mode_none);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Slow path. Input conversion required. */
|
|
||||||
void* ppEffectInBuffer[MA_EFFECT_MAX_INPUT_STREAM_COUNT];
|
|
||||||
|
|
||||||
for (iInputStream = 0; iInputStream < inputStreamCount; iInputStream += 1) {
|
|
||||||
ppEffectInBuffer[iInputStream] = ma_offset_ptr(effectInBuffer, effectInBufferCap * iInputStream);
|
|
||||||
ma_convert_pcm_frames_format_and_channels(ppEffectInBuffer[iInputStream], effectFormatIn, effectChannelsIn, ppRunningFramesIn[iInputStream], formatIn, channelsIn, framesToProcessThisIterationIn, ma_dither_mode_none);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (effectFormatOut == formatOut && effectChannelsOut == channelsOut) {
|
|
||||||
/* Fast path. No output format conversion required. */
|
|
||||||
ma_effect_process_pcm_frames_ex(pEffect, inputStreamCount, (const void**)&ppEffectInBuffer[0], &framesToProcessThisIterationIn, pRunningFramesOut, &framesToProcessThisIterationOut);
|
|
||||||
} else {
|
|
||||||
/* Slow path. Output format conversion required. */
|
|
||||||
ma_effect_process_pcm_frames_ex(pEffect, inputStreamCount, (const void**)&ppEffectInBuffer[0], &framesToProcessThisIterationIn, effectOutBuffer, &framesToProcessThisIterationOut);
|
|
||||||
ma_convert_pcm_frames_format_and_channels(pRunningFramesOut, formatOut, channelsOut, effectOutBuffer, effectFormatOut, effectChannelsOut, framesToProcessThisIterationOut, ma_dither_mode_none);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
totalFramesProcessedIn += framesToProcessThisIterationIn;
|
|
||||||
totalFramesProcessedOut += framesToProcessThisIterationOut;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return MA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ma_uint64 ma_effect_get_required_input_frame_count_local(ma_effect* pEffect, ma_uint64 outputFrameCount)
|
|
||||||
{
|
|
||||||
ma_effect_base* pBase = (ma_effect_base*)pEffect;
|
|
||||||
|
|
||||||
MA_ASSERT(pEffect != NULL);
|
|
||||||
|
|
||||||
if (pBase->onGetRequiredInputFrameCount) {
|
|
||||||
return pBase->onGetRequiredInputFrameCount(pEffect, outputFrameCount);
|
|
||||||
} else {
|
|
||||||
/* If there is no callback, assume a 1:1 mapping. */
|
|
||||||
return outputFrameCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MA_API ma_uint64 ma_effect_get_required_input_frame_count(ma_effect* pEffect, ma_uint64 outputFrameCount)
|
|
||||||
{
|
|
||||||
if (pEffect == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ma_effect_get_required_input_frame_count_local(pEffect, outputFrameCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ma_uint64 ma_effect_get_expected_output_frame_count_local(ma_effect* pEffect, ma_uint64 inputFrameCount)
|
|
||||||
{
|
|
||||||
ma_effect_base* pBase = (ma_effect_base*)pEffect;
|
|
||||||
|
|
||||||
MA_ASSERT(pEffect != NULL);
|
|
||||||
|
|
||||||
if (pBase->onGetExpectedOutputFrameCount) {
|
|
||||||
return pBase->onGetExpectedOutputFrameCount(pEffect, inputFrameCount);
|
|
||||||
} else {
|
|
||||||
/* If there is no callback, assume a 1:1 mapping. */
|
|
||||||
return inputFrameCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MA_API ma_uint64 ma_effect_get_expected_output_frame_count(ma_effect* pEffect, ma_uint64 inputFrameCount)
|
|
||||||
{
|
|
||||||
if (pEffect == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ma_effect_get_expected_output_frame_count_local(pEffect, inputFrameCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
MA_API ma_result ma_effect_get_output_data_format(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
|
|
||||||
{
|
|
||||||
ma_effect_base* pBaseEffect = (ma_effect_base*)pEffect;
|
|
||||||
ma_result result;
|
|
||||||
ma_format format;
|
|
||||||
ma_uint32 channels;
|
|
||||||
ma_uint32 sampleRate;
|
|
||||||
|
|
||||||
if (pFormat != NULL) {
|
|
||||||
*pFormat = ma_format_unknown;
|
|
||||||
}
|
|
||||||
if (pChannels != NULL) {
|
|
||||||
*pChannels = 0;
|
|
||||||
}
|
|
||||||
if (pSampleRate != NULL) {
|
|
||||||
*pSampleRate = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pBaseEffect == NULL || pBaseEffect->onGetOutputDataFormat == NULL) {
|
|
||||||
return MA_INVALID_ARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = pBaseEffect->onGetOutputDataFormat(pEffect, &format, &channels, &sampleRate);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pFormat != NULL) {
|
|
||||||
*pFormat = format;
|
|
||||||
}
|
|
||||||
if (pChannels != NULL) {
|
|
||||||
*pChannels = channels;
|
|
||||||
}
|
|
||||||
if (pSampleRate != NULL) {
|
|
||||||
*pSampleRate = sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
MA_API ma_result ma_effect_get_input_data_format(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
|
|
||||||
{
|
|
||||||
ma_effect_base* pBase = (ma_effect_base*)pEffect;
|
|
||||||
ma_result result;
|
|
||||||
ma_format format;
|
|
||||||
ma_uint32 channels;
|
|
||||||
ma_uint32 sampleRate;
|
|
||||||
|
|
||||||
if (pFormat != NULL) {
|
|
||||||
*pFormat = ma_format_unknown;
|
|
||||||
}
|
|
||||||
if (pChannels != NULL) {
|
|
||||||
*pChannels = 0;
|
|
||||||
}
|
|
||||||
if (pSampleRate != NULL) {
|
|
||||||
*pSampleRate = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = pBase->onGetInputDataFormat(pEffect, &format, &channels, &sampleRate);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pFormat != NULL) {
|
|
||||||
*pFormat = format;
|
|
||||||
}
|
|
||||||
if (pChannels != NULL) {
|
|
||||||
*pChannels = channels;
|
|
||||||
}
|
|
||||||
if (pSampleRate != NULL) {
|
|
||||||
*pSampleRate = sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void ma_accumulate_and_clip_u8(ma_uint8* pDst, const ma_int16* pSrc, ma_uint64 count)
|
static void ma_accumulate_and_clip_u8(ma_uint8* pDst, const ma_int16* pSrc, ma_uint64 count)
|
||||||
{
|
{
|
||||||
@@ -4512,136 +4215,6 @@ static ma_result ma_volume_and_accumulate_and_clip_pcm_frames(void* pDst, const
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static ma_result ma_volume_and_clip_and_effect_pcm_frames(void* pDst, ma_format formatOut, ma_uint32 channelsOut, ma_uint64 frameCountOut, const void* pSrc, ma_format formatIn, ma_uint32 channelsIn, ma_uint64 frameCountIn, float volume, ma_effect* pEffect, ma_bool32 isAccumulation)
|
|
||||||
{
|
|
||||||
ma_result result;
|
|
||||||
ma_uint8 effectBufferIn[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
|
||||||
ma_uint32 effectBufferInCapInFrames;
|
|
||||||
ma_uint8 effectBufferOut[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
|
||||||
ma_uint32 effectBufferOutCapInFrames;
|
|
||||||
ma_format effectFormatIn;
|
|
||||||
ma_uint32 effectChannelsIn;
|
|
||||||
ma_format effectFormatOut;
|
|
||||||
ma_uint32 effectChannelsOut;
|
|
||||||
ma_uint64 totalFramesProcessedOut = 0;
|
|
||||||
ma_uint64 totalFramesProcessedIn = 0;
|
|
||||||
/* */ void* pRunningDst = pDst;
|
|
||||||
const void* pRunningSrc = pSrc;
|
|
||||||
|
|
||||||
if (pDst == NULL || pSrc == NULL || pEffect == NULL) {
|
|
||||||
return MA_INVALID_ARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No op if silent. */
|
|
||||||
if (volume == 0) {
|
|
||||||
return MA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We need to know the effect's input and output formats so we can do pre- and post-effect data conversion if necessary. */
|
|
||||||
ma_effect_get_input_data_format( pEffect, &effectFormatIn, &effectChannelsIn, NULL);
|
|
||||||
ma_effect_get_output_data_format(pEffect, &effectFormatOut, &effectChannelsOut, NULL);
|
|
||||||
|
|
||||||
effectBufferInCapInFrames = sizeof(effectBufferIn ) / ma_get_bytes_per_frame(effectFormatIn, effectChannelsIn );
|
|
||||||
effectBufferOutCapInFrames = sizeof(effectBufferOut) / ma_get_bytes_per_frame(effectFormatOut, effectChannelsOut);
|
|
||||||
|
|
||||||
while (totalFramesProcessedOut < frameCountOut && totalFramesProcessedIn < frameCountIn) {
|
|
||||||
ma_uint64 effectFrameCountIn;
|
|
||||||
ma_uint64 effectFrameCountOut;
|
|
||||||
|
|
||||||
effectFrameCountOut = frameCountOut - totalFramesProcessedOut;
|
|
||||||
if (effectFrameCountOut > effectBufferOutCapInFrames) {
|
|
||||||
effectFrameCountOut = effectBufferOutCapInFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
effectFrameCountIn = ma_effect_get_required_input_frame_count(pEffect, effectFrameCountOut);
|
|
||||||
if (effectFrameCountIn > frameCountIn - totalFramesProcessedIn) {
|
|
||||||
effectFrameCountIn = frameCountIn - totalFramesProcessedIn;
|
|
||||||
}
|
|
||||||
if (effectFrameCountIn > effectBufferInCapInFrames) {
|
|
||||||
effectFrameCountIn = effectBufferInCapInFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
The first step is to get the data ready for the effect. If the effect's input format and channels are the same as the source buffer, we just
|
|
||||||
clip the accumulation buffer straight input the effect's input buffer. Otherwise need to do a conversion.
|
|
||||||
*/
|
|
||||||
if (effectFormatIn == formatIn && effectChannelsIn == channelsIn) {
|
|
||||||
/* Fast path. No data conversion required for the input data except clipping. */
|
|
||||||
ma_volume_and_clip_pcm_frames(effectBufferIn, pRunningSrc, effectFrameCountIn, formatIn, channelsIn, volume);
|
|
||||||
} else {
|
|
||||||
/* Slow path. Data conversion required between the input data and the effect input data. */
|
|
||||||
ma_uint8 clippedSrcBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
|
||||||
ma_uint32 clippedSrcBufferCapInFrames = sizeof(clippedSrcBuffer) / ma_get_bytes_per_frame(formatIn, channelsIn);
|
|
||||||
|
|
||||||
if (effectFrameCountIn > clippedSrcBufferCapInFrames) {
|
|
||||||
effectFrameCountIn = clippedSrcBufferCapInFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
ma_volume_and_clip_pcm_frames(clippedSrcBuffer, pRunningSrc, effectFrameCountIn, formatIn, channelsIn, volume);
|
|
||||||
|
|
||||||
/* At this point the input data has had volume and clipping applied. We can now convert this to the effect's input format. */
|
|
||||||
ma_convert_pcm_frames_format_and_channels(effectBufferIn, effectFormatIn, effectChannelsIn, clippedSrcBuffer, formatIn, channelsIn, effectFrameCountIn, ma_dither_mode_none);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* At this point we have our input data in the effect's input format and we can now apply it. */
|
|
||||||
result = ma_effect_process_pcm_frames(pEffect, effectBufferIn, &effectFrameCountIn, effectBufferOut, &effectFrameCountOut);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
return result; /* Failed to process the effect. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
The effect has been applied. If the effect's output format is the same as the final output we can just accumulate straight into the output buffer,
|
|
||||||
otherwise we need to convert.
|
|
||||||
*/
|
|
||||||
if (effectFormatOut == formatOut && effectChannelsOut == channelsOut) {
|
|
||||||
/* Fast path. No data conversion required for output data. Just accumulate or overwrite. */
|
|
||||||
if (isAccumulation) {
|
|
||||||
ma_unclipped_accumulate_pcm_frames(pRunningDst, effectBufferOut, effectFrameCountOut, effectFormatOut, effectChannelsOut);
|
|
||||||
} else {
|
|
||||||
ma_clip_pcm_frames(pRunningDst, effectBufferOut, effectFrameCountOut, effectFormatOut, effectChannelsOut);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Slow path. Data conversion required before accumulating. */
|
|
||||||
ma_uint8 accumulationInBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
|
||||||
ma_uint32 accumulationInBufferCapInFrames = sizeof(accumulationInBuffer) / ma_get_bytes_per_frame(formatOut, channelsOut);
|
|
||||||
ma_uint64 totalFramesAccumulated = 0;
|
|
||||||
ma_uint8* pRunningEffectBufferOut = effectBufferOut;
|
|
||||||
|
|
||||||
while (totalFramesAccumulated < effectFrameCountOut) {
|
|
||||||
ma_uint64 framesToAccumulate = effectFrameCountOut - totalFramesAccumulated;
|
|
||||||
if (framesToAccumulate > accumulationInBufferCapInFrames) {
|
|
||||||
framesToAccumulate = accumulationInBufferCapInFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We know how many frames to process in this iteration, so first of all do the conversion from the effect's output to the final output format.*/
|
|
||||||
ma_convert_pcm_frames_format_and_channels(accumulationInBuffer, formatOut, channelsOut, pRunningEffectBufferOut, effectFormatOut, effectChannelsOut, framesToAccumulate, ma_dither_mode_none);
|
|
||||||
|
|
||||||
/* We have the data in the final output format, so now we just accumulate or overwrite. */
|
|
||||||
if (isAccumulation) {
|
|
||||||
ma_unclipped_accumulate_pcm_frames(ma_offset_ptr(pRunningDst, totalFramesAccumulated * ma_get_accumulation_bytes_per_frame(formatOut, channelsOut)), accumulationInBuffer, framesToAccumulate, formatOut, channelsOut);
|
|
||||||
} else {
|
|
||||||
ma_clip_pcm_frames(ma_offset_ptr(pRunningDst, totalFramesAccumulated * ma_get_bytes_per_frame(formatOut, channelsOut)), accumulationInBuffer, framesToAccumulate, formatOut, channelsOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
totalFramesAccumulated += framesToAccumulate;
|
|
||||||
pRunningEffectBufferOut = ma_offset_ptr(pRunningEffectBufferOut, framesToAccumulate * ma_get_bytes_per_frame(formatOut, channelsOut));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
totalFramesProcessedIn += effectFrameCountIn;
|
|
||||||
totalFramesProcessedOut += effectFrameCountOut;
|
|
||||||
|
|
||||||
pRunningSrc = ma_offset_ptr(pRunningSrc, effectFrameCountIn * ma_get_accumulation_bytes_per_frame(formatIn, channelsIn));
|
|
||||||
if (isAccumulation) {
|
|
||||||
pRunningDst = ma_offset_ptr(pRunningDst, effectFrameCountOut * ma_get_accumulation_bytes_per_frame(formatIn, channelsIn));
|
|
||||||
} else {
|
|
||||||
pRunningDst = ma_offset_ptr(pRunningDst, effectFrameCountOut * ma_get_bytes_per_frame(formatOut, channelsOut));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return MA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ma_mix_accumulation_buffers_u8(ma_int16* pDst, const ma_int16* pSrc, ma_uint64 sampleCount, float volume)
|
static void ma_mix_accumulation_buffers_u8(ma_int16* pDst, const ma_int16* pSrc, ma_uint64 sampleCount, float volume)
|
||||||
@@ -8208,37 +7781,6 @@ MA_API ma_panner_config ma_panner_config_init(ma_format format, ma_uint32 channe
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ma_result ma_panner_effect__on_process_pcm_frames(ma_effect* pEffect, ma_uint32 inputStreamCount, const void** ppFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
|
|
||||||
{
|
|
||||||
ma_panner* pPanner = (ma_panner*)pEffect;
|
|
||||||
ma_result result;
|
|
||||||
ma_uint64 frameCount;
|
|
||||||
|
|
||||||
(void)inputStreamCount;
|
|
||||||
|
|
||||||
/* The panner has a 1:1 relationship between input and output frame counts. */
|
|
||||||
frameCount = ma_min(*pFrameCountIn, *pFrameCountOut);
|
|
||||||
|
|
||||||
/* Only the first input stream is considered. Extra streams are ignored. */
|
|
||||||
result = ma_panner_process_pcm_frames(pPanner, pFramesOut, ppFramesIn[0], ma_min(*pFrameCountIn, *pFrameCountOut));
|
|
||||||
|
|
||||||
*pFrameCountIn = frameCount;
|
|
||||||
*pFrameCountOut = frameCount;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ma_result ma_panner_effect__on_get_data_format(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
|
|
||||||
{
|
|
||||||
ma_panner* pPanner = (ma_panner*)pEffect;
|
|
||||||
|
|
||||||
*pFormat = pPanner->format;
|
|
||||||
*pChannels = pPanner->channels;
|
|
||||||
*pSampleRate = 0; /* There's no notion of sample rate with this effect. */
|
|
||||||
|
|
||||||
return MA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
MA_API ma_result ma_panner_init(const ma_panner_config* pConfig, ma_panner* pPanner)
|
MA_API ma_result ma_panner_init(const ma_panner_config* pConfig, ma_panner* pPanner)
|
||||||
{
|
{
|
||||||
if (pPanner == NULL) {
|
if (pPanner == NULL) {
|
||||||
@@ -8259,8 +7801,6 @@ MA_API ma_result ma_panner_init(const ma_panner_config* pConfig, ma_panner* pPan
|
|||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ma_stereo_balance_pcm_frames_f32(float* pFramesOut, const float* pFramesIn, ma_uint64 frameCount, float pan)
|
static void ma_stereo_balance_pcm_frames_f32(float* pFramesOut, const float* pFramesIn, ma_uint64 frameCount, float pan)
|
||||||
{
|
{
|
||||||
ma_uint64 iFrame;
|
ma_uint64 iFrame;
|
||||||
@@ -8436,48 +7976,6 @@ MA_API ma_spatializer_config ma_spatializer_config_init(ma_uint32 channelsIn, ma
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ma_result ma_spatializer_effect__on_process_pcm_frames(ma_effect* pEffect, ma_uint32 inputStreamCount, const void** ppFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
|
|
||||||
{
|
|
||||||
ma_spatializer* pSpatializer = (ma_spatializer*)pEffect;
|
|
||||||
ma_result result;
|
|
||||||
ma_uint64 frameCount;
|
|
||||||
|
|
||||||
(void)inputStreamCount;
|
|
||||||
|
|
||||||
/* The spatializer has a 1:1 relationship between input and output frame counts. */
|
|
||||||
frameCount = ma_min(*pFrameCountIn, *pFrameCountOut);
|
|
||||||
|
|
||||||
/* Only the first input stream is considered. Extra streams are ignored. */
|
|
||||||
result = ma_spatializer_process_pcm_frames(pSpatializer, pFramesOut, ppFramesIn[0], frameCount);
|
|
||||||
|
|
||||||
*pFrameCountIn = frameCount;
|
|
||||||
*pFrameCountOut = frameCount;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ma_result ma_spatializer_effect__on_get_data_format_in(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
|
|
||||||
{
|
|
||||||
ma_spatializer* pSpatializer = (ma_spatializer*)pEffect;
|
|
||||||
|
|
||||||
*pFormat = ma_format_f32;
|
|
||||||
*pChannels = pSpatializer->channelsIn;
|
|
||||||
*pSampleRate = 0; /* There's no notion of sample rate with this effect. */
|
|
||||||
|
|
||||||
return MA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ma_result ma_spatializer_effect__on_get_data_format_out(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
|
|
||||||
{
|
|
||||||
ma_spatializer* pSpatializer = (ma_spatializer*)pEffect;
|
|
||||||
|
|
||||||
*pFormat = ma_format_f32;
|
|
||||||
*pChannels = pSpatializer->channelsOut;
|
|
||||||
*pSampleRate = 0; /* There's no notion of sample rate with this effect. */
|
|
||||||
|
|
||||||
return MA_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
MA_API ma_result ma_spatializer_init(const ma_spatializer_config* pConfig, ma_spatializer* pSpatializer)
|
MA_API ma_result ma_spatializer_init(const ma_spatializer_config* pConfig, ma_spatializer* pSpatializer)
|
||||||
{
|
{
|
||||||
if (pSpatializer == NULL) {
|
if (pSpatializer == NULL) {
|
||||||
@@ -8551,31 +8049,6 @@ MA_API ma_fader_config ma_fader_config_init(ma_format format, ma_uint32 channels
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static ma_result ma_fader_effect__on_process_pcm_frames(ma_effect* pEffect, ma_uint32 inputStreamCount, const void** ppFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
|
|
||||||
{
|
|
||||||
ma_fader* pFader = (ma_fader*)pEffect;
|
|
||||||
ma_result result;
|
|
||||||
ma_uint64 frameCount;
|
|
||||||
|
|
||||||
(void)inputStreamCount;
|
|
||||||
|
|
||||||
/* The fader has a 1:1 relationship between input and output frame counts. */
|
|
||||||
frameCount = ma_min(*pFrameCountIn, *pFrameCountOut);
|
|
||||||
|
|
||||||
result = ma_fader_process_pcm_frames(pFader, pFramesOut, ppFramesIn[0], frameCount);
|
|
||||||
|
|
||||||
*pFrameCountIn = frameCount;
|
|
||||||
*pFrameCountOut = frameCount;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ma_result ma_fader_effect__on_get_data_format(ma_effect* pEffect, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
|
|
||||||
{
|
|
||||||
return ma_fader_get_data_format((ma_fader*)pEffect, pFormat, pChannels, pSampleRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
MA_API ma_result ma_fader_init(const ma_fader_config* pConfig, ma_fader* pFader)
|
MA_API ma_result ma_fader_init(const ma_fader_config* pConfig, ma_fader* pFader)
|
||||||
{
|
{
|
||||||
if (pFader == NULL) {
|
if (pFader == NULL) {
|
||||||
|
|||||||
Reference in New Issue
Block a user