mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-24 09:14:04 +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);
|
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
|
typedef struct
|
||||||
{
|
{
|
||||||
ma_node_config nodeConfig;
|
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
|
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)
|
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