Commit ef0abd01 authored by David Reid's avatar David Reid

Add delay effect.

This can be used for echo as well as a simple delay.
parent af72639d
#define MINIAUDIO_IMPLEMENTATION
#include "../../../../miniaudio.h"
#include "../../../miniaudio_engine.h"
#include <stdio.h>
#define DEVICE_FORMAT ma_format_f32; /* Must always be f32 for this example because the node graph system only works with this. */
#define DEVICE_CHANNELS 2
#define DEVICE_SAMPLE_RATE 48000
static ma_audio_buffer_ref g_dataSupply; /* The underlying data source of the source node. */
static ma_data_source_node g_dataSupplyNode; /* The node that will sit at the root level. Will be reading data from g_dataSupply. */
static ma_delay_node g_delayNode; /* The delay node. */
static ma_node_graph g_nodeGraph; /* The main node graph that we'll be feeding data through. */
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
{
MA_ASSERT(pDevice->capture.format == pDevice->playback.format && pDevice->capture.format == ma_format_f32);
MA_ASSERT(pDevice->capture.channels == pDevice->playback.channels);
/*
The node graph system is a pulling style of API. At the lowest level of the chain will be a
node acting as a data source for the purpose of delivering the initial audio data. In our case,
the data source is our `pInput` buffer. We need to update the underlying data source so that it
read data from `pInput`.
*/
ma_audio_buffer_ref_set_data(&g_dataSupply, pInput, frameCount);
/* With the source buffer configured we can now read directly from the node graph. */
ma_node_graph_read_pcm_frames(&g_nodeGraph, pOutput, frameCount, NULL);
}
int main(int argc, char** argv)
{
ma_result result;
ma_device_config deviceConfig;
ma_device device;
ma_node_graph_config nodeGraphConfig;
ma_delay_node_config delayNodeConfig;
ma_data_source_node_config dataSupplyNodeConfig;
deviceConfig = ma_device_config_init(ma_device_type_duplex);
deviceConfig.capture.pDeviceID = NULL;
deviceConfig.capture.format = DEVICE_FORMAT;
deviceConfig.capture.channels = DEVICE_CHANNELS;
deviceConfig.capture.shareMode = ma_share_mode_shared;
deviceConfig.playback.pDeviceID = NULL;
deviceConfig.playback.format = DEVICE_FORMAT;
deviceConfig.playback.channels = DEVICE_CHANNELS;
deviceConfig.dataCallback = data_callback;
result = ma_device_init(NULL, &deviceConfig, &device);
if (result != MA_SUCCESS) {
return result;
}
/* Node graph. */
nodeGraphConfig = ma_node_graph_config_init(device.capture.channels);
result = ma_node_graph_init(&nodeGraphConfig, NULL, &g_nodeGraph);
if (result != MA_SUCCESS) {
printf("Failed to initialize node graph.");
goto done0;
}
/* Reverb. Attached straight to the endpoint. */
delayNodeConfig = ma_delay_node_config_init(device.capture.channels, device.sampleRate, (100 * device.sampleRate) / 1000, 0.5f);
result = ma_delay_node_init(&g_nodeGraph, &delayNodeConfig, NULL, &g_delayNode);
if (result != MA_SUCCESS) {
printf("Failed to initialize vocoder node.");
goto done1;
}
ma_node_attach_output_bus(&g_delayNode, 0, ma_node_graph_get_endpoint(&g_nodeGraph), 0);
/* Data supply. Attached to input bus 0 of the delay node. */
result = ma_audio_buffer_ref_init(device.capture.format, device.capture.channels, NULL, 0, &g_dataSupply);
if (result != MA_SUCCESS) {
printf("Failed to initialize audio buffer for source.");
goto done2;
}
dataSupplyNodeConfig = ma_data_source_node_config_init(&g_dataSupply, MA_FALSE);
result = ma_data_source_node_init(&g_nodeGraph, &dataSupplyNodeConfig, NULL, &g_dataSupplyNode);
if (result != MA_SUCCESS) {
printf("Failed to initialize source node.");
goto done2;
}
ma_node_attach_output_bus(&g_dataSupplyNode, 0, &g_delayNode, 0);
ma_device_start(&device);
printf("Press Enter to quit...\n");
getchar();
/* It's important that we stop the device first or else we'll uninitialize the graph from under the device. */
ma_device_stop(&device);
/*done3:*/ ma_data_source_node_uninit(&g_dataSupplyNode, NULL);
done2: ma_delay_node_uninit(&g_delayNode, NULL);
done1: ma_node_graph_uninit(&g_nodeGraph, NULL);
done0: ma_device_uninit(&device);
(void)argc;
(void)argv;
return 0;
}
...@@ -2008,13 +2008,22 @@ MA_API ma_uint64 ma_sound_group_get_time_in_pcm_frames(const ma_sound_group* pGr ...@@ -2008,13 +2008,22 @@ MA_API ma_uint64 ma_sound_group_get_time_in_pcm_frames(const ma_sound_group* pGr
/* /*
Biquad Node Biquad Node
*/ */
typedef struct
{
ma_node_config nodeConfig;
ma_biquad_config biquad;
} ma_biquad_node_config;
MA_API ma_biquad_node_config ma_biquad_node_config_init(ma_uint32 channels, float b0, float b1, float b2, float a0, float a1, float a2);
typedef struct typedef struct
{ {
ma_node_base baseNode; ma_node_base baseNode;
ma_biquad biquad; ma_biquad biquad;
} ma_biquad_node; } ma_biquad_node;
MA_API ma_result ma_biquad_node_init(ma_node_graph* pNodeGraph, const ma_biquad_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_biquad_node* pNode); MA_API ma_result ma_biquad_node_init(ma_node_graph* pNodeGraph, const ma_biquad_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_biquad_node* pNode);
MA_API ma_result ma_biquad_node_reinit(const ma_biquad_config* pConfig, ma_biquad_node* pNode); MA_API ma_result ma_biquad_node_reinit(const ma_biquad_config* pConfig, ma_biquad_node* pNode);
MA_API void ma_biquad_node_uninit(ma_biquad_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks); MA_API void ma_biquad_node_uninit(ma_biquad_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
...@@ -2022,13 +2031,22 @@ MA_API void ma_biquad_node_uninit(ma_biquad_node* pNode, const ma_allocation_cal ...@@ -2022,13 +2031,22 @@ MA_API void ma_biquad_node_uninit(ma_biquad_node* pNode, const ma_allocation_cal
/* /*
Low Pass Filter Node Low Pass Filter Node
*/ */
typedef struct
{
ma_node_config nodeConfig;
ma_lpf_config lpf;
} ma_lpf_node_config;
MA_API ma_lpf_node_config ma_lpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order);
typedef struct typedef struct
{ {
ma_node_base baseNode; ma_node_base baseNode;
ma_lpf lpf; ma_lpf lpf;
} ma_lpf_node; } ma_lpf_node;
MA_API ma_result ma_lpf_node_init(ma_node_graph* pNodeGraph, const ma_lpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf_node* pNode); MA_API ma_result ma_lpf_node_init(ma_node_graph* pNodeGraph, const ma_lpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf_node* pNode);
MA_API ma_result ma_lpf_node_reinit(const ma_lpf_config* pConfig, ma_lpf_node* pNode); MA_API ma_result ma_lpf_node_reinit(const ma_lpf_config* pConfig, ma_lpf_node* pNode);
MA_API void ma_lpf_node_uninit(ma_lpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks); MA_API void ma_lpf_node_uninit(ma_lpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
...@@ -2036,13 +2054,22 @@ MA_API void ma_lpf_node_uninit(ma_lpf_node* pNode, const ma_allocation_callbacks ...@@ -2036,13 +2054,22 @@ MA_API void ma_lpf_node_uninit(ma_lpf_node* pNode, const ma_allocation_callbacks
/* /*
High Pass Filter Node High Pass Filter Node
*/ */
typedef struct
{
ma_node_config nodeConfig;
ma_hpf_config hpf;
} ma_hpf_node_config;
MA_API ma_hpf_node_config ma_hpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order);
typedef struct typedef struct
{ {
ma_node_base baseNode; ma_node_base baseNode;
ma_hpf hpf; ma_hpf hpf;
} ma_hpf_node; } ma_hpf_node;
MA_API ma_result ma_hpf_node_init(ma_node_graph* pNodeGraph, const ma_hpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf_node* pNode); MA_API ma_result ma_hpf_node_init(ma_node_graph* pNodeGraph, const ma_hpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf_node* pNode);
MA_API ma_result ma_hpf_node_reinit(const ma_hpf_config* pConfig, ma_hpf_node* pNode); MA_API ma_result ma_hpf_node_reinit(const ma_hpf_config* pConfig, ma_hpf_node* pNode);
MA_API void ma_hpf_node_uninit(ma_hpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks); MA_API void ma_hpf_node_uninit(ma_hpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
...@@ -2050,13 +2077,22 @@ MA_API void ma_hpf_node_uninit(ma_hpf_node* pNode, const ma_allocation_callbacks ...@@ -2050,13 +2077,22 @@ MA_API void ma_hpf_node_uninit(ma_hpf_node* pNode, const ma_allocation_callbacks
/* /*
Band Pass Filter Node Band Pass Filter Node
*/ */
typedef struct
{
ma_node_config nodeConfig;
ma_bpf_config bpf;
} ma_bpf_node_config;
MA_API ma_bpf_node_config ma_bpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order);
typedef struct typedef struct
{ {
ma_node_base baseNode; ma_node_base baseNode;
ma_bpf bpf; ma_bpf bpf;
} ma_bpf_node; } ma_bpf_node;
MA_API ma_result ma_bpf_node_init(ma_node_graph* pNodeGraph, const ma_bpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_bpf_node* pNode); MA_API ma_result ma_bpf_node_init(ma_node_graph* pNodeGraph, const ma_bpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_bpf_node* pNode);
MA_API ma_result ma_bpf_node_reinit(const ma_bpf_config* pConfig, ma_bpf_node* pNode); MA_API ma_result ma_bpf_node_reinit(const ma_bpf_config* pConfig, ma_bpf_node* pNode);
MA_API void ma_bpf_node_uninit(ma_bpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks); MA_API void ma_bpf_node_uninit(ma_bpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
...@@ -2064,13 +2100,22 @@ MA_API void ma_bpf_node_uninit(ma_bpf_node* pNode, const ma_allocation_callbacks ...@@ -2064,13 +2100,22 @@ MA_API void ma_bpf_node_uninit(ma_bpf_node* pNode, const ma_allocation_callbacks
/* /*
Notching Filter Node Notching Filter Node
*/ */
typedef struct
{
ma_node_config nodeConfig;
ma_notch_config notch;
} ma_notch_node_config;
MA_API ma_notch_node_config ma_notch_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double q, double frequency);
typedef struct typedef struct
{ {
ma_node_base baseNode; ma_node_base baseNode;
ma_notch2 notch; ma_notch2 notch;
} ma_notch_node; } ma_notch_node;
MA_API ma_result ma_notch_node_init(ma_node_graph* pNodeGraph, const ma_notch_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_notch_node* pNode); MA_API ma_result ma_notch_node_init(ma_node_graph* pNodeGraph, const ma_notch_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_notch_node* pNode);
MA_API ma_result ma_notch_node_reinit(const ma_notch_config* pConfig, ma_notch_node* pNode); MA_API ma_result ma_notch_node_reinit(const ma_notch_config* pConfig, ma_notch_node* pNode);
MA_API void ma_notch_node_uninit(ma_notch_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks); MA_API void ma_notch_node_uninit(ma_notch_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
...@@ -2078,13 +2123,22 @@ MA_API void ma_notch_node_uninit(ma_notch_node* pNode, const ma_allocation_callb ...@@ -2078,13 +2123,22 @@ MA_API void ma_notch_node_uninit(ma_notch_node* pNode, const ma_allocation_callb
/* /*
Peaking Filter Node Peaking Filter Node
*/ */
typedef struct
{
ma_node_config nodeConfig;
ma_peak_config peak;
} ma_peak_node_config;
MA_API ma_peak_node_config ma_peak_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency);
typedef struct typedef struct
{ {
ma_node_base baseNode; ma_node_base baseNode;
ma_peak2 peak; ma_peak2 peak;
} ma_peak_node; } ma_peak_node;
MA_API ma_result ma_peak_node_init(ma_node_graph* pNodeGraph, const ma_peak_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_peak_node* pNode); MA_API ma_result ma_peak_node_init(ma_node_graph* pNodeGraph, const ma_peak_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_peak_node* pNode);
MA_API ma_result ma_peak_node_reinit(const ma_peak_config* pConfig, ma_peak_node* pNode); MA_API ma_result ma_peak_node_reinit(const ma_peak_config* pConfig, ma_peak_node* pNode);
MA_API void ma_peak_node_uninit(ma_peak_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks); MA_API void ma_peak_node_uninit(ma_peak_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
...@@ -2092,13 +2146,22 @@ MA_API void ma_peak_node_uninit(ma_peak_node* pNode, const ma_allocation_callbac ...@@ -2092,13 +2146,22 @@ MA_API void ma_peak_node_uninit(ma_peak_node* pNode, const ma_allocation_callbac
/* /*
Low Shelf Filter Node Low Shelf Filter Node
*/ */
typedef struct
{
ma_node_config nodeConfig;
ma_loshelf_config loshelf;
} ma_loshelf_node_config;
MA_API ma_loshelf_node_config ma_loshelf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency);
typedef struct typedef struct
{ {
ma_node_base baseNode; ma_node_base baseNode;
ma_loshelf2 loshelf; ma_loshelf2 loshelf;
} ma_loshelf_node; } ma_loshelf_node;
MA_API ma_result ma_loshelf_node_init(ma_node_graph* pNodeGraph, const ma_loshelf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_loshelf_node* pNode); MA_API ma_result ma_loshelf_node_init(ma_node_graph* pNodeGraph, const ma_loshelf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_loshelf_node* pNode);
MA_API ma_result ma_loshelf_node_reinit(const ma_loshelf_config* pConfig, ma_loshelf_node* pNode); MA_API ma_result ma_loshelf_node_reinit(const ma_loshelf_config* pConfig, ma_loshelf_node* pNode);
MA_API void ma_loshelf_node_uninit(ma_loshelf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks); MA_API void ma_loshelf_node_uninit(ma_loshelf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
...@@ -2106,16 +2169,89 @@ MA_API void ma_loshelf_node_uninit(ma_loshelf_node* pNode, const ma_allocation_c ...@@ -2106,16 +2169,89 @@ MA_API void ma_loshelf_node_uninit(ma_loshelf_node* pNode, const ma_allocation_c
/* /*
High Shelf Filter Node High Shelf Filter Node
*/ */
typedef struct
{
ma_node_config nodeConfig;
ma_hishelf_config hishelf;
} ma_hishelf_node_config;
MA_API ma_hishelf_node_config ma_hishelf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency);
typedef struct typedef struct
{ {
ma_node_base baseNode; ma_node_base baseNode;
ma_hishelf2 hishelf; ma_hishelf2 hishelf;
} ma_hishelf_node; } ma_hishelf_node;
MA_API ma_result ma_hishelf_node_init(ma_node_graph* pNodeGraph, const ma_hishelf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hishelf_node* pNode); MA_API ma_result ma_hishelf_node_init(ma_node_graph* pNodeGraph, const ma_hishelf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hishelf_node* pNode);
MA_API ma_result ma_hishelf_node_reinit(const ma_hishelf_config* pConfig, ma_hishelf_node* pNode); MA_API ma_result ma_hishelf_node_reinit(const ma_hishelf_config* pConfig, ma_hishelf_node* pNode);
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
{
ma_node_config nodeConfig;
ma_delay_config delay;
} ma_delay_node_config;
MA_API ma_delay_node_config ma_delay_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 delayInFrames, float decay);
typedef struct
{
ma_node_base baseNode;
ma_delay delay;
} ma_delay_node;
MA_API ma_result ma_delay_node_init(ma_node_graph* pNodeGraph, const ma_delay_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_delay_node* pDelayNode);
MA_API void ma_delay_node_uninit(ma_delay_node* pDelayNode, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API void ma_delay_node_set_wet(ma_delay_node* pDelayNode, float value);
MA_API float ma_delay_node_get_wet(const ma_delay_node* pDelayNode);
MA_API void ma_delay_node_set_dry(ma_delay_node* pDelayNode, float value);
MA_API float ma_delay_node_get_dry(const ma_delay_node* pDelayNode);
MA_API void ma_delay_node_set_decay(ma_delay_node* pDelayNode, float value);
MA_API float ma_delay_node_get_decay(const ma_delay_node* pDelayNode);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
...@@ -13202,6 +13338,16 @@ MA_API ma_uint64 ma_sound_group_get_time_in_pcm_frames(const ma_sound_group* pGr ...@@ -13202,6 +13338,16 @@ MA_API ma_uint64 ma_sound_group_get_time_in_pcm_frames(const ma_sound_group* pGr
/* /*
Biquad Node Biquad Node
*/ */
MA_API ma_biquad_node_config ma_biquad_node_config_init(ma_uint32 channels, float b0, float b1, float b2, float a0, float a1, float a2)
{
ma_biquad_node_config config;
config.nodeConfig = ma_node_config_init();
config.biquad = ma_biquad_config_init(ma_format_f32, channels, b0, b1, b2, a0, a1, a2);
return config;
}
static void ma_biquad_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut) static void ma_biquad_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{ {
ma_biquad_node* pLPFNode = (ma_biquad_node*)pNode; ma_biquad_node* pLPFNode = (ma_biquad_node*)pNode;
...@@ -13221,7 +13367,7 @@ static ma_node_vtable g_ma_biquad_node_vtable = ...@@ -13221,7 +13367,7 @@ static ma_node_vtable g_ma_biquad_node_vtable =
0 /* Default flags. */ 0 /* Default flags. */
}; };
MA_API ma_result ma_biquad_node_init(ma_node_graph* pNodeGraph, const ma_biquad_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_biquad_node* pNode) MA_API ma_result ma_biquad_node_init(ma_node_graph* pNodeGraph, const ma_biquad_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_biquad_node* pNode)
{ {
ma_result result; ma_result result;
ma_node_config baseNodeConfig; ma_node_config baseNodeConfig;
...@@ -13236,23 +13382,22 @@ MA_API ma_result ma_biquad_node_init(ma_node_graph* pNodeGraph, const ma_biquad_ ...@@ -13236,23 +13382,22 @@ MA_API ma_result ma_biquad_node_init(ma_node_graph* pNodeGraph, const ma_biquad_
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pConfig->format != ma_format_f32) { if (pConfig->biquad.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */ return MA_INVALID_ARGS; /* The format must be f32. */
} }
baseNodeConfig = ma_node_config_init(); result = ma_biquad_init(&pConfig->biquad, &pNode->biquad);
baseNodeConfig.vtable = &g_ma_biquad_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->channels;
baseNodeConfig.outputChannels[0] = pConfig->channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
result = ma_biquad_init(pConfig, &pNode->biquad); baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_biquad_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->biquad.channels;
baseNodeConfig.outputChannels[0] = pConfig->biquad.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_node_uninit(pNode, pAllocationCallbacks);
return result; return result;
} }
...@@ -13278,6 +13423,16 @@ MA_API void ma_biquad_node_uninit(ma_biquad_node* pNode, const ma_allocation_cal ...@@ -13278,6 +13423,16 @@ MA_API void ma_biquad_node_uninit(ma_biquad_node* pNode, const ma_allocation_cal
/* /*
Low Pass Filter Node Low Pass Filter Node
*/ */
MA_API ma_lpf_node_config ma_lpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
{
ma_lpf_node_config config;
config.nodeConfig = ma_node_config_init();
config.lpf = ma_lpf_config_init(ma_format_f32, channels, sampleRate, cutoffFrequency, order);
return config;
}
static void ma_lpf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut) static void ma_lpf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{ {
ma_lpf_node* pLPFNode = (ma_lpf_node*)pNode; ma_lpf_node* pLPFNode = (ma_lpf_node*)pNode;
...@@ -13297,7 +13452,7 @@ static ma_node_vtable g_ma_lpf_node_vtable = ...@@ -13297,7 +13452,7 @@ static ma_node_vtable g_ma_lpf_node_vtable =
0 /* Default flags. */ 0 /* Default flags. */
}; };
MA_API ma_result ma_lpf_node_init(ma_node_graph* pNodeGraph, const ma_lpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf_node* pNode) MA_API ma_result ma_lpf_node_init(ma_node_graph* pNodeGraph, const ma_lpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf_node* pNode)
{ {
ma_result result; ma_result result;
ma_node_config baseNodeConfig; ma_node_config baseNodeConfig;
...@@ -13312,23 +13467,22 @@ MA_API ma_result ma_lpf_node_init(ma_node_graph* pNodeGraph, const ma_lpf_config ...@@ -13312,23 +13467,22 @@ MA_API ma_result ma_lpf_node_init(ma_node_graph* pNodeGraph, const ma_lpf_config
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pConfig->format != ma_format_f32) { if (pConfig->lpf.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */ return MA_INVALID_ARGS; /* The format must be f32. */
} }
baseNodeConfig = ma_node_config_init(); result = ma_lpf_init(&pConfig->lpf, &pNode->lpf);
baseNodeConfig.vtable = &g_ma_lpf_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->channels;
baseNodeConfig.outputChannels[0] = pConfig->channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
result = ma_lpf_init(pConfig, &pNode->lpf); baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_lpf_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->lpf.channels;
baseNodeConfig.outputChannels[0] = pConfig->lpf.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_node_uninit(pNode, pAllocationCallbacks);
return result; return result;
} }
...@@ -13354,6 +13508,16 @@ MA_API void ma_lpf_node_uninit(ma_lpf_node* pNode, const ma_allocation_callbacks ...@@ -13354,6 +13508,16 @@ MA_API void ma_lpf_node_uninit(ma_lpf_node* pNode, const ma_allocation_callbacks
/* /*
High Pass Filter Node High Pass Filter Node
*/ */
MA_API ma_hpf_node_config ma_hpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
{
ma_hpf_node_config config;
config.nodeConfig = ma_node_config_init();
config.hpf = ma_hpf_config_init(ma_format_f32, channels, sampleRate, cutoffFrequency, order);
return config;
}
static void ma_hpf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut) static void ma_hpf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{ {
ma_hpf_node* pHPFNode = (ma_hpf_node*)pNode; ma_hpf_node* pHPFNode = (ma_hpf_node*)pNode;
...@@ -13373,7 +13537,7 @@ static ma_node_vtable g_ma_hpf_node_vtable = ...@@ -13373,7 +13537,7 @@ static ma_node_vtable g_ma_hpf_node_vtable =
0 /* Default flags. */ 0 /* Default flags. */
}; };
MA_API ma_result ma_hpf_node_init(ma_node_graph* pNodeGraph, const ma_hpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf_node* pNode) MA_API ma_result ma_hpf_node_init(ma_node_graph* pNodeGraph, const ma_hpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf_node* pNode)
{ {
ma_result result; ma_result result;
ma_node_config baseNodeConfig; ma_node_config baseNodeConfig;
...@@ -13388,23 +13552,22 @@ MA_API ma_result ma_hpf_node_init(ma_node_graph* pNodeGraph, const ma_hpf_config ...@@ -13388,23 +13552,22 @@ MA_API ma_result ma_hpf_node_init(ma_node_graph* pNodeGraph, const ma_hpf_config
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pConfig->format != ma_format_f32) { if (pConfig->hpf.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */ return MA_INVALID_ARGS; /* The format must be f32. */
} }
baseNodeConfig = ma_node_config_init(); result = ma_hpf_init(&pConfig->hpf, &pNode->hpf);
baseNodeConfig.vtable = &g_ma_hpf_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->channels;
baseNodeConfig.outputChannels[0] = pConfig->channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
result = ma_hpf_init(pConfig, &pNode->hpf); baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_hpf_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->hpf.channels;
baseNodeConfig.outputChannels[0] = pConfig->hpf.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_node_uninit(pNode, pAllocationCallbacks);
return result; return result;
} }
...@@ -13431,6 +13594,16 @@ MA_API void ma_hpf_node_uninit(ma_hpf_node* pNode, const ma_allocation_callbacks ...@@ -13431,6 +13594,16 @@ MA_API void ma_hpf_node_uninit(ma_hpf_node* pNode, const ma_allocation_callbacks
/* /*
Band Pass Filter Node Band Pass Filter Node
*/ */
MA_API ma_bpf_node_config ma_bpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
{
ma_bpf_node_config config;
config.nodeConfig = ma_node_config_init();
config.bpf = ma_bpf_config_init(ma_format_f32, channels, sampleRate, cutoffFrequency, order);
return config;
}
static void ma_bpf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut) static void ma_bpf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{ {
ma_bpf_node* pBPFNode = (ma_bpf_node*)pNode; ma_bpf_node* pBPFNode = (ma_bpf_node*)pNode;
...@@ -13450,7 +13623,7 @@ static ma_node_vtable g_ma_bpf_node_vtable = ...@@ -13450,7 +13623,7 @@ static ma_node_vtable g_ma_bpf_node_vtable =
0 /* Default flags. */ 0 /* Default flags. */
}; };
MA_API ma_result ma_bpf_node_init(ma_node_graph* pNodeGraph, const ma_bpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_bpf_node* pNode) MA_API ma_result ma_bpf_node_init(ma_node_graph* pNodeGraph, const ma_bpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_bpf_node* pNode)
{ {
ma_result result; ma_result result;
ma_node_config baseNodeConfig; ma_node_config baseNodeConfig;
...@@ -13465,23 +13638,22 @@ MA_API ma_result ma_bpf_node_init(ma_node_graph* pNodeGraph, const ma_bpf_config ...@@ -13465,23 +13638,22 @@ MA_API ma_result ma_bpf_node_init(ma_node_graph* pNodeGraph, const ma_bpf_config
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pConfig->format != ma_format_f32) { if (pConfig->bpf.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */ return MA_INVALID_ARGS; /* The format must be f32. */
} }
baseNodeConfig = ma_node_config_init(); result = ma_bpf_init(&pConfig->bpf, &pNode->bpf);
baseNodeConfig.vtable = &g_ma_bpf_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->channels;
baseNodeConfig.outputChannels[0] = pConfig->channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
result = ma_bpf_init(pConfig, &pNode->bpf); baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_bpf_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->bpf.channels;
baseNodeConfig.outputChannels[0] = pConfig->bpf.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_node_uninit(pNode, pAllocationCallbacks);
return result; return result;
} }
...@@ -13507,6 +13679,16 @@ MA_API void ma_bpf_node_uninit(ma_bpf_node* pNode, const ma_allocation_callbacks ...@@ -13507,6 +13679,16 @@ MA_API void ma_bpf_node_uninit(ma_bpf_node* pNode, const ma_allocation_callbacks
/* /*
Notching Filter Node Notching Filter Node
*/ */
MA_API ma_notch_node_config ma_notch_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double q, double frequency)
{
ma_notch_node_config config;
config.nodeConfig = ma_node_config_init();
config.notch = ma_notch2_config_init(ma_format_f32, channels, sampleRate, q, frequency);
return config;
}
static void ma_notch_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut) static void ma_notch_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{ {
ma_notch_node* pBPFNode = (ma_notch_node*)pNode; ma_notch_node* pBPFNode = (ma_notch_node*)pNode;
...@@ -13526,7 +13708,7 @@ static ma_node_vtable g_ma_notch_node_vtable = ...@@ -13526,7 +13708,7 @@ static ma_node_vtable g_ma_notch_node_vtable =
0 /* Default flags. */ 0 /* Default flags. */
}; };
MA_API ma_result ma_notch_node_init(ma_node_graph* pNodeGraph, const ma_notch_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_notch_node* pNode) MA_API ma_result ma_notch_node_init(ma_node_graph* pNodeGraph, const ma_notch_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_notch_node* pNode)
{ {
ma_result result; ma_result result;
ma_node_config baseNodeConfig; ma_node_config baseNodeConfig;
...@@ -13541,23 +13723,22 @@ MA_API ma_result ma_notch_node_init(ma_node_graph* pNodeGraph, const ma_notch_co ...@@ -13541,23 +13723,22 @@ MA_API ma_result ma_notch_node_init(ma_node_graph* pNodeGraph, const ma_notch_co
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pConfig->format != ma_format_f32) { if (pConfig->notch.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */ return MA_INVALID_ARGS; /* The format must be f32. */
} }
baseNodeConfig = ma_node_config_init(); result = ma_notch2_init(&pConfig->notch, &pNode->notch);
baseNodeConfig.vtable = &g_ma_notch_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->channels;
baseNodeConfig.outputChannels[0] = pConfig->channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
result = ma_notch2_init(pConfig, &pNode->notch); baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_notch_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->notch.channels;
baseNodeConfig.outputChannels[0] = pConfig->notch.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_node_uninit(pNode, pAllocationCallbacks);
return result; return result;
} }
...@@ -13583,6 +13764,16 @@ MA_API void ma_notch_node_uninit(ma_notch_node* pNode, const ma_allocation_callb ...@@ -13583,6 +13764,16 @@ MA_API void ma_notch_node_uninit(ma_notch_node* pNode, const ma_allocation_callb
/* /*
Peaking Filter Node Peaking Filter Node
*/ */
MA_API ma_peak_node_config ma_peak_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency)
{
ma_peak_node_config config;
config.nodeConfig = ma_node_config_init();
config.peak = ma_peak2_config_init(ma_format_f32, channels, sampleRate, gainDB, q, frequency);
return config;
}
static void ma_peak_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut) static void ma_peak_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{ {
ma_peak_node* pBPFNode = (ma_peak_node*)pNode; ma_peak_node* pBPFNode = (ma_peak_node*)pNode;
...@@ -13602,7 +13793,7 @@ static ma_node_vtable g_ma_peak_node_vtable = ...@@ -13602,7 +13793,7 @@ static ma_node_vtable g_ma_peak_node_vtable =
0 /* Default flags. */ 0 /* Default flags. */
}; };
MA_API ma_result ma_peak_node_init(ma_node_graph* pNodeGraph, const ma_peak_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_peak_node* pNode) MA_API ma_result ma_peak_node_init(ma_node_graph* pNodeGraph, const ma_peak_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_peak_node* pNode)
{ {
ma_result result; ma_result result;
ma_node_config baseNodeConfig; ma_node_config baseNodeConfig;
...@@ -13617,23 +13808,23 @@ MA_API ma_result ma_peak_node_init(ma_node_graph* pNodeGraph, const ma_peak_conf ...@@ -13617,23 +13808,23 @@ MA_API ma_result ma_peak_node_init(ma_node_graph* pNodeGraph, const ma_peak_conf
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pConfig->format != ma_format_f32) { if (pConfig->peak.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */ return MA_INVALID_ARGS; /* The format must be f32. */
} }
baseNodeConfig = ma_node_config_init(); result = ma_peak2_init(&pConfig->peak, &pNode->peak);
baseNodeConfig.vtable = &g_ma_peak_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->channels;
baseNodeConfig.outputChannels[0] = pConfig->channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_node_uninit(pNode, pAllocationCallbacks);
return result; return result;
} }
result = ma_peak2_init(pConfig, &pNode->peak); baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_peak_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->peak.channels;
baseNodeConfig.outputChannels[0] = pConfig->peak.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_node_uninit(pNode, pAllocationCallbacks);
return result; return result;
} }
...@@ -13659,6 +13850,16 @@ MA_API void ma_peak_node_uninit(ma_peak_node* pNode, const ma_allocation_callbac ...@@ -13659,6 +13850,16 @@ MA_API void ma_peak_node_uninit(ma_peak_node* pNode, const ma_allocation_callbac
/* /*
Low Shelf Filter Node Low Shelf Filter Node
*/ */
MA_API ma_loshelf_node_config ma_loshelf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency)
{
ma_loshelf_node_config config;
config.nodeConfig = ma_node_config_init();
config.loshelf = ma_loshelf2_config_init(ma_format_f32, channels, sampleRate, gainDB, q, frequency);
return config;
}
static void ma_loshelf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut) static void ma_loshelf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{ {
ma_loshelf_node* pBPFNode = (ma_loshelf_node*)pNode; ma_loshelf_node* pBPFNode = (ma_loshelf_node*)pNode;
...@@ -13678,7 +13879,7 @@ static ma_node_vtable g_ma_loshelf_node_vtable = ...@@ -13678,7 +13879,7 @@ static ma_node_vtable g_ma_loshelf_node_vtable =
0 /* Default flags. */ 0 /* Default flags. */
}; };
MA_API ma_result ma_loshelf_node_init(ma_node_graph* pNodeGraph, const ma_loshelf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_loshelf_node* pNode) MA_API ma_result ma_loshelf_node_init(ma_node_graph* pNodeGraph, const ma_loshelf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_loshelf_node* pNode)
{ {
ma_result result; ma_result result;
ma_node_config baseNodeConfig; ma_node_config baseNodeConfig;
...@@ -13693,23 +13894,22 @@ MA_API ma_result ma_loshelf_node_init(ma_node_graph* pNodeGraph, const ma_loshel ...@@ -13693,23 +13894,22 @@ MA_API ma_result ma_loshelf_node_init(ma_node_graph* pNodeGraph, const ma_loshel
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pConfig->format != ma_format_f32) { if (pConfig->loshelf.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */ return MA_INVALID_ARGS; /* The format must be f32. */
} }
baseNodeConfig = ma_node_config_init(); result = ma_loshelf2_init(&pConfig->loshelf, &pNode->loshelf);
baseNodeConfig.vtable = &g_ma_loshelf_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->channels;
baseNodeConfig.outputChannels[0] = pConfig->channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
result = ma_loshelf2_init(pConfig, &pNode->loshelf); baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_loshelf_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->loshelf.channels;
baseNodeConfig.outputChannels[0] = pConfig->loshelf.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_node_uninit(pNode, pAllocationCallbacks);
return result; return result;
} }
...@@ -13735,6 +13935,16 @@ MA_API void ma_loshelf_node_uninit(ma_loshelf_node* pNode, const ma_allocation_c ...@@ -13735,6 +13935,16 @@ MA_API void ma_loshelf_node_uninit(ma_loshelf_node* pNode, const ma_allocation_c
/* /*
High Shelf Filter Node High Shelf Filter Node
*/ */
MA_API ma_hishelf_node_config ma_hishelf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency)
{
ma_hishelf_node_config config;
config.nodeConfig = ma_node_config_init();
config.hishelf = ma_hishelf2_config_init(ma_format_f32, channels, sampleRate, gainDB, q, frequency);
return config;
}
static void ma_hishelf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut) static void ma_hishelf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{ {
ma_hishelf_node* pBPFNode = (ma_hishelf_node*)pNode; ma_hishelf_node* pBPFNode = (ma_hishelf_node*)pNode;
...@@ -13754,7 +13964,7 @@ static ma_node_vtable g_ma_hishelf_node_vtable = ...@@ -13754,7 +13964,7 @@ static ma_node_vtable g_ma_hishelf_node_vtable =
0 /* Default flags. */ 0 /* Default flags. */
}; };
MA_API ma_result ma_hishelf_node_init(ma_node_graph* pNodeGraph, const ma_hishelf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hishelf_node* pNode) MA_API ma_result ma_hishelf_node_init(ma_node_graph* pNodeGraph, const ma_hishelf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hishelf_node* pNode)
{ {
ma_result result; ma_result result;
ma_node_config baseNodeConfig; ma_node_config baseNodeConfig;
...@@ -13769,23 +13979,22 @@ MA_API ma_result ma_hishelf_node_init(ma_node_graph* pNodeGraph, const ma_hishel ...@@ -13769,23 +13979,22 @@ MA_API ma_result ma_hishelf_node_init(ma_node_graph* pNodeGraph, const ma_hishel
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
if (pConfig->format != ma_format_f32) { if (pConfig->hishelf.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */ return MA_INVALID_ARGS; /* The format must be f32. */
} }
baseNodeConfig = ma_node_config_init(); result = ma_hishelf2_init(&pConfig->hishelf, &pNode->hishelf);
baseNodeConfig.vtable = &g_ma_hishelf_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->channels;
baseNodeConfig.outputChannels[0] = pConfig->channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
result = ma_hishelf2_init(pConfig, &pNode->hishelf); baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_hishelf_node_vtable;
baseNodeConfig.inputChannels[0] = pConfig->hishelf.channels;
baseNodeConfig.outputChannels[0] = pConfig->hishelf.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_node_uninit(pNode, pAllocationCallbacks);
return result; return result;
} }
...@@ -13806,4 +14015,291 @@ MA_API void ma_hishelf_node_uninit(ma_hishelf_node* pNode, const ma_allocation_c ...@@ -13806,4 +14015,291 @@ MA_API void ma_hishelf_node_uninit(ma_hishelf_node* pNode, const ma_allocation_c
ma_node_uninit(pNode, pAllocationCallbacks); ma_node_uninit(pNode, pAllocationCallbacks);
} }
/*
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_delay_node_config config;
config.nodeConfig = ma_node_config_init();
config.delay = ma_delay_config_init(channels, sampleRate, delayInFrames, decay);
return config;
}
static void ma_delay_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_delay_node* pDelayNode = (ma_delay_node*)pNode;
(void)pFrameCountIn;
ma_delay_process_pcm_frames(&pDelayNode->delay, ppFramesOut[0], ppFramesIn[0], *pFrameCountOut);
}
static ma_node_vtable g_ma_delay_node_vtable =
{
ma_delay_node_process_pcm_frames,
NULL,
1, /* 1 input channels. */
1, /* 1 output channel. */
MA_NODE_FLAG_CONTINUOUS_PROCESSING /* Reverb requires continuous processing to ensure the tail get's processed. */
};
MA_API ma_result ma_delay_node_init(ma_node_graph* pNodeGraph, const ma_delay_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_delay_node* pDelayNode)
{
ma_result result;
ma_node_config baseConfig;
if (pDelayNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pDelayNode);
result = ma_delay_init(&pConfig->delay, pAllocationCallbacks, &pDelayNode->delay);
if (result != MA_SUCCESS) {
return result;
}
baseConfig = pConfig->nodeConfig;
baseConfig.vtable = &g_ma_delay_node_vtable;
baseConfig.inputChannels [0] = pConfig->delay.channels;
baseConfig.inputChannels [1] = 0; /* Unused. */
baseConfig.outputChannels[0] = pConfig->delay.channels;
baseConfig.outputChannels[1] = 0; /* Unused. */
result = ma_node_init(pNodeGraph, &baseConfig, pAllocationCallbacks, &pDelayNode->baseNode);
if (result != MA_SUCCESS) {
ma_delay_uninit(&pDelayNode->delay, pAllocationCallbacks);
return result;
}
return result;
}
MA_API void ma_delay_node_uninit(ma_delay_node* pDelayNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pDelayNode == NULL) {
return;
}
/* The base node is always uninitialized first. */
ma_node_uninit(pDelayNode, pAllocationCallbacks);
ma_delay_uninit(&pDelayNode->delay, pAllocationCallbacks);
}
MA_API void ma_delay_node_set_wet(ma_delay_node* pDelayNode, float value)
{
if (pDelayNode == NULL) {
return;
}
ma_delay_set_wet(&pDelayNode->delay, value);
}
MA_API float ma_delay_node_get_wet(const ma_delay_node* pDelayNode)
{
if (pDelayNode == NULL) {
return 0;
}
return ma_delay_get_wet(&pDelayNode->delay);
}
MA_API void ma_delay_node_set_dry(ma_delay_node* pDelayNode, float value)
{
if (pDelayNode == NULL) {
return;
}
ma_delay_set_dry(&pDelayNode->delay, value);
}
MA_API float ma_delay_node_get_dry(const ma_delay_node* pDelayNode)
{
if (pDelayNode == NULL) {
return 0;
}
return ma_delay_get_dry(&pDelayNode->delay);
}
MA_API void ma_delay_node_set_decay(ma_delay_node* pDelayNode, float value)
{
if (pDelayNode == NULL) {
return;
}
ma_delay_set_decay(&pDelayNode->delay, value);
}
MA_API float ma_delay_node_get_decay(const ma_delay_node* pDelayNode)
{
if (pDelayNode == NULL) {
return 0;
}
return ma_delay_get_decay(&pDelayNode->delay);
}
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment