init
This commit is contained in:
commit
f698a38c7e
585 changed files with 118338 additions and 0 deletions
|
@ -0,0 +1,133 @@
|
|||
/*===============================================================================================
|
||||
Raw Codec Plugin Example
|
||||
Copyright (c), Firelight Technologies Pty, Ltd 2004-2025.
|
||||
|
||||
This example shows how to create a codec that reads raw PCM data.
|
||||
|
||||
1. The codec can be compiled as a DLL, using the reserved function name 'FMODGetCodecDescription'
|
||||
as the only export symbol, and at runtime, the dll can be loaded in with System::loadPlugin.
|
||||
|
||||
2. Alternatively a codec of this type can be compiled directly into the program that uses it, and
|
||||
you just register the codec into FMOD with System::registerCodec. This puts the codec into
|
||||
the FMOD system, just the same way System::loadPlugin would if it was an external file.
|
||||
|
||||
3. The 'open' callback is the first thing called, and FMOD already has a file handle open for it.
|
||||
In the open callback you can use FMOD_CODEC_STATE::fileread / FMOD_CODEC_STATE::fileseek to parse
|
||||
your own file format, and return FMOD_ERR_FORMAT if it is not the format you support. Return
|
||||
FMOD_OK if it succeeds your format test.
|
||||
|
||||
4. When an FMOD user calls System::createSound or System::createStream, the 'open' callback is called
|
||||
once after FMOD tries to open it as many other types of file. If you want to override FMOD's
|
||||
internal codecs then use the 'priority' parameter of System::loadPlugin or System::registerCodec.
|
||||
|
||||
5. In the open callback, tell FMOD what sort of PCM format the sound will produce with the
|
||||
FMOD_CODEC_STATE::waveformat member.
|
||||
|
||||
6. The 'close' callback is called when Sound::release is called by the FMOD user.
|
||||
|
||||
7. The 'read' callback is called when System::createSound or System::createStream wants to receive
|
||||
PCM data, in the format that you specified with FMOD_CODEC_STATE::waveformat. Data is
|
||||
interleaved as decribed in the terminology section of the FMOD API documentation.
|
||||
When a stream is being used, the read callback will be called repeatedly, using a size value
|
||||
determined by the decode buffer size of the stream. See FMOD_CREATESOUNDEXINFO or
|
||||
FMOD_ADVANCEDSETTINGS.
|
||||
|
||||
8. The 'seek' callback is called when Channel::setPosition is called, or when looping a sound
|
||||
when it is a stream.
|
||||
|
||||
===============================================================================================*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "fmod.h"
|
||||
|
||||
FMOD_RESULT F_CALL rawopen(FMOD_CODEC_STATE *codec, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
|
||||
FMOD_RESULT F_CALL rawclose(FMOD_CODEC_STATE *codec);
|
||||
FMOD_RESULT F_CALL rawread(FMOD_CODEC_STATE *codec, void *buffer, unsigned int size, unsigned int *read);
|
||||
FMOD_RESULT F_CALL rawsetposition(FMOD_CODEC_STATE *codec, int subsound, unsigned int position, FMOD_TIMEUNIT postype);
|
||||
|
||||
FMOD_CODEC_DESCRIPTION rawcodec =
|
||||
{
|
||||
FMOD_CODEC_PLUGIN_VERSION, // Plugin version.
|
||||
"FMOD Raw player plugin example", // Name.
|
||||
0x00010000, // Version 0xAAAABBBB A = major, B = minor.
|
||||
0, // Don't force everything using this codec to be a stream
|
||||
FMOD_TIMEUNIT_PCMBYTES, // The time format we would like to accept into setposition/getposition.
|
||||
&rawopen, // Open callback.
|
||||
&rawclose, // Close callback.
|
||||
&rawread, // Read callback.
|
||||
0, // Getlength callback. (If not specified FMOD return the length in FMOD_TIMEUNIT_PCM, FMOD_TIMEUNIT_MS or FMOD_TIMEUNIT_PCMBYTES units based on the lengthpcm member of the FMOD_CODEC structure).
|
||||
&rawsetposition, // Setposition callback.
|
||||
0, // Getposition callback. (only used for timeunit types that are not FMOD_TIMEUNIT_PCM, FMOD_TIMEUNIT_MS and FMOD_TIMEUNIT_PCMBYTES).
|
||||
0 // Sound create callback (don't need it)
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
FMODGetCodecDescription is mandatory for every fmod plugin. This is the symbol the registerplugin function searches for.
|
||||
Must be declared with F_CALL to make it export as stdcall.
|
||||
MUST BE EXTERN'ED AS C! C++ functions will be mangled incorrectly and not load in fmod.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
F_EXPORT FMOD_CODEC_DESCRIPTION * F_CALL FMODGetCodecDescription()
|
||||
{
|
||||
return &rawcodec;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static FMOD_CODEC_WAVEFORMAT rawwaveformat;
|
||||
|
||||
/*
|
||||
The actual codec code.
|
||||
|
||||
Note that the callbacks uses FMOD's supplied file system callbacks.
|
||||
|
||||
This is important as even though you might want to open the file yourself, you would lose the following benefits.
|
||||
1. Automatic support of memory files, CDDA based files, and HTTP/TCPIP based files.
|
||||
2. "fileoffset" / "length" support when user calls System::createSound with FMOD_CREATESOUNDEXINFO structure.
|
||||
3. Buffered file access.
|
||||
FMOD files are high level abstracts that support all sorts of 'file', they are not just disk file handles.
|
||||
If you want FMOD to use your own filesystem (and potentially lose the above benefits) use System::setFileSystem.
|
||||
*/
|
||||
|
||||
FMOD_RESULT F_CALL rawopen(FMOD_CODEC_STATE *codec, FMOD_MODE /*usermode*/, FMOD_CREATESOUNDEXINFO * /*userexinfo*/)
|
||||
{
|
||||
rawwaveformat.channels = 2;
|
||||
rawwaveformat.format = FMOD_SOUND_FORMAT_PCM16;
|
||||
rawwaveformat.frequency = 44100;
|
||||
rawwaveformat.pcmblocksize = 0;
|
||||
unsigned int size;
|
||||
FMOD_CODEC_FILE_SIZE(codec, &size);
|
||||
rawwaveformat.lengthpcm = size / (rawwaveformat.channels * sizeof(short)); /* bytes converted to PCM samples */;
|
||||
|
||||
codec->numsubsounds = 0; /* number of 'subsounds' in this sound. For most codecs this is 0, only multi sound codecs such as FSB or CDDA have subsounds. */
|
||||
codec->waveformat = &rawwaveformat;
|
||||
codec->plugindata = 0; /* user data value */
|
||||
|
||||
/* If your file format needs to read data to determine the format and load metadata, do so here with codec->fileread/fileseek function pointers. This will handle reading from disk/memory or internet. */
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL rawclose(FMOD_CODEC_STATE * /*codec*/)
|
||||
{
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL rawread(FMOD_CODEC_STATE *codec, void *buffer, unsigned int size, unsigned int *read)
|
||||
{
|
||||
return FMOD_CODEC_FILE_READ(codec, buffer, size, read);
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL rawsetposition(FMOD_CODEC_STATE *codec, int /*subsound*/, unsigned int position, FMOD_TIMEUNIT /*postype*/)
|
||||
{
|
||||
return FMOD_CODEC_FILE_SEEK(codec, position, 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,466 @@
|
|||
/*==============================================================================
|
||||
Distance Filter DSP Plugin Example
|
||||
Copyright (c), Firelight Technologies Pty, Ltd 2004-2025.
|
||||
|
||||
This example shows how to create a distance filter DSP effect.
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef WIN32
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fmod.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
F_EXPORT FMOD_DSP_DESCRIPTION* F_CALL FMODGetDSPDescription();
|
||||
}
|
||||
|
||||
const float FMOD_DISTANCE_FILTER_PARAM_MAX_DISTANCE_MIN = 0.0f;
|
||||
const float FMOD_DISTANCE_FILTER_PARAM_MAX_DISTANCE_MAX = 10000.0f;
|
||||
const float FMOD_DISTANCE_FILTER_PARAM_MAX_DISTANCE_DEFAULT = 20.0f;
|
||||
const float FMOD_DISTANCE_FILTER_PARAM_BANDPASS_FREQUENCY_MIN = 10.0f;
|
||||
const float FMOD_DISTANCE_FILTER_PARAM_BANDPASS_FREQUENCY_MAX = 22000.0f;
|
||||
const float FMOD_DISTANCE_FILTER_PARAM_BANDPASS_FREQUENCY_DEFAULT = 1500.0f;
|
||||
|
||||
enum
|
||||
{
|
||||
FMOD_DISTANCE_FILTER_MAX_DISTANCE,
|
||||
FMOD_DISTANCE_FILTER_BANDPASS_FREQUENCY,
|
||||
FMOD_DISTANCE_FILTER_3D_ATTRIBUTES,
|
||||
FMOD_DISTANCE_FILTER_NUM_PARAMETERS
|
||||
};
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspcreate (FMOD_DSP_STATE *dsp_state);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dsprelease (FMOD_DSP_STATE *dsp_state);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspreset (FMOD_DSP_STATE *dsp_state);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspread (FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspprocess (FMOD_DSP_STATE *dsp_state, unsigned int length, const FMOD_DSP_BUFFER_ARRAY *inbufferarray, FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL inputsidle, FMOD_DSP_PROCESS_OPERATION op);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspsetparamfloat(FMOD_DSP_STATE *dsp_state, int index, float value);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspsetparamint (FMOD_DSP_STATE *dsp_state, int index, int value);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspsetparambool (FMOD_DSP_STATE *dsp_state, int index, FMOD_BOOL value);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspsetparamdata (FMOD_DSP_STATE *dsp_state, int index, void *data, unsigned int length);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspgetparamfloat(FMOD_DSP_STATE *dsp_state, int index, float *value, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspgetparamint (FMOD_DSP_STATE *dsp_state, int index, int *value, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspgetparambool (FMOD_DSP_STATE *dsp_state, int index, FMOD_BOOL *value, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspgetparamdata (FMOD_DSP_STATE *dsp_state, int index, void **value, unsigned int *length, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_shouldiprocess (FMOD_DSP_STATE *dsp_state, FMOD_BOOL inputsidle, unsigned int length, FMOD_CHANNELMASK inmask, int inchannels, FMOD_SPEAKERMODE speakermode);
|
||||
|
||||
static FMOD_DSP_PARAMETER_DESC p_max_distance;
|
||||
static FMOD_DSP_PARAMETER_DESC p_bandpass_frequency;
|
||||
static FMOD_DSP_PARAMETER_DESC p_3d_attributes;
|
||||
|
||||
FMOD_DSP_PARAMETER_DESC *FMOD_DistanceFilter_dspparam[FMOD_DISTANCE_FILTER_NUM_PARAMETERS] =
|
||||
{
|
||||
&p_max_distance,
|
||||
&p_bandpass_frequency,
|
||||
&p_3d_attributes
|
||||
};
|
||||
|
||||
FMOD_DSP_DESCRIPTION FMOD_DistanceFilter_Desc =
|
||||
{
|
||||
FMOD_PLUGIN_SDK_VERSION,
|
||||
"FMOD Distance Filter", // name
|
||||
0x00010000, // plugin version
|
||||
1, // number of input buffers to process
|
||||
1, // number of output buffers to process
|
||||
FMOD_DistanceFilter_dspcreate,
|
||||
FMOD_DistanceFilter_dsprelease,
|
||||
FMOD_DistanceFilter_dspreset,
|
||||
FMOD_DistanceFilter_dspread,
|
||||
0, // FMOD_DistanceFilter_dspprocess, // *** declare this callback instead of FMOD_DistanceFilter_dspread if the plugin sets the output channel count ***
|
||||
0,
|
||||
FMOD_DISTANCE_FILTER_NUM_PARAMETERS,
|
||||
FMOD_DistanceFilter_dspparam,
|
||||
FMOD_DistanceFilter_dspsetparamfloat,
|
||||
0, // FMOD_DistanceFilter_dspsetparamint,
|
||||
0, // FMOD_DistanceFilter_dspsetparambool,
|
||||
FMOD_DistanceFilter_dspsetparamdata,
|
||||
FMOD_DistanceFilter_dspgetparamfloat,
|
||||
0, // FMOD_DistanceFilter_dspgetparamint,
|
||||
0, // FMOD_DistanceFilter_dspgetparambool,
|
||||
FMOD_DistanceFilter_dspgetparamdata,
|
||||
FMOD_DistanceFilter_shouldiprocess,
|
||||
0, // userdata
|
||||
0, // sys_register
|
||||
0, // sys_deregister
|
||||
0 // sys_mix
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
F_EXPORT FMOD_DSP_DESCRIPTION* F_CALL FMODGetDSPDescription()
|
||||
{
|
||||
static float distance_mapping_values[] = { 0, 1, 5, 20, 100, 500, 10000 };
|
||||
static float distance_mapping_scale[] = { 0, 1, 2, 3, 4, 4.5, 5 };
|
||||
|
||||
FMOD_DSP_INIT_PARAMDESC_FLOAT_WITH_MAPPING(p_max_distance, "Max Dist", "", "Distance at which bandpass stops narrowing. 0 to 1000000000. Default = 100", FMOD_DISTANCE_FILTER_PARAM_MAX_DISTANCE_DEFAULT, distance_mapping_values, distance_mapping_scale);
|
||||
FMOD_DSP_INIT_PARAMDESC_FLOAT(p_bandpass_frequency, "Frequency", "Hz", "Bandpass target frequency. 100 to 10,000Hz. Default = 2000Hz", FMOD_DISTANCE_FILTER_PARAM_BANDPASS_FREQUENCY_MIN, FMOD_DISTANCE_FILTER_PARAM_BANDPASS_FREQUENCY_MAX, FMOD_DISTANCE_FILTER_PARAM_BANDPASS_FREQUENCY_DEFAULT);
|
||||
FMOD_DSP_INIT_PARAMDESC_DATA(p_3d_attributes, "3D Attributes", "", "", FMOD_DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES);
|
||||
|
||||
return &FMOD_DistanceFilter_Desc;
|
||||
}
|
||||
}
|
||||
|
||||
class FMODDistanceFilterState
|
||||
{
|
||||
public:
|
||||
FMODDistanceFilterState() { }
|
||||
|
||||
void init (FMOD_DSP_STATE *dsp_state);
|
||||
void release (FMOD_DSP_STATE *dsp_state);
|
||||
FMOD_RESULT process (float *inbuffer, float *outbuffer, unsigned int length, int channels);
|
||||
FMOD_RESULT process (unsigned int length, const FMOD_DSP_BUFFER_ARRAY *inbufferarray, FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL inputsidle, FMOD_DSP_PROCESS_OPERATION op);
|
||||
void reset ();
|
||||
void setMaxDistance (float);
|
||||
void setBandpassFrequency(float);
|
||||
void setDistance (float);
|
||||
float maxDistance () const { return m_max_distance; }
|
||||
float bandpassFrequency () const { return m_bandpass_frequency; }
|
||||
|
||||
private:
|
||||
void updateTimeConstants ();
|
||||
|
||||
float m_max_distance;
|
||||
float m_bandpass_frequency;
|
||||
float m_distance;
|
||||
float m_target_highpass_time_const;
|
||||
float m_current_highpass_time_const;
|
||||
float m_target_lowpass_time_const;
|
||||
float m_current_lowpass_time_const;
|
||||
int m_ramp_samples_left;
|
||||
float *m_previous_lp1_out;
|
||||
float *m_previous_lp2_out;
|
||||
float *m_previous_hp_out;
|
||||
int m_sample_rate;
|
||||
int m_max_channels;
|
||||
};
|
||||
|
||||
void FMODDistanceFilterState::init(FMOD_DSP_STATE *dsp_state)
|
||||
{
|
||||
FMOD_DSP_GETSAMPLERATE(dsp_state, &m_sample_rate);
|
||||
|
||||
m_max_channels = 8;
|
||||
m_max_distance = FMOD_DISTANCE_FILTER_PARAM_MAX_DISTANCE_DEFAULT;
|
||||
m_bandpass_frequency = FMOD_DISTANCE_FILTER_PARAM_BANDPASS_FREQUENCY_DEFAULT;
|
||||
m_distance = 0;
|
||||
|
||||
m_previous_lp1_out = (float*)FMOD_DSP_ALLOC(dsp_state, m_max_channels * sizeof(float));
|
||||
m_previous_lp2_out = (float*)FMOD_DSP_ALLOC(dsp_state, m_max_channels * sizeof(float));
|
||||
m_previous_hp_out = (float*)FMOD_DSP_ALLOC(dsp_state, m_max_channels * sizeof(float));
|
||||
|
||||
updateTimeConstants();
|
||||
reset();
|
||||
}
|
||||
|
||||
void FMODDistanceFilterState::release(FMOD_DSP_STATE *dsp_state)
|
||||
{
|
||||
FMOD_DSP_FREE(dsp_state, m_previous_lp1_out);
|
||||
FMOD_DSP_FREE(dsp_state, m_previous_lp2_out);
|
||||
FMOD_DSP_FREE(dsp_state, m_previous_hp_out);
|
||||
}
|
||||
|
||||
FMOD_RESULT FMODDistanceFilterState::process(float *inbuffer, float *outbuffer, unsigned int length, int channels)
|
||||
{
|
||||
if(channels > m_max_channels)
|
||||
{
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// Note: buffers are interleaved
|
||||
static float jitter = (float)1E-20;
|
||||
float lp1_out, lp2_out;
|
||||
int ch;
|
||||
|
||||
float lp_tc = m_current_lowpass_time_const;
|
||||
float hp_tc = m_current_highpass_time_const;
|
||||
|
||||
if (m_ramp_samples_left)
|
||||
{
|
||||
float lp_delta = (m_target_lowpass_time_const - m_current_lowpass_time_const) / m_ramp_samples_left;
|
||||
float hp_delta = (m_target_highpass_time_const - m_current_highpass_time_const) / m_ramp_samples_left;
|
||||
while (length)
|
||||
{
|
||||
if (--m_ramp_samples_left)
|
||||
{
|
||||
lp_tc += lp_delta;
|
||||
hp_tc += hp_delta;
|
||||
for (ch = 0; ch < channels; ++ch)
|
||||
{
|
||||
lp1_out = m_previous_lp1_out[ch] + lp_tc * (*inbuffer++ + jitter - m_previous_lp1_out[ch]);
|
||||
lp2_out = m_previous_lp2_out[ch] + lp_tc * (lp1_out - m_previous_lp2_out[ch]);
|
||||
*outbuffer = hp_tc * (m_previous_hp_out[ch] + lp2_out - m_previous_lp2_out[ch]);
|
||||
|
||||
m_previous_lp1_out[ch] = lp1_out;
|
||||
m_previous_lp2_out[ch] = lp2_out;
|
||||
m_previous_hp_out[ch] = *outbuffer++;
|
||||
}
|
||||
jitter = -jitter;
|
||||
}
|
||||
else
|
||||
{
|
||||
lp_tc = m_target_lowpass_time_const;
|
||||
hp_tc = m_target_highpass_time_const;
|
||||
break;
|
||||
}
|
||||
--length;
|
||||
}
|
||||
}
|
||||
|
||||
while (length--)
|
||||
{
|
||||
for (ch = 0; ch < channels; ++ch)
|
||||
{
|
||||
lp1_out = m_previous_lp1_out[ch] + lp_tc * (*inbuffer++ + jitter - m_previous_lp1_out[ch]);
|
||||
lp2_out = m_previous_lp2_out[ch] + lp_tc * (lp1_out - m_previous_lp2_out[ch]);
|
||||
*outbuffer = hp_tc * (m_previous_hp_out[ch] + lp2_out - m_previous_lp2_out[ch]);
|
||||
|
||||
m_previous_lp1_out[ch] = lp1_out;
|
||||
m_previous_lp2_out[ch] = lp2_out;
|
||||
m_previous_hp_out[ch] = *outbuffer++;
|
||||
}
|
||||
jitter = -jitter;
|
||||
}
|
||||
|
||||
m_current_lowpass_time_const = lp_tc;
|
||||
m_current_highpass_time_const = hp_tc;
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT FMODDistanceFilterState::process(unsigned int length, const FMOD_DSP_BUFFER_ARRAY *inbufferarray, FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL inputsidle, FMOD_DSP_PROCESS_OPERATION op)
|
||||
{
|
||||
if (op == FMOD_DSP_PROCESS_QUERY)
|
||||
{
|
||||
FMOD_SPEAKERMODE outmode;
|
||||
int outchannels;
|
||||
|
||||
#if 1 // For stereo output
|
||||
{
|
||||
outmode = FMOD_SPEAKERMODE_STEREO;
|
||||
outchannels = 2;
|
||||
}
|
||||
#else // For 5.1 output
|
||||
{
|
||||
outmode = FMOD_SPEAKERMODE_5POINT1;
|
||||
outchannels = 6;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (outbufferarray)
|
||||
{
|
||||
outbufferarray->speakermode = outmode;
|
||||
outbufferarray->buffernumchannels[0] = outchannels;
|
||||
}
|
||||
|
||||
if (inputsidle)
|
||||
{
|
||||
return FMOD_ERR_DSP_DONTPROCESS;
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
// Do processing here
|
||||
float *inbuffer = inbufferarray->buffers[0];
|
||||
float *outbuffer = outbufferarray->buffers[0];
|
||||
int inchannels = inbufferarray->buffernumchannels[0];
|
||||
int outchannels = outbufferarray->buffernumchannels[0];
|
||||
|
||||
while(length--)
|
||||
{
|
||||
// MAIN DSP LOOP...
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
void FMODDistanceFilterState::reset()
|
||||
{
|
||||
m_current_lowpass_time_const = m_target_lowpass_time_const;
|
||||
m_current_highpass_time_const = m_target_highpass_time_const;
|
||||
m_ramp_samples_left = 0;
|
||||
|
||||
memset(m_previous_lp1_out, 0, m_max_channels * sizeof(float));
|
||||
memset(m_previous_lp2_out, 0, m_max_channels * sizeof(float));
|
||||
memset(m_previous_hp_out, 0, m_max_channels * sizeof(float));
|
||||
}
|
||||
|
||||
void FMODDistanceFilterState::setMaxDistance(float distance)
|
||||
{
|
||||
m_max_distance = distance;
|
||||
updateTimeConstants();
|
||||
}
|
||||
|
||||
void FMODDistanceFilterState::setBandpassFrequency(float frequency)
|
||||
{
|
||||
m_bandpass_frequency = frequency;
|
||||
updateTimeConstants();
|
||||
}
|
||||
|
||||
void FMODDistanceFilterState::setDistance(float distance)
|
||||
{
|
||||
m_distance = distance;
|
||||
updateTimeConstants();
|
||||
}
|
||||
|
||||
void FMODDistanceFilterState::updateTimeConstants()
|
||||
{
|
||||
#define PI (3.14159265358979323846f)
|
||||
#define MIN_CUTOFF (10.0f)
|
||||
#define MAX_CUTOFF (22000.0f)
|
||||
|
||||
float dist_factor = m_distance >= m_max_distance ? 1.0f : m_distance / m_max_distance;
|
||||
float lp_cutoff = m_bandpass_frequency + (1.0f - dist_factor) * (1.0f - dist_factor) * (MAX_CUTOFF - m_bandpass_frequency);
|
||||
float hp_cutoff = MIN_CUTOFF + dist_factor * dist_factor * (m_bandpass_frequency - MIN_CUTOFF);
|
||||
|
||||
float dt = 1.0f / m_sample_rate;
|
||||
float threshold = m_sample_rate / PI;
|
||||
|
||||
if (lp_cutoff >= MAX_CUTOFF)
|
||||
{
|
||||
m_target_lowpass_time_const = 1.0f;
|
||||
}
|
||||
else if (lp_cutoff <= threshold)
|
||||
{
|
||||
float RC = 1.0f / (2.0f * PI * lp_cutoff);
|
||||
m_target_lowpass_time_const = dt / (RC + dt);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_target_lowpass_time_const = 0.666666667f + (lp_cutoff - threshold) / (3.0f * (MAX_CUTOFF - threshold));
|
||||
}
|
||||
|
||||
if (hp_cutoff >= MAX_CUTOFF)
|
||||
{
|
||||
m_target_highpass_time_const = 0.0f;
|
||||
}
|
||||
else if (hp_cutoff <= threshold)
|
||||
{
|
||||
float RC = 1.0f / (2.0f * PI * hp_cutoff);
|
||||
m_target_highpass_time_const = RC / (RC + dt);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_target_highpass_time_const = (MAX_CUTOFF - hp_cutoff) / (3.0f * (MAX_CUTOFF - threshold));
|
||||
}
|
||||
|
||||
m_ramp_samples_left = 256;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspcreate(FMOD_DSP_STATE *dsp_state)
|
||||
{
|
||||
FMODDistanceFilterState* state = (FMODDistanceFilterState *)FMOD_DSP_ALLOC(dsp_state, sizeof(FMODDistanceFilterState));
|
||||
state->init(dsp_state);
|
||||
dsp_state->plugindata = state;
|
||||
if (!state)
|
||||
{
|
||||
return FMOD_ERR_MEMORY;
|
||||
}
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dsprelease(FMOD_DSP_STATE *dsp_state)
|
||||
{
|
||||
FMODDistanceFilterState *state = (FMODDistanceFilterState *)dsp_state->plugindata;
|
||||
state->release(dsp_state);
|
||||
FMOD_DSP_FREE(dsp_state, state);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspread(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int * /*outchannels*/)
|
||||
{
|
||||
FMODDistanceFilterState *state = (FMODDistanceFilterState *)dsp_state->plugindata;
|
||||
return state->process(inbuffer, outbuffer, length, inchannels); // input and output channels count match for this effect
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspprocess(FMOD_DSP_STATE *dsp_state, unsigned int length, const FMOD_DSP_BUFFER_ARRAY *inbufferarray, FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL inputsidle, FMOD_DSP_PROCESS_OPERATION op)
|
||||
{
|
||||
FMODDistanceFilterState *state = (FMODDistanceFilterState *)dsp_state->plugindata;
|
||||
return state->process(length, inbufferarray, outbufferarray, inputsidle, op); // as an example for plugins which set the output channel count
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspreset(FMOD_DSP_STATE *dsp_state)
|
||||
{
|
||||
FMODDistanceFilterState *state = (FMODDistanceFilterState *)dsp_state->plugindata;
|
||||
state->reset();
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspsetparamfloat(FMOD_DSP_STATE *dsp_state, int index, float value)
|
||||
{
|
||||
FMODDistanceFilterState *state = (FMODDistanceFilterState *)dsp_state->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_DISTANCE_FILTER_MAX_DISTANCE:
|
||||
state->setMaxDistance(value);
|
||||
return FMOD_OK;
|
||||
|
||||
case FMOD_DISTANCE_FILTER_BANDPASS_FREQUENCY:
|
||||
state->setBandpassFrequency(value);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspgetparamfloat(FMOD_DSP_STATE *dsp_state, int index, float *value, char *valuestr)
|
||||
{
|
||||
FMODDistanceFilterState *state = (FMODDistanceFilterState *)dsp_state->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_DISTANCE_FILTER_MAX_DISTANCE:
|
||||
*value = state->maxDistance();
|
||||
if (valuestr) snprintf(valuestr, FMOD_DSP_GETPARAM_VALUESTR_LENGTH, "%.1f", state->maxDistance());
|
||||
return FMOD_OK;
|
||||
|
||||
case FMOD_DISTANCE_FILTER_BANDPASS_FREQUENCY:
|
||||
*value = state->bandpassFrequency();
|
||||
if (valuestr) snprintf(valuestr, FMOD_DSP_GETPARAM_VALUESTR_LENGTH, "%.1f Hz", state->bandpassFrequency());
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspsetparamdata(FMOD_DSP_STATE *dsp_state, int index, void *data, unsigned int /*length*/)
|
||||
{
|
||||
FMODDistanceFilterState *state = (FMODDistanceFilterState *)dsp_state->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_DISTANCE_FILTER_3D_ATTRIBUTES:
|
||||
FMOD_DSP_PARAMETER_3DATTRIBUTES* param = (FMOD_DSP_PARAMETER_3DATTRIBUTES*)data;
|
||||
state->setDistance(sqrtf(param->relative.position.x * param->relative.position.x + param->relative.position.y * param->relative.position.y + param->relative.position.z * param->relative.position.z));
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_dspgetparamdata(FMOD_DSP_STATE * /*dsp_state*/, int index, void ** /*value*/, unsigned int * /*length*/, char * /*valuestr*/)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_DISTANCE_FILTER_3D_ATTRIBUTES:
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_DistanceFilter_shouldiprocess(FMOD_DSP_STATE * /*dsp_state*/, FMOD_BOOL inputsidle, unsigned int /*length*/, FMOD_CHANNELMASK /*inmask*/, int /*inchannels*/, FMOD_SPEAKERMODE /*speakermode*/)
|
||||
{
|
||||
if (inputsidle)
|
||||
{
|
||||
return FMOD_ERR_DSP_DONTPROCESS;
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
|
@ -0,0 +1,360 @@
|
|||
/*==============================================================================
|
||||
Gain DSP Plugin Example
|
||||
Copyright (c), Firelight Technologies Pty, Ltd 2004-2025.
|
||||
|
||||
This example shows how to create a simple gain DSP effect.
|
||||
==============================================================================*/
|
||||
|
||||
#ifdef WIN32
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fmod.hpp"
|
||||
|
||||
#define FMOD_GAIN_USEPROCESSCALLBACK /* FMOD plugins have 2 methods of processing data.
|
||||
1. via a 'read' callback which is compatible with FMOD Ex but limited in functionality, or
|
||||
2. via a 'process' callback which exposes more functionality, like masks and query before process early out logic. */
|
||||
|
||||
extern "C" {
|
||||
F_EXPORT FMOD_DSP_DESCRIPTION* F_CALL FMODGetDSPDescription();
|
||||
}
|
||||
|
||||
const float FMOD_GAIN_PARAM_GAIN_MIN = -80.0f;
|
||||
const float FMOD_GAIN_PARAM_GAIN_MAX = 10.0f;
|
||||
const float FMOD_GAIN_PARAM_GAIN_DEFAULT = 0.0f;
|
||||
#define FMOD_GAIN_RAMPCOUNT 256
|
||||
|
||||
enum
|
||||
{
|
||||
FMOD_GAIN_PARAM_GAIN = 0,
|
||||
FMOD_GAIN_PARAM_INVERT,
|
||||
FMOD_GAIN_NUM_PARAMETERS
|
||||
};
|
||||
|
||||
#define DECIBELS_TO_LINEAR(__dbval__) ((__dbval__ <= FMOD_GAIN_PARAM_GAIN_MIN) ? 0.0f : powf(10.0f, __dbval__ / 20.0f))
|
||||
#define LINEAR_TO_DECIBELS(__linval__) ((__linval__ <= 0.0f) ? FMOD_GAIN_PARAM_GAIN_MIN : 20.0f * log10f((float)__linval__))
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspcreate (FMOD_DSP_STATE *dsp_state);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dsprelease (FMOD_DSP_STATE *dsp_state);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspreset (FMOD_DSP_STATE *dsp_state);
|
||||
#ifdef FMOD_GAIN_USEPROCESSCALLBACK
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspprocess (FMOD_DSP_STATE *dsp_state, unsigned int length, const FMOD_DSP_BUFFER_ARRAY *inbufferarray, FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL inputsidle, FMOD_DSP_PROCESS_OPERATION op);
|
||||
#else
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspread (FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels);
|
||||
#endif
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspsetparamfloat(FMOD_DSP_STATE *dsp_state, int index, float value);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspsetparamint (FMOD_DSP_STATE *dsp_state, int index, int value);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspsetparambool (FMOD_DSP_STATE *dsp_state, int index, FMOD_BOOL value);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspsetparamdata (FMOD_DSP_STATE *dsp_state, int index, void *data, unsigned int length);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspgetparamfloat(FMOD_DSP_STATE *dsp_state, int index, float *value, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspgetparamint (FMOD_DSP_STATE *dsp_state, int index, int *value, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspgetparambool (FMOD_DSP_STATE *dsp_state, int index, FMOD_BOOL *value, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspgetparamdata (FMOD_DSP_STATE *dsp_state, int index, void **value, unsigned int *length, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_shouldiprocess (FMOD_DSP_STATE *dsp_state, FMOD_BOOL inputsidle, unsigned int length, FMOD_CHANNELMASK inmask, int inchannels, FMOD_SPEAKERMODE speakermode);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_sys_register (FMOD_DSP_STATE *dsp_state);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_sys_deregister (FMOD_DSP_STATE *dsp_state);
|
||||
FMOD_RESULT F_CALL FMOD_Gain_sys_mix (FMOD_DSP_STATE *dsp_state, int stage);
|
||||
|
||||
static bool FMOD_Gain_Running = false;
|
||||
static FMOD_DSP_PARAMETER_DESC p_gain;
|
||||
static FMOD_DSP_PARAMETER_DESC p_invert;
|
||||
|
||||
FMOD_DSP_PARAMETER_DESC *FMOD_Gain_dspparam[FMOD_GAIN_NUM_PARAMETERS] =
|
||||
{
|
||||
&p_gain,
|
||||
&p_invert
|
||||
};
|
||||
|
||||
FMOD_DSP_DESCRIPTION FMOD_Gain_Desc =
|
||||
{
|
||||
FMOD_PLUGIN_SDK_VERSION,
|
||||
"FMOD Gain", // name
|
||||
0x00010000, // plug-in version
|
||||
1, // number of input buffers to process
|
||||
1, // number of output buffers to process
|
||||
FMOD_Gain_dspcreate,
|
||||
FMOD_Gain_dsprelease,
|
||||
FMOD_Gain_dspreset,
|
||||
#ifndef FMOD_GAIN_USEPROCESSCALLBACK
|
||||
FMOD_Gain_dspread,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
#ifdef FMOD_GAIN_USEPROCESSCALLBACK
|
||||
FMOD_Gain_dspprocess,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
0,
|
||||
FMOD_GAIN_NUM_PARAMETERS,
|
||||
FMOD_Gain_dspparam,
|
||||
FMOD_Gain_dspsetparamfloat,
|
||||
0, // FMOD_Gain_dspsetparamint,
|
||||
FMOD_Gain_dspsetparambool,
|
||||
0, // FMOD_Gain_dspsetparamdata,
|
||||
FMOD_Gain_dspgetparamfloat,
|
||||
0, // FMOD_Gain_dspgetparamint,
|
||||
FMOD_Gain_dspgetparambool,
|
||||
0, // FMOD_Gain_dspgetparamdata,
|
||||
FMOD_Gain_shouldiprocess,
|
||||
0, // userdata
|
||||
FMOD_Gain_sys_register,
|
||||
FMOD_Gain_sys_deregister,
|
||||
FMOD_Gain_sys_mix
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
F_EXPORT FMOD_DSP_DESCRIPTION* F_CALL FMODGetDSPDescription()
|
||||
{
|
||||
static float gain_mapping_values[] = { -80, -50, -30, -10, 10 };
|
||||
static float gain_mapping_scale[] = { 0, 2, 4, 7, 11 };
|
||||
|
||||
FMOD_DSP_INIT_PARAMDESC_FLOAT_WITH_MAPPING(p_gain, "Gain", "dB", "Gain in dB. -80 to 10. Default = 0", FMOD_GAIN_PARAM_GAIN_DEFAULT, gain_mapping_values, gain_mapping_scale);
|
||||
FMOD_DSP_INIT_PARAMDESC_BOOL(p_invert, "Invert", "", "Invert signal. Default = off", false, 0);
|
||||
return &FMOD_Gain_Desc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FMODGainState
|
||||
{
|
||||
public:
|
||||
FMODGainState();
|
||||
|
||||
void read(float *inbuffer, float *outbuffer, unsigned int length, int channels);
|
||||
void reset();
|
||||
void setGain(float);
|
||||
void setInvert(bool);
|
||||
float gain() const { return LINEAR_TO_DECIBELS(m_invert ? -m_target_gain : m_target_gain); }
|
||||
FMOD_BOOL invert() const { return m_invert; }
|
||||
|
||||
private:
|
||||
float m_target_gain;
|
||||
float m_current_gain;
|
||||
int m_ramp_samples_left;
|
||||
bool m_invert;
|
||||
};
|
||||
|
||||
FMODGainState::FMODGainState()
|
||||
{
|
||||
m_target_gain = DECIBELS_TO_LINEAR(FMOD_GAIN_PARAM_GAIN_DEFAULT);
|
||||
m_invert = 0;
|
||||
reset();
|
||||
}
|
||||
|
||||
void FMODGainState::read(float *inbuffer, float *outbuffer, unsigned int length, int channels)
|
||||
{
|
||||
// Note: buffers are interleaved
|
||||
float gain = m_current_gain;
|
||||
|
||||
if (m_ramp_samples_left)
|
||||
{
|
||||
float target = m_target_gain;
|
||||
float delta = (target - gain) / m_ramp_samples_left;
|
||||
while (length)
|
||||
{
|
||||
if (--m_ramp_samples_left)
|
||||
{
|
||||
gain += delta;
|
||||
for (int i = 0; i < channels; ++i)
|
||||
{
|
||||
*outbuffer++ = *inbuffer++ * gain;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gain = target;
|
||||
break;
|
||||
}
|
||||
--length;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int samples = length * channels;
|
||||
while (samples--)
|
||||
{
|
||||
*outbuffer++ = *inbuffer++ * gain;
|
||||
}
|
||||
|
||||
m_current_gain = gain;
|
||||
}
|
||||
|
||||
void FMODGainState::reset()
|
||||
{
|
||||
m_current_gain = m_target_gain;
|
||||
m_ramp_samples_left = 0;
|
||||
}
|
||||
|
||||
void FMODGainState::setGain(float gain)
|
||||
{
|
||||
m_target_gain = m_invert ? -DECIBELS_TO_LINEAR(gain) : DECIBELS_TO_LINEAR(gain);
|
||||
m_ramp_samples_left = FMOD_GAIN_RAMPCOUNT;
|
||||
}
|
||||
|
||||
void FMODGainState::setInvert(bool invert)
|
||||
{
|
||||
if (invert != m_invert)
|
||||
{
|
||||
m_target_gain = -m_target_gain;
|
||||
m_ramp_samples_left = FMOD_GAIN_RAMPCOUNT;
|
||||
}
|
||||
m_invert = invert;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspcreate(FMOD_DSP_STATE *dsp_state)
|
||||
{
|
||||
dsp_state->plugindata = (FMODGainState *)FMOD_DSP_ALLOC(dsp_state, sizeof(FMODGainState));
|
||||
if (!dsp_state->plugindata)
|
||||
{
|
||||
return FMOD_ERR_MEMORY;
|
||||
}
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dsprelease(FMOD_DSP_STATE *dsp_state)
|
||||
{
|
||||
FMODGainState *state = (FMODGainState *)dsp_state->plugindata;
|
||||
FMOD_DSP_FREE(dsp_state, state);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
#ifdef FMOD_GAIN_USEPROCESSCALLBACK
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspprocess(FMOD_DSP_STATE *dsp_state, unsigned int length, const FMOD_DSP_BUFFER_ARRAY *inbufferarray, FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL inputsidle, FMOD_DSP_PROCESS_OPERATION op)
|
||||
{
|
||||
FMODGainState *state = (FMODGainState *)dsp_state->plugindata;
|
||||
|
||||
if (op == FMOD_DSP_PROCESS_QUERY)
|
||||
{
|
||||
if (outbufferarray && inbufferarray)
|
||||
{
|
||||
outbufferarray[0].buffernumchannels[0] = inbufferarray[0].buffernumchannels[0];
|
||||
outbufferarray[0].speakermode = inbufferarray[0].speakermode;
|
||||
}
|
||||
|
||||
if (inputsidle)
|
||||
{
|
||||
return FMOD_ERR_DSP_DONTPROCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state->read(inbufferarray[0].buffers[0], outbufferarray[0].buffers[0], length, inbufferarray[0].buffernumchannels[0]); // input and output channels count match for this effect
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspread(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int * /*outchannels*/)
|
||||
{
|
||||
FMODGainState *state = (FMODGainState *)dsp_state->plugindata;
|
||||
state->read(inbuffer, outbuffer, length, inchannels); // input and output channels count match for this effect
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspreset(FMOD_DSP_STATE *dsp_state)
|
||||
{
|
||||
FMODGainState *state = (FMODGainState *)dsp_state->plugindata;
|
||||
state->reset();
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspsetparamfloat(FMOD_DSP_STATE *dsp_state, int index, float value)
|
||||
{
|
||||
FMODGainState *state = (FMODGainState *)dsp_state->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_GAIN_PARAM_GAIN:
|
||||
state->setGain(value);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspgetparamfloat(FMOD_DSP_STATE *dsp_state, int index, float *value, char *valuestr)
|
||||
{
|
||||
FMODGainState *state = (FMODGainState *)dsp_state->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_GAIN_PARAM_GAIN:
|
||||
*value = state->gain();
|
||||
if (valuestr) snprintf(valuestr, FMOD_DSP_GETPARAM_VALUESTR_LENGTH, "%.1f dB", state->gain());
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspsetparambool(FMOD_DSP_STATE *dsp_state, int index, FMOD_BOOL value)
|
||||
{
|
||||
FMODGainState *state = (FMODGainState *)dsp_state->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_GAIN_PARAM_INVERT:
|
||||
state->setInvert(value ? true : false);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_dspgetparambool(FMOD_DSP_STATE *dsp_state, int index, FMOD_BOOL *value, char *valuestr)
|
||||
{
|
||||
FMODGainState *state = (FMODGainState *)dsp_state->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_GAIN_PARAM_INVERT:
|
||||
*value = state->invert();
|
||||
if (valuestr) snprintf(valuestr, FMOD_DSP_GETPARAM_VALUESTR_LENGTH, state->invert() ? "Inverted" : "Off" );
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_shouldiprocess(FMOD_DSP_STATE * /*dsp_state*/, FMOD_BOOL inputsidle, unsigned int /*length*/, FMOD_CHANNELMASK /*inmask*/, int /*inchannels*/, FMOD_SPEAKERMODE /*speakermode*/)
|
||||
{
|
||||
if (inputsidle)
|
||||
{
|
||||
return FMOD_ERR_DSP_DONTPROCESS;
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_sys_register(FMOD_DSP_STATE * /*dsp_state*/)
|
||||
{
|
||||
FMOD_Gain_Running = true;
|
||||
// called once for this type of dsp being loaded or registered (it is not per instance)
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_sys_deregister(FMOD_DSP_STATE * /*dsp_state*/)
|
||||
{
|
||||
FMOD_Gain_Running = false;
|
||||
// called once for this type of dsp being unloaded or de-registered (it is not per instance)
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Gain_sys_mix(FMOD_DSP_STATE * /*dsp_state*/, int /*stage*/)
|
||||
{
|
||||
// stage == 0 , before all dsps are processed/mixed, this callback is called once for this type.
|
||||
// stage == 1 , after all dsps are processed/mixed, this callback is called once for this type.
|
||||
return FMOD_OK;
|
||||
}
|
|
@ -0,0 +1,302 @@
|
|||
/*==============================================================================
|
||||
Plugin Example
|
||||
Copyright (c), Firelight Technologies Pty, Ltd 2004-2025.
|
||||
|
||||
This example shows how to created a plugin effect.
|
||||
==============================================================================*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fmod.hpp"
|
||||
|
||||
extern "C" {
|
||||
F_EXPORT FMOD_DSP_DESCRIPTION* F_CALL FMODGetDSPDescription();
|
||||
}
|
||||
|
||||
const float FMOD_NOISE_PARAM_GAIN_MIN = -80.0f;
|
||||
const float FMOD_NOISE_PARAM_GAIN_MAX = 10.0f;
|
||||
const float FMOD_NOISE_PARAM_GAIN_DEFAULT = 0.0f;
|
||||
|
||||
#define FMOD_NOISE_RAMPCOUNT 256
|
||||
|
||||
enum
|
||||
{
|
||||
FMOD_NOISE_PARAM_LEVEL = 0,
|
||||
FMOD_NOISE_PARAM_FORMAT,
|
||||
FMOD_NOISE_NUM_PARAMETERS
|
||||
};
|
||||
|
||||
enum FMOD_NOISE_FORMAT
|
||||
{
|
||||
FMOD_NOISE_FORMAT_MONO = 0,
|
||||
FMOD_NOISE_FORMAT_STEREO,
|
||||
FMOD_NOISE_FORMAT_5POINT1
|
||||
};
|
||||
|
||||
#define DECIBELS_TO_LINEAR(__dbval__) ((__dbval__ <= FMOD_NOISE_PARAM_GAIN_MIN) ? 0.0f : powf(10.0f, __dbval__ / 20.0f))
|
||||
#define LINEAR_TO_DECIBELS(__linval__) ((__linval__ <= 0.0f) ? FMOD_NOISE_PARAM_GAIN_MIN : 20.0f * log10f((float)__linval__))
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspcreate (FMOD_DSP_STATE *dsp);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dsprelease (FMOD_DSP_STATE *dsp);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspreset (FMOD_DSP_STATE *dsp);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspprocess (FMOD_DSP_STATE *dsp, unsigned int length, const FMOD_DSP_BUFFER_ARRAY *inbufferarray, FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL inputsidle, FMOD_DSP_PROCESS_OPERATION op);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspsetparamfloat(FMOD_DSP_STATE *dsp, int index, float value);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspsetparamint (FMOD_DSP_STATE *dsp, int index, int value);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspsetparambool (FMOD_DSP_STATE *dsp, int index, bool value);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspsetparamdata (FMOD_DSP_STATE *dsp, int index, void *data, unsigned int length);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspgetparamfloat(FMOD_DSP_STATE *dsp, int index, float *value, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspgetparamint (FMOD_DSP_STATE *dsp, int index, int *value, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspgetparambool (FMOD_DSP_STATE *dsp, int index, bool *value, char *valuestr);
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspgetparamdata (FMOD_DSP_STATE *dsp, int index, void **value, unsigned int *length, char *valuestr);
|
||||
|
||||
static FMOD_DSP_PARAMETER_DESC p_level;
|
||||
static FMOD_DSP_PARAMETER_DESC p_format;
|
||||
|
||||
FMOD_DSP_PARAMETER_DESC *FMOD_Noise_dspparam[FMOD_NOISE_NUM_PARAMETERS] =
|
||||
{
|
||||
&p_level,
|
||||
&p_format
|
||||
};
|
||||
|
||||
const char* FMOD_Noise_Format_Names[3] = {"Mono", "Stereo", "5.1"};
|
||||
|
||||
FMOD_DSP_DESCRIPTION FMOD_Noise_Desc =
|
||||
{
|
||||
FMOD_PLUGIN_SDK_VERSION,
|
||||
"FMOD Noise", // name
|
||||
0x00010000, // plug-in version
|
||||
0, // number of input buffers to process
|
||||
1, // number of output buffers to process
|
||||
FMOD_Noise_dspcreate,
|
||||
FMOD_Noise_dsprelease,
|
||||
FMOD_Noise_dspreset,
|
||||
0,
|
||||
FMOD_Noise_dspprocess,
|
||||
0,
|
||||
FMOD_NOISE_NUM_PARAMETERS,
|
||||
FMOD_Noise_dspparam,
|
||||
FMOD_Noise_dspsetparamfloat,
|
||||
FMOD_Noise_dspsetparamint,
|
||||
0,
|
||||
0,
|
||||
FMOD_Noise_dspgetparamfloat,
|
||||
FMOD_Noise_dspgetparamint,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // userdata
|
||||
0, // Register
|
||||
0, // Deregister
|
||||
0 // Mix
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
F_EXPORT FMOD_DSP_DESCRIPTION* F_CALL FMODGetDSPDescription()
|
||||
{
|
||||
FMOD_DSP_INIT_PARAMDESC_FLOAT(p_level, "Level", "dB", "Gain in dB. -80 to 10. Default = 0", FMOD_NOISE_PARAM_GAIN_MIN, FMOD_NOISE_PARAM_GAIN_MAX, FMOD_NOISE_PARAM_GAIN_DEFAULT);
|
||||
FMOD_DSP_INIT_PARAMDESC_INT(p_format, "Format", "", "Mono, stereo or 5.1. Default = 0 (mono)", FMOD_NOISE_FORMAT_MONO, FMOD_NOISE_FORMAT_5POINT1, FMOD_NOISE_FORMAT_MONO, false, FMOD_Noise_Format_Names);
|
||||
return &FMOD_Noise_Desc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FMODNoiseState
|
||||
{
|
||||
public:
|
||||
FMODNoiseState();
|
||||
|
||||
void generate(float *outbuffer, unsigned int length, int channels);
|
||||
void reset();
|
||||
void setLevel(float);
|
||||
void setFormat(FMOD_NOISE_FORMAT format) { m_format = format; }
|
||||
float level() const { return LINEAR_TO_DECIBELS(m_target_level); }
|
||||
FMOD_NOISE_FORMAT format() const { return m_format; }
|
||||
|
||||
private:
|
||||
float m_target_level;
|
||||
float m_current_level;
|
||||
int m_ramp_samples_left;
|
||||
FMOD_NOISE_FORMAT m_format;
|
||||
};
|
||||
|
||||
FMODNoiseState::FMODNoiseState()
|
||||
{
|
||||
m_target_level = DECIBELS_TO_LINEAR(FMOD_NOISE_PARAM_GAIN_DEFAULT);
|
||||
m_format = FMOD_NOISE_FORMAT_MONO;
|
||||
reset();
|
||||
}
|
||||
|
||||
void FMODNoiseState::generate(float *outbuffer, unsigned int length, int channels)
|
||||
{
|
||||
// Note: buffers are interleaved
|
||||
float gain = m_current_level;
|
||||
|
||||
if (m_ramp_samples_left)
|
||||
{
|
||||
float target = m_target_level;
|
||||
float delta = (target - gain) / m_ramp_samples_left;
|
||||
while (length)
|
||||
{
|
||||
if (--m_ramp_samples_left)
|
||||
{
|
||||
gain += delta;
|
||||
for (int i = 0; i < channels; ++i)
|
||||
{
|
||||
*outbuffer++ = (((float)(rand()%32768) / 16384.0f) - 1.0f) * gain;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gain = target;
|
||||
break;
|
||||
}
|
||||
--length;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int samples = length * channels;
|
||||
while (samples--)
|
||||
{
|
||||
*outbuffer++ = (((float)(rand()%32768) / 16384.0f) - 1.0f) * gain;
|
||||
}
|
||||
|
||||
m_current_level = gain;
|
||||
}
|
||||
|
||||
void FMODNoiseState::reset()
|
||||
{
|
||||
m_current_level = m_target_level;
|
||||
m_ramp_samples_left = 0;
|
||||
}
|
||||
|
||||
void FMODNoiseState::setLevel(float level)
|
||||
{
|
||||
m_target_level = DECIBELS_TO_LINEAR(level);
|
||||
m_ramp_samples_left = FMOD_NOISE_RAMPCOUNT;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspcreate(FMOD_DSP_STATE *dsp)
|
||||
{
|
||||
dsp->plugindata = (FMODNoiseState *)FMOD_DSP_ALLOC(dsp, sizeof(FMODNoiseState));
|
||||
if (!dsp->plugindata)
|
||||
{
|
||||
return FMOD_ERR_MEMORY;
|
||||
}
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dsprelease(FMOD_DSP_STATE *dsp)
|
||||
{
|
||||
FMODNoiseState *state = (FMODNoiseState *)dsp->plugindata;
|
||||
FMOD_DSP_FREE(dsp, state);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspprocess(FMOD_DSP_STATE *dsp, unsigned int length, const FMOD_DSP_BUFFER_ARRAY * /*inbufferarray*/, FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL /*inputsidle*/, FMOD_DSP_PROCESS_OPERATION op)
|
||||
{
|
||||
FMODNoiseState *state = (FMODNoiseState *)dsp->plugindata;
|
||||
|
||||
if (op == FMOD_DSP_PROCESS_QUERY)
|
||||
{
|
||||
FMOD_SPEAKERMODE outmode = FMOD_SPEAKERMODE_DEFAULT;
|
||||
int outchannels = 0;
|
||||
|
||||
switch(state->format())
|
||||
{
|
||||
case FMOD_NOISE_FORMAT_MONO:
|
||||
outmode = FMOD_SPEAKERMODE_MONO;
|
||||
outchannels = 1;
|
||||
break;
|
||||
|
||||
case FMOD_NOISE_FORMAT_STEREO:
|
||||
outmode = FMOD_SPEAKERMODE_STEREO;
|
||||
outchannels = 2;
|
||||
break;
|
||||
|
||||
case FMOD_NOISE_FORMAT_5POINT1:
|
||||
outmode = FMOD_SPEAKERMODE_5POINT1;
|
||||
outchannels = 6;
|
||||
}
|
||||
|
||||
if (outbufferarray)
|
||||
{
|
||||
outbufferarray->speakermode = outmode;
|
||||
outbufferarray->buffernumchannels[0] = outchannels;
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
state->generate(outbufferarray->buffers[0], length, outbufferarray->buffernumchannels[0]);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspreset(FMOD_DSP_STATE *dsp)
|
||||
{
|
||||
FMODNoiseState *state = (FMODNoiseState *)dsp->plugindata;
|
||||
state->reset();
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspsetparamfloat(FMOD_DSP_STATE *dsp, int index, float value)
|
||||
{
|
||||
FMODNoiseState *state = (FMODNoiseState *)dsp->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_NOISE_PARAM_LEVEL:
|
||||
state->setLevel(value);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspgetparamfloat(FMOD_DSP_STATE *dsp, int index, float *value, char *valuestr)
|
||||
{
|
||||
FMODNoiseState *state = (FMODNoiseState *)dsp->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_NOISE_PARAM_LEVEL:
|
||||
*value = state->level();
|
||||
if (valuestr) snprintf(valuestr, FMOD_DSP_GETPARAM_VALUESTR_LENGTH, "%.1f dB", state->level());
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspsetparamint(FMOD_DSP_STATE *dsp, int index, int value)
|
||||
{
|
||||
FMODNoiseState *state = (FMODNoiseState *)dsp->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_NOISE_PARAM_FORMAT:
|
||||
state->setFormat((FMOD_NOISE_FORMAT)value);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
FMOD_RESULT F_CALL FMOD_Noise_dspgetparamint(FMOD_DSP_STATE *dsp, int index, int *value, char *valuestr)
|
||||
{
|
||||
FMODNoiseState *state = (FMODNoiseState *)dsp->plugindata;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case FMOD_NOISE_PARAM_FORMAT:
|
||||
*value = state->format();
|
||||
if (valuestr) snprintf(valuestr, FMOD_DSP_GETPARAM_VALUESTR_LENGTH, "%s", FMOD_Noise_Format_Names[state->format()]);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
return FMOD_ERR_INVALID_PARAM;
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/*==============================================================================
|
||||
RNBO DSP Plugin Example
|
||||
Copyright (c), Firelight Technologies Pty, Ltd 2004-2025.
|
||||
|
||||
This example shows how to integrate RNBO C++ source code into an FMOD effect.
|
||||
1. Add the rnbo and rnbo/common directories to your include paths.
|
||||
2. Add the generated RNBO source .cpp file and rnbo/RNBO.cpp files to your list
|
||||
of source files.
|
||||
3. Build and copy the generated library into your FMOD Studio script directory:
|
||||
https://fmod.com/docs/2.02/studio/plugin-reference.html#loading-plug-ins
|
||||
==============================================================================*/
|
||||
#if __has_include("RNBO.h")
|
||||
#include "RNBO.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <atomic>
|
||||
#include <string.h>
|
||||
|
||||
#include "fmod.hpp"
|
||||
|
||||
static FMOD_DSP_PARAMETER_DESC** params = nullptr;
|
||||
static int numParams;
|
||||
static int numInputs;
|
||||
static int numOutputs;
|
||||
static std::atomic<int> gSysCount = 0;
|
||||
|
||||
static FMOD_RESULT F_CALL FMOD_RNBO_Create(FMOD_DSP_STATE *dsp_state)
|
||||
{
|
||||
dsp_state->plugindata = FMOD_DSP_ALLOC(dsp_state, sizeof(RNBO::CoreObject));
|
||||
if (!dsp_state->plugindata)
|
||||
{
|
||||
return FMOD_ERR_MEMORY;
|
||||
}
|
||||
|
||||
RNBO::CoreObject *rnboObject = (RNBO::CoreObject *)dsp_state->plugindata;
|
||||
|
||||
int sampleRate;
|
||||
unsigned int blockSize;
|
||||
|
||||
FMOD_DSP_GETSAMPLERATE(dsp_state, &sampleRate);
|
||||
FMOD_DSP_GETBLOCKSIZE(dsp_state, &blockSize);
|
||||
|
||||
new (rnboObject) RNBO::CoreObject();
|
||||
|
||||
rnboObject->prepareToProcess(sampleRate, blockSize);
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
static FMOD_RESULT F_CALL FMOD_RNBO_Release(FMOD_DSP_STATE *dsp_state)
|
||||
{
|
||||
RNBO::CoreObject *rnboObject = (RNBO::CoreObject *)dsp_state->plugindata;
|
||||
rnboObject->~CoreObject();
|
||||
|
||||
FMOD_DSP_FREE(dsp_state, rnboObject);
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
static FMOD_RESULT F_CALL FMOD_RNBO_Process(FMOD_DSP_STATE *dsp_state, unsigned int length, const FMOD_DSP_BUFFER_ARRAY *inbufferarray, FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL inputsidle, FMOD_DSP_PROCESS_OPERATION op)
|
||||
{
|
||||
RNBO::CoreObject *rnboObject = (RNBO::CoreObject *)dsp_state->plugindata;
|
||||
|
||||
if (op == FMOD_DSP_PROCESS_QUERY)
|
||||
{
|
||||
if (numInputs > 0)
|
||||
{
|
||||
if (inputsidle)
|
||||
{
|
||||
return FMOD_ERR_DSP_SILENCE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outbufferarray && outbufferarray[0].buffernumchannels)
|
||||
{
|
||||
outbufferarray[0].buffernumchannels[0] = numOutputs;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rnboObject->process(inbufferarray[0].buffers[0], inbufferarray[0].buffernumchannels[0],
|
||||
outbufferarray[0].buffers[0], outbufferarray[0].buffernumchannels[0], length);
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
static FMOD_RESULT F_CALL FMOD_RNBO_SetParamFloat(FMOD_DSP_STATE *dsp_state, int index, float value)
|
||||
{
|
||||
RNBO::CoreObject *rnboObject = (RNBO::CoreObject *)dsp_state->plugindata;
|
||||
|
||||
rnboObject->setParameterValue(index, value);
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
static FMOD_RESULT F_CALL FMOD_RNBO_GetParamFloat(FMOD_DSP_STATE *dsp_state, int index, float *value, char *valuestr)
|
||||
{
|
||||
RNBO::CoreObject *rnboObject = (RNBO::CoreObject *)dsp_state->plugindata;
|
||||
|
||||
*value = (float)rnboObject->getParameterValue(index);
|
||||
if (valuestr) snprintf(valuestr, FMOD_DSP_GETPARAM_VALUESTR_LENGTH, "%s", rnboObject->getParameterName(index));
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
static FMOD_RESULT F_CALL FMOD_RNBO_SysRegister(FMOD_DSP_STATE* dsp_state)
|
||||
{
|
||||
RNBO::CoreObject* rnboObject = (RNBO::CoreObject*)dsp_state->plugindata;
|
||||
|
||||
gSysCount++;
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
static FMOD_RESULT F_CALL FMOD_RNBO_SysDeregister(FMOD_DSP_STATE* dsp_state)
|
||||
{
|
||||
RNBO::CoreObject* rnboObject = (RNBO::CoreObject*)dsp_state->plugindata;
|
||||
|
||||
gSysCount--;
|
||||
if (gSysCount == 0)
|
||||
{
|
||||
for (int i = 0; i < numParams; ++i)
|
||||
{
|
||||
free(params[i]);
|
||||
}
|
||||
free(params);
|
||||
|
||||
params = nullptr;
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
extern "C" F_EXPORT FMOD_DSP_DESCRIPTION *F_CALL FMODGetDSPDescription()
|
||||
{
|
||||
static FMOD_DSP_DESCRIPTION desc = { FMOD_PLUGIN_SDK_VERSION, "FMOD RNBO", 0x00010000 };
|
||||
desc.create = FMOD_RNBO_Create;
|
||||
desc.release = FMOD_RNBO_Release;
|
||||
desc.process = FMOD_RNBO_Process;
|
||||
desc.setparameterfloat = FMOD_RNBO_SetParamFloat;
|
||||
desc.getparameterfloat = FMOD_RNBO_GetParamFloat;
|
||||
desc.sys_register = FMOD_RNBO_SysRegister;
|
||||
desc.sys_deregister = FMOD_RNBO_SysDeregister;
|
||||
|
||||
if (!params)
|
||||
{
|
||||
RNBO::CoreObject tmpRnboObject;
|
||||
|
||||
numParams = tmpRnboObject.getNumParameters();
|
||||
numInputs = tmpRnboObject.getNumInputChannels();
|
||||
numOutputs = tmpRnboObject.getNumOutputChannels();
|
||||
|
||||
desc.numparameters = numParams;
|
||||
desc.numinputbuffers = numInputs > 0;
|
||||
desc.numoutputbuffers = numOutputs > 0;
|
||||
|
||||
params = (FMOD_DSP_PARAMETER_DESC**)malloc(desc.numparameters * sizeof(FMOD_DSP_PARAMETER_DESC*));
|
||||
|
||||
for (int i = 0; i < numParams; ++i)
|
||||
{
|
||||
RNBO::ParameterInfo info = {};
|
||||
tmpRnboObject.getParameterInfo(i, &info);
|
||||
|
||||
params[i] = (FMOD_DSP_PARAMETER_DESC *)malloc(sizeof(FMOD_DSP_PARAMETER_DESC));
|
||||
memset(params[i], 0, sizeof(FMOD_DSP_PARAMETER_DESC));
|
||||
|
||||
snprintf(params[i]->name, sizeof(params[i]->name), "%s", tmpRnboObject.getParameterId(i));
|
||||
snprintf(params[i]->label, sizeof(params[i]->label), "%s", info.unit);
|
||||
|
||||
params[i]->type = FMOD_DSP_PARAMETER_TYPE_FLOAT;
|
||||
params[i]->floatdesc.defaultval = info.initialValue;
|
||||
params[i]->floatdesc.min = info.min;
|
||||
params[i]->floatdesc.max = info.max;
|
||||
}
|
||||
|
||||
desc.paramdesc = params;
|
||||
}
|
||||
return &desc;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue