mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Move ma_delay out of the MA_NO_NODE_GRAPH section.
This commit is contained in:
+196
-196
@@ -3418,6 +3418,43 @@ MA_API ma_uint32 ma_hishelf2_get_latency(const ma_hishelf2* pFilter);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Delay
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRate;
|
||||
ma_uint32 delayInFrames;
|
||||
ma_bool32 delayStart; /* Set to true to delay the start of the output; false otherwise. */
|
||||
float wet; /* 0..1. Default = 1. */
|
||||
float dry; /* 0..1. Default = 1. */
|
||||
float decay; /* 0..1. Default = 0 (no feedback). Feedback decay. Use this for echo. */
|
||||
} ma_delay_config;
|
||||
|
||||
MA_API ma_delay_config ma_delay_config_init(ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 delayInFrames, float decay);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_delay_config config;
|
||||
ma_uint32 cursor; /* Feedback is written to this cursor. Always equal or in front of the read cursor. */
|
||||
ma_uint32 bufferSizeInFrames; /* The maximum of config.startDelayInFrames and config.feedbackDelayInFrames. */
|
||||
float* pBuffer;
|
||||
} ma_delay;
|
||||
|
||||
MA_API ma_result ma_delay_init(const ma_delay_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_delay* pDelay);
|
||||
MA_API void ma_delay_uninit(ma_delay* pDelay, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
MA_API ma_result ma_delay_process_pcm_frames(ma_delay* pDelay, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount);
|
||||
MA_API void ma_delay_set_wet(ma_delay* pDelay, float value);
|
||||
MA_API float ma_delay_get_wet(const ma_delay* pDelay);
|
||||
MA_API void ma_delay_set_dry(ma_delay* pDelay, float value);
|
||||
MA_API float ma_delay_get_dry(const ma_delay* pDelay);
|
||||
MA_API void ma_delay_set_decay(ma_delay* pDelay, float value);
|
||||
MA_API float ma_delay_get_decay(const ma_delay* pDelay);
|
||||
|
||||
|
||||
|
||||
/************************************************************************************************************************************************************
|
||||
*************************************************************************************************************************************************************
|
||||
|
||||
@@ -8532,44 +8569,6 @@ MA_API ma_result ma_hishelf_node_reinit(const ma_hishelf_config* pConfig, ma_his
|
||||
MA_API void ma_hishelf_node_uninit(ma_hishelf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Delay
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRate;
|
||||
ma_uint32 delayInFrames;
|
||||
ma_bool32 delayStart; /* Set to true to delay the start of the output; false otherwise. */
|
||||
float wet; /* 0..1. Default = 1. */
|
||||
float dry; /* 0..1. Default = 1. */
|
||||
float decay; /* 0..1. Default = 0 (no feedback). Feedback decay. Use this for echo. */
|
||||
} ma_delay_config;
|
||||
|
||||
MA_API ma_delay_config ma_delay_config_init(ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 delayInFrames, float decay);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_delay_config config;
|
||||
ma_uint32 cursor; /* Feedback is written to this cursor. Always equal or in front of the read cursor. */
|
||||
ma_uint32 bufferSizeInFrames; /* The maximum of config.startDelayInFrames and config.feedbackDelayInFrames. */
|
||||
float* pBuffer;
|
||||
} ma_delay;
|
||||
|
||||
MA_API ma_result ma_delay_init(const ma_delay_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_delay* pDelay);
|
||||
MA_API void ma_delay_uninit(ma_delay* pDelay, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
MA_API ma_result ma_delay_process_pcm_frames(ma_delay* pDelay, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount);
|
||||
MA_API void ma_delay_set_wet(ma_delay* pDelay, float value);
|
||||
MA_API float ma_delay_get_wet(const ma_delay* pDelay);
|
||||
MA_API void ma_delay_set_dry(ma_delay* pDelay, float value);
|
||||
MA_API float ma_delay_get_dry(const ma_delay* pDelay);
|
||||
MA_API void ma_delay_set_decay(ma_delay* pDelay, float value);
|
||||
MA_API float ma_delay_get_decay(const ma_delay* pDelay);
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_node_config nodeConfig;
|
||||
@@ -43641,6 +43640,165 @@ MA_API ma_uint32 ma_hishelf2_get_latency(const ma_hishelf2* pFilter)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Delay
|
||||
*/
|
||||
MA_API ma_delay_config ma_delay_config_init(ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 delayInFrames, float decay)
|
||||
{
|
||||
ma_delay_config config;
|
||||
|
||||
MA_ZERO_OBJECT(&config);
|
||||
config.channels = channels;
|
||||
config.sampleRate = sampleRate;
|
||||
config.delayInFrames = delayInFrames;
|
||||
config.delayStart = (decay == 0) ? MA_TRUE : MA_FALSE; /* Delay the start if it looks like we're not configuring an echo. */
|
||||
config.wet = 1;
|
||||
config.dry = 1;
|
||||
config.decay = decay;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
MA_API ma_result ma_delay_init(const ma_delay_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_delay* pDelay)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
MA_ZERO_OBJECT(pDelay);
|
||||
|
||||
if (pConfig == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (pConfig->decay < 0 || pConfig->decay > 1) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
pDelay->config = *pConfig;
|
||||
pDelay->bufferSizeInFrames = pConfig->delayInFrames;
|
||||
pDelay->cursor = 0;
|
||||
|
||||
pDelay->pBuffer = (float*)ma_malloc((size_t)(pDelay->bufferSizeInFrames * ma_get_bytes_per_frame(ma_format_f32, pConfig->channels)), pAllocationCallbacks);
|
||||
if (pDelay->pBuffer == NULL) {
|
||||
return MA_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
ma_silence_pcm_frames(pDelay->pBuffer, pDelay->bufferSizeInFrames, ma_format_f32, pConfig->channels);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API void ma_delay_uninit(ma_delay* pDelay, const ma_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ma_free(pDelay->pBuffer, pAllocationCallbacks);
|
||||
}
|
||||
|
||||
MA_API ma_result ma_delay_process_pcm_frames(ma_delay* pDelay, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
|
||||
{
|
||||
ma_uint32 iFrame;
|
||||
ma_uint32 iChannel;
|
||||
float* pFramesOutF32 = (float*)pFramesOut;
|
||||
const float* pFramesInF32 = (const float*)pFramesIn;
|
||||
|
||||
if (pDelay == NULL || pFramesOut == NULL || pFramesIn == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||
for (iChannel = 0; iChannel < pDelay->config.channels; iChannel += 1) {
|
||||
ma_uint32 iBuffer = (pDelay->cursor * pDelay->config.channels) + iChannel;
|
||||
|
||||
if (pDelay->config.delayStart) {
|
||||
/* Delayed start. */
|
||||
|
||||
/* Read */
|
||||
pFramesOutF32[iChannel] = pDelay->pBuffer[iBuffer] * pDelay->config.wet;
|
||||
|
||||
/* Feedback */
|
||||
pDelay->pBuffer[iBuffer] = (pDelay->pBuffer[iBuffer] * pDelay->config.decay) + (pFramesInF32[iChannel] * pDelay->config.dry);
|
||||
} else {
|
||||
/* Immediate start */
|
||||
|
||||
/* Feedback */
|
||||
pDelay->pBuffer[iBuffer] = (pDelay->pBuffer[iBuffer] * pDelay->config.decay) + (pFramesInF32[iChannel] * pDelay->config.dry);
|
||||
|
||||
/* Read */
|
||||
pFramesOutF32[iChannel] = pDelay->pBuffer[iBuffer] * pDelay->config.wet;
|
||||
}
|
||||
}
|
||||
|
||||
pDelay->cursor = (pDelay->cursor + 1) % pDelay->bufferSizeInFrames;
|
||||
|
||||
pFramesOutF32 += pDelay->config.channels;
|
||||
pFramesInF32 += pDelay->config.channels;
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API void ma_delay_set_wet(ma_delay* pDelay, float value)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pDelay->config.wet = value;
|
||||
}
|
||||
|
||||
MA_API float ma_delay_get_wet(const ma_delay* pDelay)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pDelay->config.wet;
|
||||
}
|
||||
|
||||
MA_API void ma_delay_set_dry(ma_delay* pDelay, float value)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pDelay->config.dry = value;
|
||||
}
|
||||
|
||||
MA_API float ma_delay_get_dry(const ma_delay* pDelay)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pDelay->config.dry;
|
||||
}
|
||||
|
||||
MA_API void ma_delay_set_decay(ma_delay* pDelay, float value)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pDelay->config.decay = value;
|
||||
}
|
||||
|
||||
MA_API float ma_delay_get_decay(const ma_delay* pDelay)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pDelay->config.decay;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************************************************************************************************************
|
||||
|
||||
Resampling
|
||||
@@ -65144,164 +65302,6 @@ MA_API void ma_hishelf_node_uninit(ma_hishelf_node* pNode, const ma_allocation_c
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Delay
|
||||
*/
|
||||
MA_API ma_delay_config ma_delay_config_init(ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 delayInFrames, float decay)
|
||||
{
|
||||
ma_delay_config config;
|
||||
|
||||
MA_ZERO_OBJECT(&config);
|
||||
config.channels = channels;
|
||||
config.sampleRate = sampleRate;
|
||||
config.delayInFrames = delayInFrames;
|
||||
config.delayStart = (decay == 0) ? MA_TRUE : MA_FALSE; /* Delay the start if it looks like we're not configuring an echo. */
|
||||
config.wet = 1;
|
||||
config.dry = 1;
|
||||
config.decay = decay;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
MA_API ma_result ma_delay_init(const ma_delay_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_delay* pDelay)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
MA_ZERO_OBJECT(pDelay);
|
||||
|
||||
if (pConfig == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (pConfig->decay < 0 || pConfig->decay > 1) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
pDelay->config = *pConfig;
|
||||
pDelay->bufferSizeInFrames = pConfig->delayInFrames;
|
||||
pDelay->cursor = 0;
|
||||
|
||||
pDelay->pBuffer = (float*)ma_malloc((size_t)(pDelay->bufferSizeInFrames * ma_get_bytes_per_frame(ma_format_f32, pConfig->channels)), pAllocationCallbacks);
|
||||
if (pDelay->pBuffer == NULL) {
|
||||
return MA_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
ma_silence_pcm_frames(pDelay->pBuffer, pDelay->bufferSizeInFrames, ma_format_f32, pConfig->channels);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API void ma_delay_uninit(ma_delay* pDelay, const ma_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ma_free(pDelay->pBuffer, pAllocationCallbacks);
|
||||
}
|
||||
|
||||
MA_API ma_result ma_delay_process_pcm_frames(ma_delay* pDelay, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
|
||||
{
|
||||
ma_uint32 iFrame;
|
||||
ma_uint32 iChannel;
|
||||
float* pFramesOutF32 = (float*)pFramesOut;
|
||||
const float* pFramesInF32 = (const float*)pFramesIn;
|
||||
|
||||
if (pDelay == NULL || pFramesOut == NULL || pFramesIn == NULL) {
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||
for (iChannel = 0; iChannel < pDelay->config.channels; iChannel += 1) {
|
||||
ma_uint32 iBuffer = (pDelay->cursor * pDelay->config.channels) + iChannel;
|
||||
|
||||
if (pDelay->config.delayStart) {
|
||||
/* Delayed start. */
|
||||
|
||||
/* Read */
|
||||
pFramesOutF32[iChannel] = pDelay->pBuffer[iBuffer] * pDelay->config.wet;
|
||||
|
||||
/* Feedback */
|
||||
pDelay->pBuffer[iBuffer] = (pDelay->pBuffer[iBuffer] * pDelay->config.decay) + (pFramesInF32[iChannel] * pDelay->config.dry);
|
||||
} else {
|
||||
/* Immediate start */
|
||||
|
||||
/* Feedback */
|
||||
pDelay->pBuffer[iBuffer] = (pDelay->pBuffer[iBuffer] * pDelay->config.decay) + (pFramesInF32[iChannel] * pDelay->config.dry);
|
||||
|
||||
/* Read */
|
||||
pFramesOutF32[iChannel] = pDelay->pBuffer[iBuffer] * pDelay->config.wet;
|
||||
}
|
||||
}
|
||||
|
||||
pDelay->cursor = (pDelay->cursor + 1) % pDelay->bufferSizeInFrames;
|
||||
|
||||
pFramesOutF32 += pDelay->config.channels;
|
||||
pFramesInF32 += pDelay->config.channels;
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
MA_API void ma_delay_set_wet(ma_delay* pDelay, float value)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pDelay->config.wet = value;
|
||||
}
|
||||
|
||||
MA_API float ma_delay_get_wet(const ma_delay* pDelay)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pDelay->config.wet;
|
||||
}
|
||||
|
||||
MA_API void ma_delay_set_dry(ma_delay* pDelay, float value)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pDelay->config.dry = value;
|
||||
}
|
||||
|
||||
MA_API float ma_delay_get_dry(const ma_delay* pDelay)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pDelay->config.dry;
|
||||
}
|
||||
|
||||
MA_API void ma_delay_set_decay(ma_delay* pDelay, float value)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pDelay->config.decay = value;
|
||||
}
|
||||
|
||||
MA_API float ma_delay_get_decay(const ma_delay* pDelay)
|
||||
{
|
||||
if (pDelay == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pDelay->config.decay;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
MA_API ma_delay_node_config ma_delay_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 delayInFrames, float decay)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user