mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +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
|
||||
==================================
|
||||
@@ -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
|
||||
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
|
||||
|
||||
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)
|
||||
@@ -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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ma_stereo_balance_pcm_frames_f32(float* pFramesOut, const float* pFramesIn, ma_uint64 frameCount, float pan)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (pFader == NULL) {
|
||||
|
||||
Reference in New Issue
Block a user