- initial import

git-svn-id: http://moon:8086/svn/software/trunk/projects/JaySynth@37 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
2014-10-25 07:27:55 +00:00
commit 843c6e300c
75 changed files with 40248 additions and 0 deletions
+433
View File
@@ -0,0 +1,433 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "blit.h"
#include "fir/fir2.h"
#include "vector_utils.h"
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
INT32 smin(INT32 x, INT32 y)
{
if (x < y)
return x;
return y;
}
INT32 smax(INT32 x, INT32 y)
{
if (x > y)
return x;
return y;
}
UINT32 umin(UINT32 x, UINT32 y)
{
if (x < y)
return x;
return y;
}
UINT32 umax(UINT32 x, UINT32 y)
{
if (x > y)
return x;
return y;
}
void IP_ModInit(blit_common_t *pCom)
{
INT32 n, k;
synth_float_t *pN_K = pCom->N_K;
synth_float_t *pK = pCom->K;
for (n=0; n <= BLIT_INTEROLATION_ORDER; n++)
{
for (k=0; k <= BLIT_INTEROLATION_ORDER; k++)
{
if (k == n)
continue;
*(pN_K++) = (synth_float_t)1 / (n-k);
*(pK++) = (synth_float_t)k;
}
}
}
synth_float_t IP_Process(blit_t *pObj, synth_float_t *pLUT, synth_float_t m)
{
INT32 mi, j;
INT32 n, k;
synth_float_t hn, y = 0, delay;
synth_float_t *pN_K = pObj->pCom->N_K;
synth_float_t *pK = pObj->pCom->K;
mi = (INT32)m;
delay = m - (synth_float_t)mi;
j = (INT32)BLIT_INTEROLATION_ORDER;
for (n=0; n <= BLIT_INTEROLATION_ORDER; n++)
{
hn = (synth_float_t)1;
for (k=0; k < BLIT_INTEROLATION_ORDER; k++)
{
hn *= (*(pN_K++) * (delay - *(pK++)));
}
y += hn*pLUT[smax(0, mi-j)];
j--;
}
return y;
}
void BLIT_freq_update(blit_t *pObj, synth_float_t scale)
{
synth_float_t p;
pObj->freq_update_req = 0;
// p = pObj->fs/(pObj->f*scale*pObj->fm);
p = pObj->fs/(scale*pObj->fm);
pObj->dx = (synth_float_t)1.0/p;
pObj->m = umin(BLIT_NUM_HARM_MAX-1, (UINT32)((synth_float_t)SYNTH_BANDWIDTH*2.0*(int)((p/2)) + 0));
}
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void BLIT_ModInit(blit_common_t *pCom)
{
int m, n;
synth_float_t **ppKaiser;
synth_float_t x, dx, a, b, blit, blep;
// Calculate table sizes
pCom->pTableSizes = (UINT32*)malloc(BLIT_NUM_HARM_MAX*sizeof(UINT32));
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
pCom->pTableSizes[m] = m*BLIT_TABLE_OVERSAMPLING;
if (pCom->pTableSizes[m] < BLIT_TABLE_SIZE_MIN)
pCom->pTableSizes[m] = BLIT_TABLE_SIZE_MIN;
}
// Generate Kaiser window
ppKaiser = (synth_float_t**)malloc(BLIT_NUM_HARM_MAX*sizeof(synth_float_t*));
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
ppKaiser[m] = (synth_float_t*)malloc(pCom->pTableSizes[m]*sizeof(synth_float_t));
CalcKaiser(NULL, ppKaiser[m], 8.f, pCom->pTableSizes[m]);
}
// Allocate BLIT table
pCom->ppBLEP = (synth_float_t**)malloc(BLIT_NUM_HARM_MAX*sizeof(synth_float_t*));
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
pCom->ppBLEP[m] = (synth_float_t*)malloc(pCom->pTableSizes[m]*sizeof(synth_float_t));
}
// Generate BLIT
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
dx = (synth_float_t)1/(pCom->pTableSizes[m]);
x = -0.5;
blep = 0;
for (n=0; n < pCom->pTableSizes[m]; n++)
{
a = sin(x*pi);
b = sin(m*x*pi);
if (a == 0)
blit = (synth_float_t)m;
else
blit = b/a * ppKaiser[m][n];
blep += blit;
pCom->ppBLEP[m][n] = blep/(pCom->pTableSizes[m]);
x += dx;
}
}
/*
m = BLIT_NUM_HARM_MAX/2;
for (n=0; n < BLIT_TABLE_SIZE; n++)
{
SynthDebug("BLEP[%d][%d] = %.14f\n", m, n, pCom->ppBLEP[m][n]);
}
for (n=0; n < BLIT_TABLE_SIZE; n++)
{
SynthDebug("Kaiser[%d] = %.14f\n", n, pKaiser[n]);
}
*/
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
free(ppKaiser[m]);
}
free(ppKaiser);
// Precalculate Interpolation constants
IP_ModInit(pCom);
}
void BLIT_ModFree(blit_common_t *pCom)
{
int m;
if (pCom->ppBLEP)
{
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
free(pCom->ppBLEP[m]);
}
free(pCom->ppBLEP);
}
free(pCom->pTableSizes);
}
void BLIT_Init(blit_t *pObj, blit_common_t *pCom, synth_float_t fs)
{
pObj->pCom = pCom;
pObj->fs = fs;
pObj->dutycycle = 0.5;
BLIT_Reset(pObj, 0);
pObj->bufsize = 0;
BLIT_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
BLIT_Prepare(pObj, SYNTH_MAX_BUFSIZE);
}
void BLIT_Free(blit_t *pObj)
{
BLIT_SetBufsize(pObj, 0);
}
void BLIT_SetBufsize(blit_t *pObj, UINT32 size)
{
if (pObj->bufsize == size)
return;
pObj->bufsize = size;
if (!size)
return;
}
void BLIT_SetFS(blit_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
pObj->freq_update_req = 1;
}
void BLIT_Prepare(blit_t *pObj, UINT32 len)
{
synth_float_t pitch_buf[SYNTH_MAX_BUFSIZE];
synth_float_t out_buf[SYNTH_MAX_BUFSIZE];
len = min(len, SYNTH_MAX_BUFSIZE);
// Let Oscillators run with different pitches to randomize phase
Add_inplace_VS(pitch_buf, 0, 8*440.0*(1+0.01*(synth_float_t)rand()/RAND_MAX), len);
BLIT_Process_SAW_Vector(pObj, pitch_buf, NULL, NULL, NULL, out_buf, len);
BLIT_Process_SQR_Vector(pObj, pitch_buf, NULL, NULL, NULL, NULL, out_buf, len);
BLIT_Process_TRI_Vector(pObj, pitch_buf, NULL, NULL, NULL, out_buf, len);
}
void BLIT_Reset(blit_t *pObj, synth_float_t phase)
{
pObj->saw_x = fmod(0.5f + phase, 1);
pObj->sqr_x1 = fmod(0.5f + phase, 1);
pObj->sqr_x2 = fmod(0.5f + phase, 1);
pObj->sqr_pol1 = 1; // ToDo: Adjust according to phase
pObj->sqr_pol2 = 1; // ToDo: Adjust according to phase
pObj->tri_x = fmod(0.5f + phase, 1);
pObj->tri_sum = 0; // ToDo: Adjust according to phase
pObj->tri_pol = 1; // ToDo: Adjust according to phase
pObj->fm = 1;
pObj->pwm = 0;
pObj->pulse_offset = 0; // ToDo: Adjust according to phase
}
void BLIT_Start(blit_t *pObj)
{
pObj->freq_update_req = 1;
}
void BLIT_SetDutyCycle(blit_t *pObj, synth_float_t duty_cycle)
{
pObj->dutycycle = duty_cycle;
}
void BLIT_Process_SAW_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len)
{
UINT32 i, is_slave, m;
synth_float_t out;
synth_float_t blep, n;
blit_common_t *pCom = pObj->pCom;
is_slave = (pSyncIn != NULL) && (pSyncOut == NULL);
if (pSyncOut)
memset(pSyncOut, 0, len*sizeof(synth_float_t));
// Create output
for (i=0; i< len; i++)
{
if (pObj->freq_update_req)
{
BLIT_freq_update(pObj, pPitch[i]);
}
if (pObj->saw_x >= (synth_float_t)0.5)
{
pObj->saw_x -= 1;
if (pCV_fm)
{
pObj->fm = (synth_float_t)pow((synth_float_t)2, pCV_fm[i]);
}
BLIT_freq_update(pObj, pPitch[i]);
}
m = pObj->m;
// Lagrange interpolation
n = (pObj->saw_x+0.5)*((pCom->pTableSizes[m])-1);
blep = IP_Process(pObj, &pCom->ppBLEP[m][0], n);
out = pObj->saw_x - blep;
pObj->saw_x += pObj->dx;
*(pOut++) = 2*(out+0.5);
}
}
void BLIT_Process_SQR_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len)
{
UINT32 i, is_slave, m;
synth_float_t blep1, blep2, n;
synth_float_t dutycycle;
blit_common_t *pCom = pObj->pCom;
is_slave = (pSyncIn != NULL) && (pSyncOut == NULL);
if (pSyncOut)
memset(pSyncOut, 0, len*sizeof(synth_float_t));
// Create output
for (i=0; i< len; i++)
{
if (pObj->freq_update_req)
{
BLIT_freq_update(pObj, pPitch[i]);
}
if (pObj->sqr_x1 >= (synth_float_t)0.5)
{
pObj->sqr_x1 -= 1;
pObj->sqr_pol1 = !pObj->sqr_pol1;
if (pCV_fm)
{
pObj->fm = (synth_float_t)pow((synth_float_t)2, pCV_fm[i]);
}
if (pCV_pwm)
{
pObj->pwm = (synth_float_t)pCV_pwm[i];
}
dutycycle = min(1, max(0, pObj->dutycycle + pObj->pwm));
pObj->pulse_offset = 2*(dutycycle-0.5);
pObj->sqr_x2 = pObj->sqr_x1 + dutycycle - 1;
pObj->sqr_pol2 = pObj->sqr_pol1;
BLIT_freq_update(pObj, pPitch[i]);
}
while (pObj->sqr_x2 >= (synth_float_t)0.5)
{
pObj->sqr_pol2 = !pObj->sqr_pol2;
pObj->sqr_x2 -= 1;
}
while (pObj->sqr_x2 < (synth_float_t)-0.5)
{
pObj->sqr_pol2 = !pObj->sqr_pol2;
pObj->sqr_x2 += 1;
}
m = pObj->m;
// Lagrange interpolation
n = (pObj->sqr_x1+0.5)*((pCom->pTableSizes[m])-1);
blep1 = IP_Process(pObj, &pCom->ppBLEP[m][0], n);
if (pObj->sqr_pol1)
blep1 = 1 - blep1;
n = (pObj->sqr_x2+0.5)*((pCom->pTableSizes[m])-1);
blep2 = IP_Process(pObj, &pCom->ppBLEP[m][0], n);
if (pObj->sqr_pol2)
blep2 = 1 - blep2;
*(pOut++) = 4*(blep1-0.5)*(blep2-0.5) - pObj->pulse_offset;
pObj->sqr_x1 += pObj->dx;
pObj->sqr_x2 += pObj->dx;
}
}
void BLIT_Process_TRI_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len)
{
UINT32 i, is_slave, m;
synth_float_t out;
synth_float_t blep, n;
blit_common_t *pCom = pObj->pCom;
is_slave = (pSyncIn != NULL) && (pSyncOut == NULL);
if (pSyncOut)
memset(pSyncOut, 0, len*sizeof(synth_float_t));
for (i=0; i< len; i++)
{
if (pObj->freq_update_req)
{
BLIT_freq_update(pObj, pPitch[i]);
}
if (pObj->tri_x >= (synth_float_t)0.5)
{
pObj->tri_x -= 1;
pObj->tri_pol = !pObj->tri_pol;
if (pCV_fm)
{
pObj->fm = (synth_float_t)pow((synth_float_t)2, pCV_fm[i]);
}
BLIT_freq_update(pObj, 2*pPitch[i]);
}
m = pObj->m;
// Lagrange interpolation
n = (pObj->tri_x+0.5)*((pCom->pTableSizes[m])-1);
// blep = IP_Process(&_sg_ppBLEP[m][0], n);
// No interpolation
blep = pCom->ppBLEP[m][(UINT32)n];
if (pObj->tri_pol)
out = 1 - blep;
else
out = blep;
pObj->tri_sum += 4*(out-0.5)*pObj->dx;
*(pOut++) = pObj->tri_sum;
pObj->tri_x += pObj->dx;
}
}
+61
View File
@@ -0,0 +1,61 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _BLIT_H_
#define _BLIT_H_
#include "synth_defs.h"
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
typedef struct _sblit_common_t
{
UINT32 *pTableSizes;
synth_float_t **ppBLEP;
synth_float_t N_K[(BLIT_INTEROLATION_ORDER+0)*(BLIT_INTEROLATION_ORDER+1)];
synth_float_t K[(BLIT_INTEROLATION_ORDER+0)*(BLIT_INTEROLATION_ORDER+1)];
} blit_common_t;
typedef struct _sblit_t
{
blit_common_t *pCom;
synth_float_t fs, fm, pwm, dutycycle, pulse_offset;
synth_float_t saw_x, x2, dx;
synth_float_t sqr_x1, sqr_x2, tri;
synth_float_t tri_x, tri_sum;
UINT32 m, tri_pol, sqr_pol1, sqr_pol2;
UINT32 freq_update_req, bufsize;
} blit_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void BLIT_ModInit(blit_common_t *pCom);
void BLIT_ModFree(blit_common_t *pCom);
void BLIT_Init(blit_t *pObj, blit_common_t *pCom, synth_float_t fs);
void BLIT_Free(blit_t *pObj);
void BLIT_SetBufsize(blit_t *pObj, UINT32 size);
void BLIT_SetFS(blit_t *pObj, synth_float_t fs);
void BLIT_Reset(blit_t *pObj, synth_float_t phase);
void BLIT_Start(blit_t *pObj);
void BLIT_Prepare(blit_t *pObj, UINT32 len);
void BLIT_SetDutyCycle(blit_t *pObj, synth_float_t duty_cycle);
void BLIT_Process_SAW_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len);
void BLIT_Process_SQR_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len);
void BLIT_Process_TRI_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _BLIT_H_
+208
View File
@@ -0,0 +1,208 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "env.h"
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void ENV_Init(envgen_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
ENV_Reset(pObj);
ENV_Param2Set(pObj, ENV_PARAM2_A, 0.001);
ENV_Param2Set(pObj, ENV_PARAM2_D, 1.000);
ENV_Param2Set(pObj, ENV_PARAM2_S, 1.000);
ENV_Param2Set(pObj, ENV_PARAM2_R, 1.000);
pObj->bufsize = 0;
pObj->pOut = NULL;
ENV_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
}
void ENV_Free(envgen_t *pObj)
{
ENV_SetBufsize(pObj, 0);
}
void ENV_SetBufsize(envgen_t *pObj, UINT32 size)
{
if (pObj->bufsize == size)
return;
pObj->bufsize = size;
if (pObj->pOut)
free(pObj->pOut);
pObj->pOut = NULL;
if (!size)
return;
pObj->pOut = (synth_float_t*)malloc(pObj->bufsize*sizeof(synth_float_t));
}
void ENV_SetFS(envgen_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
}
void ENV_Reset(envgen_t *pObj)
{
pObj->state = env_state_idle;
pObj->s = 0;
pObj->k = (synth_float_t)1/ENV_KE;
}
void ENV_Event(envgen_t *pObj, UINT32 type)
{
switch(type)
{
case env_event_trigger:
case env_event_retrigger:
// pObj->sr = 0;
pObj->state = env_state_attack;
// pObj->k = (synth_float_t)1/ENV_KE;
// if (type == env_event_retrigger)
// {
// pObj->a_r = 1.f/(0.001*pObj->fs);
// pObj->b_r = 1.f - pObj->a_r;
// pObj->state = env_state_attack_retrigger;
//
// }
break;
case env_event_release:
if (pObj->state == env_state_idle)
break;
// if (pObj->state == env_state_attack)
// pObj->sf = pObj->sr;
// if (pObj->state == env_state_sustain)
// pObj->sf = pObj->param.Vs/pObj->k;
pObj->state = env_state_release;
break;
default:
break;
}
};
void ENV_Param2Set(envgen_t *pObj, UINT32 type, synth_float_t value)
{
switch(type)
{
case ENV_PARAM2_A:
pObj->param.Ta = max(ENV_MIN_A, value);
pObj->a_a = 1.f/(pObj->param.Ta*pObj->fs);
pObj->b_a = 1.f - pObj->a_a;
break;
case ENV_PARAM2_D:
pObj->param.Td = max(ENV_MIN_D, value);
pObj->a_d = 5.f/(pObj->param.Td*pObj->fs);
pObj->b_d = 1.f - pObj->a_d;
break;
case ENV_PARAM2_S:
pObj->param.Vs = value;
break;
case ENV_PARAM2_R:
pObj->param.Tr = max(ENV_MIN_R, value);
pObj->a_r = 5.f/(pObj->param.Tr*pObj->fs);
pObj->b_r = 1.f - pObj->a_r;
break;
default:
break;
}
}
UINT32 ENV_ParamGet(envgen_t *pObj, UINT32 type)
{
return 0;
}
INT32 ENV_IsIdle(envgen_t *pObj)
{
return pObj->state == env_state_idle;
}
synth_float_t* ENV_ProcessDataV(envgen_t *pObj, UINT32 len)
{
synth_float_t *pX, y;
pX = pObj->pOut;
while(len)
{
y = pObj->k*pObj->s;
switch (pObj->state)
{
case env_state_idle:
break;
case env_state_attack:
// y = pObj->k*pObj->sr;
if (y >= 1.0)
{
// pObj->af = 5.f/(pObj->param.Td*pObj->fs);
// pObj->bf = 1.f - pObj->af;
// pObj->k = (synth_float_t)1/ENV_KE;
// pObj->sf = pObj->sr;
pObj->state = env_state_decay;
}
pObj->s = pObj->a_a + pObj->b_a*pObj->s;
break;
case env_state_attack_retrigger:
pObj->sf = pObj->b_r*pObj->sf;
if (pObj->sf <= ENV_TOL)
{
pObj->a_r = 5.f/(pObj->param.Tr*pObj->fs);
pObj->b_r = 1.f - pObj->a_r;
pObj->state = env_state_attack;
}
break;
case env_state_decay:
if (y <= pObj->param.Vs)
{
pObj->state = env_state_sustain;
}
pObj->s = pObj->b_d*pObj->s;
break;
case env_state_sustain:
y = pObj->param.Vs;
break;
case env_state_release:
if (y <= ENV_TOL)
{
pObj->state = env_state_idle;
}
pObj->s = pObj->b_r*pObj->s;
break;
default:
break;
}
*(pX++) = y;
len--;
}
return pObj->pOut;
}
+94
View File
@@ -0,0 +1,94 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _ENV_H_
#define _ENV_H_
#include "synth_defs.h"
#define ENV_TOL ((synth_float_t)(1E-4))
#define ENV_KE ((synth_float_t)(1-exp(-1)))
#define ENV_MIN_A (0.001) // s
#define ENV_MIN_D (0.005) // s
#define ENV_MIN_R (0.005) // s
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
ENV_PARAM2_A,
ENV_PARAM2_D,
ENV_PARAM2_S,
ENV_PARAM2_R,
ENV_PARAM2_END
};
enum
{
env_state_idle = 0,
env_state_attack,
env_state_attack_retrigger,
env_state_decay,
env_state_sustain,
env_state_release
};
enum
{
env_event_trigger = 0,
env_event_retrigger,
env_event_release,
};
typedef struct _senv_param_t
{
synth_float_t Ta;
synth_float_t Td;
synth_float_t Vs;
synth_float_t Tr;
} env_param_t;
typedef struct _senvgen_t
{
synth_float_t fs;
UINT32 bufsize;
UINT32 state;
env_param_t param;
synth_float_t k, s, sr, sf;
synth_float_t a_a, b_a;
synth_float_t a_d, b_d;
synth_float_t a_r, b_r;
synth_float_t *pOut;
} envgen_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void ENV_Init(envgen_t *pObj, synth_float_t fs);
void ENV_Free(envgen_t *pObj);
void ENV_Reset(envgen_t *pObj);
void ENV_SetBufsize(envgen_t *pObj, UINT32 size);
void ENV_SetFS(envgen_t *pObj, synth_float_t fs);
void ENV_Event(envgen_t *pObj, UINT32 type);
void ENV_Param2Set(envgen_t *pObj, UINT32 type, synth_float_t value);
UINT32 ENV_ParamGet(envgen_t *pObj, UINT32 type);
INT32 ENV_IsIdle(envgen_t *pObj);
INT32 ENV_IsStage(envgen_t *pObj, UINT32 stage_num);
synth_float_t* ENV_ProcessDataV(envgen_t *pObj, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _ENV_H_
+542
View File
@@ -0,0 +1,542 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "synth_defs.h"
#include "lfo.h"
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
void LFO_freq_update(lfo_t *pObj)
{
synth_float_t f;
f = pObj->param[LFO_PARAM2_FREQ];
pObj->b = 2.0 * sin(f*pi / pObj->fs);
pObj->dx = f/pObj->fs;
if (pObj->param[LFO_PARAM2_DELAY] > 0)
{
pObj->delay_dx = 1.0/(pObj->fs*pObj->param[LFO_PARAM2_DELAY]);
}
else
{
pObj->delay_dx = 1.0;
}
pObj->attack_a = 1.0/(pObj->fs*pObj->param[LFO_PARAM2_ATTACK]*LFO_KE);
}
void LFO_smmother_update(lfo_t *pObj)
{
pObj->smooth_is_negative = (pObj->param[LFO_PARAM2_SMOOTH] < 0);
if (fabs(pObj->param[LFO_PARAM2_SMOOTH]) < 0.001)
{
pObj->smooth_b = 1;
pObj->smooth_is_negative = 0;
}
else
{
pObj->smooth_b = fabs((synth_float_t)5/(pObj->param[LFO_PARAM2_SMOOTH]*pObj->fs));
}
pObj->smooth_a = 1 - pObj->smooth_b;
}
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void LFO_Init(lfo_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
pObj->pOut = NULL;
pObj->bufsize = 0;
pObj->param[LFO_PARAM2_WAVEFORM] = LFO_WAVEFORM_SINE;
pObj->param[LFO_PARAM2_FREQ] = 1;
pObj->param[LFO_PARAM2_SMOOTH] = 0.001; // seconds
pObj->param[LFO_PARAM2_DELAY] = 0; // seconds
pObj->param[LFO_PARAM2_ATTACK] = 0; // seconds
pObj->sh_sample = 0;
pObj->out = 0;
pObj->sqr = 0;
pObj->tri = 0;
pObj->gain = 1;
pObj->offset = 0.5;
LFO_Reset(pObj, 0);
pObj->freq_update_req = 0;
LFO_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
Noise_Init(&pObj->noise, 1+(UINT32)clock() * (UINT32)clock());
}
void LFO_Free(lfo_t *pObj)
{
LFO_SetBufsize(pObj, 0);
}
void LFO_SetBufsize(lfo_t *pObj, UINT32 size)
{
if (pObj->bufsize == size)
return;
pObj->bufsize = size;
if (pObj->pOut)
free(pObj->pOut);
pObj->pOut = NULL;
if (!size)
return;
pObj->pOut = (synth_float_t*)malloc(pObj->bufsize*sizeof(synth_float_t));
}
void LFO_SetFS(lfo_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
LFO_freq_update(pObj);
}
void LFO_Reset(lfo_t *pObj, synth_float_t initial_phase)
{
pObj->a = 0.5;
pObj->y[0] = pObj->a*cos(2*pi*initial_phase);
pObj->y[1] = pObj->a*sin(2*pi*initial_phase);
pObj->x = initial_phase;
pObj->out = 0;
pObj->sqr = 0;
pObj->tri = 0;
pObj->delay_x = 0;
pObj->attack_y = 0;
LFO_freq_update(pObj);
LFO_smmother_update(pObj);
}
void LFO_Param2Set(lfo_t *pObj, UINT32 type, synth_float_t value)
{
switch(type)
{
case LFO_PARAM2_WAVEFORM:
if (pObj->param[type] == (UINT32)value)
break;
pObj->param[type] = (UINT32)value;
pObj->freq_update_req = 1;
break;
case LFO_PARAM2_FREQ:
pObj->param[type] = value;
pObj->freq_update_req = 1;
break;
case LFO_PARAM2_SMOOTH:
pObj->param[type] = value;
LFO_smmother_update(pObj);
break;
case LFO_PARAM2_DELAY:
pObj->param[type] = value;
pObj->freq_update_req = 1;
break;
case LFO_PARAM2_ATTACK:
pObj->param[type] = value;
pObj->freq_update_req = 1;
break;
case LFO_PARAM2_SYMMETRY:
pObj->param[type] = value;
pObj->gain = 1;
pObj->offset = 0.5 *(1 + value) - 1;
break;
default:
break;
}
}
synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len)
{
synth_float_t *pOut, out, in;
UINT32 i, i0;
pOut = pObj->pOut;
// Process Delay
for (i=0; i< len; i++)
{
pObj->delay_x += pObj->delay_dx;
if (pObj->delay_x >= 1.0)
break;
in = (synth_float_t)0;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out;
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
i0 = i;
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SAW)
{
// Create phase
for (i=i0; i< len; i++)
{
in = pObj->x + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_ONE_MINUS_SAW)
{
// Create phase
for (i=i0; i< len; i++)
{
in = (1-pObj->x) + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SH_UNI)
{
// Create phase for S/H
for (i=i0; i< len; i++)
{
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
pObj->sh_sample = Noise_Uniform(&pObj->noise, 1, 0.5);
}
in = pObj->sh_sample + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += pObj->dx;
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SH_GAUSS)
{
// Create phase for S/H
for (i=i0; i< len; i++)
{
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
do
{
pObj->sh_sample = Noise_Gaussian(&pObj->noise, sqrt(1.f/36), 0.5);
} while ((pObj->sh_sample < 0) || (pObj->sh_sample > 1.f));
}
in = pObj->sh_sample + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += pObj->dx;
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
// Create output
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SINE)
{
for (i=i0; i< len; i++)
{
in = pObj->y[1]+pObj->a + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1];
pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0];
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_ONE_MINUS_SINE)
{
for (i=i0; i< len; i++)
{
in = (1-(pObj->y[1]+pObj->a)) + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1];
pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0];
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_COSINE)
{
for (i=i0; i< len; i++)
{
in = pObj->y[0]+pObj->a + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1];
pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0];
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_ONE_MINUS_COSINE)
{
for (i=i0; i< len; i++)
{
in = (1-(pObj->y[0]+pObj->a)) + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1];
pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0];
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SQUARE)
{
// Create phase
for (i=i0; i< len; i++)
{
in = (synth_float_t)pObj->sqr + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += 2*pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
pObj->sqr = !pObj->sqr;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_ONE_MINUS_SQUARE)
{
// Create phase
for (i=i0; i< len; i++)
{
in = (1-((synth_float_t)pObj->sqr)) + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += 2*pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
pObj->sqr = !pObj->sqr;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_TRIANGLE)
{
// Create phase
for (i=i0; i< len; i++)
{
in = (synth_float_t)pObj->tri + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
if (pObj->x < 0.5)
pObj->tri = 2*pObj->x;
else
pObj->tri = 2*(1-pObj->x);
pObj->x += pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_ONE_MINUS_TRIANGLE)
{
// Create phase
for (i=i0; i< len; i++)
{
in = (1-((synth_float_t)pObj->tri)) + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
if (pObj->x < 0.5)
pObj->tri = 2*pObj->x;
else
pObj->tri = 2*(1-pObj->x);
pObj->x += pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
return pObj->pOut;
}
+81
View File
@@ -0,0 +1,81 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _LFO_H_
#define _LFO_H_
#include "synth_defs.h"
#include "noise.h"
#define LFO_SH_ALPHA 0.002 // S&H smoothing
#define LFO_KE ((synth_float_t)(1-exp(-1)))
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
LFO_WAVEFORM_SINE,
LFO_WAVEFORM_COSINE,
LFO_WAVEFORM_SAW,
LFO_WAVEFORM_SQUARE,
LFO_WAVEFORM_TRIANGLE,
LFO_WAVEFORM_SH_UNI,
LFO_WAVEFORM_SH_GAUSS,
LFO_WAVEFORM_ONE_MINUS_SINE,
LFO_WAVEFORM_ONE_MINUS_COSINE,
LFO_WAVEFORM_ONE_MINUS_SAW,
LFO_WAVEFORM_ONE_MINUS_SQUARE,
LFO_WAVEFORM_ONE_MINUS_TRIANGLE,
LFO_NUM_WAVEFORMS
};
enum
{
LFO_PARAM2_WAVEFORM,
LFO_PARAM2_FREQ,
LFO_PARAM2_SMOOTH,
LFO_PARAM2_DELAY,
LFO_PARAM2_ATTACK,
LFO_PARAM2_SYMMETRY,
LFO_NUM_PARAMS
};
typedef struct _slfo_t
{
synth_float_t param[LFO_NUM_PARAMS];
synth_float_t fs;
synth_float_t a, b, y[2], x, dx, out, sh_sample, tri;
int freq_update_req, sqr;
synth_float_t *pOut;
UINT32 bufsize;
noise_gen_t noise;
synth_float_t smooth_a, smooth_b;
UINT32 smooth_is_negative;
synth_float_t delay_x, delay_dx, attack_y, attack_a;
synth_float_t gain, offset;
} lfo_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void LFO_Init(lfo_t *pObj, synth_float_t fs);
void LFO_Free(lfo_t *pObj);
void LFO_SetFS(lfo_t *pObj, synth_float_t fs);
void LFO_SetBufsize(lfo_t *pObj, UINT32 bufsize);
void LFO_Reset(lfo_t *pObj, synth_float_t initial_phase);
void LFO_Param2Set(lfo_t *pObj, UINT32 type, synth_float_t value);
synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _LFO_H_
File diff suppressed because it is too large Load Diff
+94
View File
@@ -0,0 +1,94 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "synth_defs.h"
#include "noise.h"
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
#define PM_IA 16807
#define PM_IM 2147483647
#define PM_AM (1.0/PM_IM)
#define PM_IQ 127773
#define PM_IR 2836
#define PM_MASK 123459876
// 'Minimal' random number generator of Park and Miller. Returns a uniform random deviate
// between 0.0 and 1.0. Set or resetidumto any integer value (except the unlikely value MASK)
// to initialize the sequence; idummust not be altered between calls for successive deviates in
// a sequence.
double ran0(long *idum)
{
long k;
double ans;
*idum ^= PM_MASK; // XORing with MASKallows use of zero and other
k=(*idum)/PM_IQ; // simple bit patterns for idum.
*idum=PM_IA*(*idum-k*PM_IQ)-PM_IR *k; // Compute idum=(IA*idum) % IM without over-
// flows by Schrages method.
if (*idum < 0)
*idum += PM_IM;
ans=PM_AM*(*idum); // Convert idumto a floating result.
*idum ^= PM_MASK; // Unmask before return.
return ans;
}
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Noise_Init(noise_gen_t *pObj, UINT32 seed)
{
pObj->state = (long)(seed & NOISE_LFSR_MAX);
}
void Noise_Free(noise_gen_t *pObj)
{
}
synth_float_t Noise_Uniform(noise_gen_t *pObj, synth_float_t var, synth_float_t mu)
{
/*
if (pObj->lfsr & 0x800000)
pObj->lfsr = ((pObj->lfsr << 1) | 1) ^ NOISE_LFSR_POLY;
else
pObj->lfsr = (pObj->lfsr << 1);
pObj->lfsr &= NOISE_LFSR_MAX;
*/
/* taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */
// pObj->lfsr = (pObj->lfsr >> 1) ^ (-(pObj->lfsr & 1) & NOISE_LFSR_POLY);
// return var * ((synth_float_t)rand()/(RAND_MAX+1) + mu -0.5);
return var*(ran0(&pObj->state) + mu -0.5);
}
synth_float_t Noise_Gaussian(noise_gen_t *pObj, synth_float_t std, synth_float_t mu)
{
synth_float_t U1, U2, V1, V2, S, Y;
do
{
U1 = Noise_Uniform(pObj, 1, 0.5); // U1=[0,1]
U2 = Noise_Uniform(pObj, 1, 0.5); // U2=[0,1]
V1 = 2 * U1 - 1; // V1=[-1,1]
V2 = 2 * U2 - 1; // V2=[-1,1]
S = V1 * V1 + V2 * V2;
} while (S >= 1);
// X = sqrt(-2 * log(S) / S) * V1;
Y = sqrt(-2 * log(S) / S) * V2;
Y = mu + std*Y;
return Y;
}
+38
View File
@@ -0,0 +1,38 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _NOISE_H_
#define _NOISE_H_
#include "synth_defs.h"
#define NOISE_LFSR_POLY 0xD0000001
#define NOISE_LFSR_MAX 0xFFFFFFFF
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
typedef struct _snoise_gen_t
{
long state;
} noise_gen_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Noise_Init(noise_gen_t *pObj, UINT32 seed);
void Noise_Free(noise_gen_t *pObj);
synth_float_t Noise_Uniform(noise_gen_t *pObj, synth_float_t vmax, synth_float_t mu);
synth_float_t Noise_Gaussian(noise_gen_t *pObj, synth_float_t std, synth_float_t mu);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _NOISE_H_
+886
View File
@@ -0,0 +1,886 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
#include "synth_defs.h"
#include "vcf.h"
#include "voice.h"
#include "param_scale.h"
static const param_info_t param_info[] =
{
{
SYNTH_PARAM_VOLUME,
"Master Volume",
/*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VOICE_PAN_SPREAD,
"Voice Pan Spread",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_TUNE,
"Master Tune",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1
},
{
SYNTH_PARAM_TOTAL_NUM_VOICES,
"Total num. Voices",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/MAX_POLYPHONY, /*interval*/1
},
{
SYNTH_PARAM_HUMANIZE_ENABLE,
"Humanize Enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_HUMANIZE_VAR_VCO,
"Humanize Spread VCO",
/*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/10, /*interval*/0.01
},
{
SYNTH_PARAM_HUMANIZE_VAR_VCF,
"Humanize Spread VCF",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/200, /*interval*/0.1
},
{
SYNTH_PARAM_HUMANIZE_VAR_ENV,
"Humanize Spread ENV",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_MONOPHONIC_ENABLE,
"Monophonic Enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_MONOPHONIC_RETRIGGER_ENABLE,
"Monophonic Retrigger Enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_UNISONO_ENABLE,
"Unisono Enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_UNISONO_NUM_VOICES,
"Unisono num. Voices",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/MAX_POLYPHONY, /*interval*/1
},
{
SYNTH_PARAM_PORTAMENTO_TIME,
"Portamento Time",
/*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.001, /*pcenter*/-1, /*max*/0.5, /*interval*/0.001
},
{
SYNTH_PARAM_OSC_0_ENABLE,
"OSC1 enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_ENABLE,
"OSC2 enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_RESTART_ON_TRIGGER,
"OSC1 restart on trigger",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_RESTART_ON_TRIGGER,
"OSC2 restart on trigger",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_LEVEL,
"OSC1 level",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_1_LEVEL,
"OSC2 level",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_0_DUTYCYCLE,
"OSC1 pulse width",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_1_DUTYCYCLE,
"OSC2 pulse width",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_0_DETUNE,
"OSC1 detune",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-50, /*pcenter*/0, /*max*/+50, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_1_DETUNE,
"OSC2 detune",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-50, /*pcenter*/0, /*max*/+50, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_0_TRANSPOSE,
"OSC1 transpose",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_TRANSPOSE,
"OSC2 transpose",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_WAVEFORM,
"OSC1 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/OSC_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_WAVEFORM,
"OSC2 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/OSC_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_PB_RANGE_MIN,
"OSC1 pitch bender minimum",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_PB_RANGE_MIN,
"OSC2 pitch bender minimum",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_PB_RANGE_MAX,
"OSC1 pitch bender maximum",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_PB_RANGE_MAX,
"OSC2 pitch bender maximum",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_FM_AMT_0,
"OSC1 FM amt 1",
/*Base*/10, /*kexp*/2.5, /*scenter*/0.5, /*min*/-48, /*pcenter*/0, /*max*/+48, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_1_FM_AMT_0,
"OSC2 FM amt 1",
/*Base*/10, /*kexp*/2.5, /*scenter*/0.5, /*min*/-48, /*pcenter*/0, /*max*/+48, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_0_FM_AMT_1,
"OSC1 FM amt 2",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_1_FM_AMT_1,
"OSC2 FM amt 2",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_0_FM_SRC_0,
"OSC1 FM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_FM_SRC_0,
"OSC2 FM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_FM_SRC_1,
"OSC1 FM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_FM_SRC_1,
"OSC2 FM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_FM_SRC_OP,
"OSC1 FM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_FM_SRC_OP,
"OSC2 FM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_AM_AMT_0,
"OSC1 AM amt 1",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_1_AM_AMT_0,
"OSC2 AM amt 1",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_0_AM_AMT_1,
"OSC1 AM amt 2",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_1_AM_AMT_1,
"OSC2 AM amt 2",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_0_AM_SRC_0,
"OSC1 AM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_AM_SRC_0,
"OSC2 AM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_AM_SRC_1,
"OSC1 AM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_AM_SRC_1,
"OSC2 AM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_AM_SRC_OP,
"OSC1 AM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_AM_SRC_OP,
"OSC2 AM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_PWM_AMT_0,
"OSC1 PWM amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_1_PWM_AMT_0,
"OSC2 PWM amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_0_PWM_AMT_1,
"OSC1 PWM amt 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_1_PWM_AMT_1,
"OSC2 PWM amt 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_0_PWM_SRC_0,
"OSC1 PWM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_PWM_SRC_0,
"OSC2 PWM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_PWM_SRC_1,
"OSC1 PWM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_PWM_SRC_1,
"OSC2 PWM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_PWM_SRC_OP,
"OSC1 PWM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_PWM_SRC_OP,
"OSC2 PWM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_NOISE_ENABLE,
"Noise enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1, /*interval*/1
},
{
SYNTH_PARAM_NOISE_LEVEL,
"Noise level",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_NOISE_SHAPE,
"Noise shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NOISE_NUM_SHAPES-1, /*interval*/1
},
{
SYNTH_PARAM_VCA_ENV_AMT,
"VCA Env amt",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCA_AM_AMT_0,
"VCA AM amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCA_AM_SRC_0,
"VCA AM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_VCA_PAN_AMT_0,
"VCA PAN amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCA_PAN_SRC_0,
"VCA PAN src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_VCA_ENV_A,
"VCA Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_VCA_ENV_D,
"VCA Decay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_VCA_ENV_S,
"VCA Sustain",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_ENV_A,
"VCF Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_VCF_ENV_D,
"VCF Decay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_VCF_ENV_S,
"VCF Sustain",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_ENV_R,
"VCF Release",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_ENV_2_A,
"ENV 2 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_ENV_2_D,
"ENV 2 Decay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_ENV_2_S,
"ENV 2 Sustain",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_ENV_2_R,
"ENV 2 Release",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_ENV_3_A,
"ENV 3 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_ENV_3_D,
"ENV 3 Decay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_ENV_3_S,
"ENV 3 Sustain",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_ENV_3_R,
"ENV 3 Release",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_VCA_ENV_R,
"VCA Release",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_VCF_TYPE,
"VCF type",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VCF_NUM_FILTERTYPES-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_ORDER,
"VCF order",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VCF_NUM_FILTERORDER-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_F,
"VCF Cutoff",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/FILTER_F_MIN, /*pcenter*/-1, /*max*/FILTER_F_MAX, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_Q,
"VCF Res",
/*Base*/10, /*kexp*/2.0, /*scenter*/0.0, /*min*/FILTER_Q_MIN, /*pcenter*/-1, /*max*/FILTER_Q_MAX, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_ENV_AMT,
"VCF Env amt",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_F_AMT_0,
"VCF Cutoff amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_F_AMT_1,
"VCF Cutoff amt 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_F_SRC_0,
"VCF Cutoff src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_F_SRC_1,
"VCF Cutoff src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_F_SRC_OP,
"VCF Cutoff src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_Q_AMT_0,
"VCF Resonance amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_Q_AMT_1,
"VCF Resonance amt 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_Q_SRC_0,
"VCF Resonance src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_Q_SRC_1,
"VCF Resonance src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_Q_SRC_OP,
"VCF Resonance src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_SPEED,
"LFO 1 speed",
/*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/20.0, /*interval*/0.01
},
{
SYNTH_PARAM_LFO_1_SPEED,
"LFO 2 speed",
/*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/20.0, /*interval*/0.01
},
{
SYNTH_PARAM_LFO_2_SPEED,
"LFO 3 speed",
/*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/20.0, /*interval*/0.01
},
{
SYNTH_PARAM_LFO_3_SPEED,
"LFO 4 speed",
/*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/20.0, /*interval*/0.01
},
{
SYNTH_PARAM_LFO_0_SMOOTH,
"LFO 1 smooth",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_1_SMOOTH,
"LFO 2 smooth",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_2_SMOOTH,
"LFO 3 smooth",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_3_SMOOTH,
"LFO 4 smooth",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_0_DELAY,
"LFO 1 Delay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_LFO_1_DELAY,
"LFO 2 Delay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_LFO_2_DELAY,
"LFO 3 Delay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_LFO_3_DELAY,
"LFO 4 Delay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_ATTACK,
"LFO 1 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_LFO_1_ATTACK,
"LFO 2 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_LFO_2_ATTACK,
"LFO 3 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_LFO_3_ATTACK,
"LFO 4 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_SHAPE,
"LFO 1 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_1_SHAPE,
"LFO 2 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_2_SHAPE,
"LFO 3 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_3_SHAPE,
"LFO 4 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_MODE,
"LFO 1 mode",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_1_MODE,
"LFO 2 mode",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_2_MODE,
"LFO 3 mode",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_3_MODE,
"LFO 4 mode",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_SYNC,
"LFO 1 sync",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_1_SYNC,
"LFO 2 sync",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_2_SYNC,
"LFO 3 sync",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_3_SYNC,
"LFO 4 sync",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_SYMMETRY,
"LFO 1 symmetry",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_1_SYMMETRY,
"LFO 2 symmetry",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_2_SYMMETRY,
"LFO 3 symmetry",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_3_SYMMETRY,
"LFO 4 symmetry",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
}
};
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
synth_float_t quantizeParam(param_info_t *pObj, synth_float_t p)
{
synth_float_t k, pq;
if (pObj->pinterval == 0)
return p;
k = (synth_float_t)1/(pObj->pinterval - 0);
if (p < 0)
pq = ((int)(p*k - 0.5))*pObj->pinterval;
else
pq = ((int)(p*k + 0.5))*pObj->pinterval;
return pq;
}
synth_float_t clampParam(param_info_t *pObj, synth_float_t p)
{
return (synth_float_t)min(pObj->pmax, max(pObj->pmin, quantizeParam(pObj, p)));
}
synth_float_t toParam(param_info_t *pObj, synth_float_t s)
{
synth_float_t p, pcenter;
synth_float_t pmax, pmin, base, kexp, scenter;
pmax = pObj->pmax;
pmin = pObj->pmin;
if (pmin == pmax)
pmax += 1E-9;
base = pObj->base;
kexp = pObj->kexp;
if (kexp == 0)
kexp = 1E-9;
scenter = pObj->scenter;
pcenter = pObj->pcenter;
if ((pcenter < pmin) || (pcenter > pmax))
pcenter = pmax*scenter + pmin*(1-scenter);
s = (synth_float_t)min(1, max(0, s));
if (s < scenter)
{
if (base == 1)
{
// pcenter-(pcenter-pmin)*(scenter-s)/scenter;
p = pcenter-(pcenter-pmin)*(scenter-s)/scenter;
}
else
{
// pcenter-(pcenter-pmin)*(B^(k*(scenter-s)/scenter)-1)/(B^k-1);
p = pcenter-(pcenter-pmin)*(pow(base,kexp*(scenter-s)/scenter)-1)/(pow(base,kexp)-1);
}
}
else
{
if (base == 1)
{
// pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter);
p = pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter);
}
else
{
// pcenter+(pmax-pcenter)*(B^(k*(-scenter+s)/(1-scenter))-1)/(B^k-1);
p = pcenter+(pmax-pcenter)*(pow(base,kexp*(-scenter+s)/(1-scenter))-1)/(pow(base,kexp)-1);
}
}
return quantizeParam(pObj, p);
}
synth_float_t toSlider(param_info_t *pObj, synth_float_t p)
{
synth_float_t s, pcenter;
synth_float_t pmax, pmin, base, kexp, scenter;
pmax = pObj->pmax;
pmin = pObj->pmin;
if (pmin == pmax)
pmax += 1E-9;
base = pObj->base;
kexp = pObj->kexp;
if (kexp == 0)
kexp = 1E-9;
scenter = pObj->scenter;
pcenter = pObj->pcenter;
if ((pcenter < pmin) || (pcenter > pmax))
pcenter = pmax*scenter + pmin*(1-scenter);
p = clampParam(pObj, p);
if (p < pcenter)
{
if (base == 1)
{
// (-pmin+p)*scenter/(pcenter-pmin);
s = (-pmin+p)*scenter/(pcenter-pmin);
}
else
{
// scenter*(log(B)*k-log(-(-pcenter*B^k+pmin+p*B^k-p)/(pcenter-pmin)))/log(B)/k;
s = scenter*(log(base)*kexp-log(-(-pcenter*pow(base,kexp)+pmin+p*pow(base,kexp)-p)/(pcenter-pmin)))/log(base)/kexp;
}
}
else
{
if (base == 1)
{
// (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter);
s = (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter);
}
else
{
// (k*log(B)*scenter+log(-(-pcenter*B^k+pmax+p*B^k-p)/(-pmax+pcenter))-log(-(-pcenter*B^k+pmax+p*B^k-p)/(-pmax+pcenter))*scenter)/log(B)/k;
s = (kexp*log(base)*scenter+log(-(-pcenter*pow(base,kexp)+pmax+p*pow(base,kexp)-p)/(-pmax+pcenter))-log(-(-pcenter*pow(base,kexp)+pmax+p*pow(base,kexp)-p)/(-pmax+pcenter))*scenter)/log(base)/kexp;
}
}
return s;
}
void paramInfoInit(param_info_t *pObj, UINT32 id, char *pName)
{
pObj->id = id;
pObj->pName = NULL;
if (pName)
{
pObj->pName = (char*)malloc(strlen(pName)+1);
memcpy(pObj->pName, pName, strlen(pName)+1);
}
pObj->base = 1;
pObj->kexp = 1;
pObj->scenter = 0;
pObj->pmin = 0;
pObj->pcenter = 0;
pObj->pmax = 1;
pObj->pinterval = 0;
}
void paramInfoFree(param_info_t *pObj)
{
if (pObj->pName)
free(pObj->pName);
}
void paramInfoSetPMIN(param_info_t *pObj, synth_float_t value)
{
pObj->pmin = value;
}
void paramInfoSetPMAX(param_info_t *pObj, synth_float_t value)
{
pObj->pmax = value;
}
void paramInfoSet(param_info_t *pObj,
synth_float_t base,
synth_float_t kexp,
synth_float_t scenter,
synth_float_t pmin,
synth_float_t pcenter,
synth_float_t pmax,
synth_float_t pinterval)
{
pObj->base = base;
pObj->kexp = kexp;
pObj->scenter = scenter;
pObj->pmin = pmin;
pObj->pcenter = pcenter;
pObj->pmax = pmax;
pObj->pinterval = pinterval;
}
void paramInfoCopy(param_info_t *pDst, param_info_t *pSrc)
{
pDst->base = pSrc->base;
pDst->kexp = pSrc->kexp;
pDst->scenter = pSrc->scenter;
pDst->pmin = pSrc->pmin;
pDst->pcenter = pSrc->pcenter;
pDst->pmax = pSrc->pmax;
pDst->pinterval = pSrc->pinterval;
}
param_info_t* getParamInfo(UINT32 type)
{
UINT32 i;
if (type >= SYNTH_NUM_PARAMS)
return NULL;
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
if (param_info[i].id == type)
break;
}
if (i == SYNTH_NUM_PARAMS)
return NULL;
return (param_info_t*)&param_info[i];
}
+188
View File
@@ -0,0 +1,188 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _PARAM_SCALE_H_
#define _PARAM_SCALE_H_
#include "synth_types.h"
enum
{
SYNTH_PARAM_VOLUME = 0,
SYNTH_PARAM_TUNE,
SYNTH_PARAM_TOTAL_NUM_VOICES,
SYNTH_PARAM_VOICE_PAN_SPREAD,
SYNTH_PARAM_HUMANIZE_ENABLE,
SYNTH_PARAM_MONOPHONIC_ENABLE,
SYNTH_PARAM_MONOPHONIC_RETRIGGER_ENABLE,
SYNTH_PARAM_UNISONO_ENABLE,
SYNTH_PARAM_UNISONO_NUM_VOICES,
SYNTH_PARAM_HUMANIZE_VAR_VCO,
SYNTH_PARAM_HUMANIZE_VAR_VCF,
SYNTH_PARAM_HUMANIZE_VAR_ENV,
SYNTH_PARAM_PORTAMENTO_TIME,
SYNTH_PARAM_OSC_0_RESTART_ON_TRIGGER,
SYNTH_PARAM_OSC_1_RESTART_ON_TRIGGER,
SYNTH_PARAM_OSC_0_ENABLE,
SYNTH_PARAM_OSC_1_ENABLE,
SYNTH_PARAM_OSC_0_LEVEL,
SYNTH_PARAM_OSC_1_LEVEL,
SYNTH_PARAM_OSC_0_DUTYCYCLE,
SYNTH_PARAM_OSC_1_DUTYCYCLE,
SYNTH_PARAM_OSC_0_DETUNE,
SYNTH_PARAM_OSC_1_DETUNE,
SYNTH_PARAM_OSC_0_TRANSPOSE,
SYNTH_PARAM_OSC_1_TRANSPOSE,
SYNTH_PARAM_OSC_0_PB_RANGE_MIN,
SYNTH_PARAM_OSC_1_PB_RANGE_MIN,
SYNTH_PARAM_OSC_0_PB_RANGE_MAX,
SYNTH_PARAM_OSC_1_PB_RANGE_MAX,
SYNTH_PARAM_OSC_0_WAVEFORM,
SYNTH_PARAM_OSC_1_WAVEFORM,
SYNTH_PARAM_OSC_0_FM_AMT_0,
SYNTH_PARAM_OSC_1_FM_AMT_0,
SYNTH_PARAM_OSC_0_FM_AMT_1,
SYNTH_PARAM_OSC_1_FM_AMT_1,
SYNTH_PARAM_OSC_0_FM_SRC_0,
SYNTH_PARAM_OSC_1_FM_SRC_0,
SYNTH_PARAM_OSC_0_FM_SRC_1,
SYNTH_PARAM_OSC_1_FM_SRC_1,
SYNTH_PARAM_OSC_0_FM_SRC_OP,
SYNTH_PARAM_OSC_1_FM_SRC_OP,
SYNTH_PARAM_OSC_0_AM_AMT_0,
SYNTH_PARAM_OSC_1_AM_AMT_0,
SYNTH_PARAM_OSC_0_AM_AMT_1,
SYNTH_PARAM_OSC_1_AM_AMT_1,
SYNTH_PARAM_OSC_0_AM_SRC_0,
SYNTH_PARAM_OSC_1_AM_SRC_0,
SYNTH_PARAM_OSC_0_AM_SRC_1,
SYNTH_PARAM_OSC_1_AM_SRC_1,
SYNTH_PARAM_OSC_0_AM_SRC_OP,
SYNTH_PARAM_OSC_1_AM_SRC_OP,
SYNTH_PARAM_OSC_0_PWM_AMT_0,
SYNTH_PARAM_OSC_1_PWM_AMT_0,
SYNTH_PARAM_OSC_0_PWM_AMT_1,
SYNTH_PARAM_OSC_1_PWM_AMT_1,
SYNTH_PARAM_OSC_0_PWM_SRC_0,
SYNTH_PARAM_OSC_1_PWM_SRC_0,
SYNTH_PARAM_OSC_0_PWM_SRC_1,
SYNTH_PARAM_OSC_1_PWM_SRC_1,
SYNTH_PARAM_OSC_0_PWM_SRC_OP,
SYNTH_PARAM_OSC_1_PWM_SRC_OP,
SYNTH_PARAM_NOISE_ENABLE,
SYNTH_PARAM_NOISE_LEVEL,
SYNTH_PARAM_NOISE_SHAPE,
SYNTH_PARAM_VCA_ENV_AMT,
SYNTH_PARAM_VCA_AM_AMT_0,
SYNTH_PARAM_VCA_AM_SRC_0,
SYNTH_PARAM_VCA_PAN_AMT_0,
SYNTH_PARAM_VCA_PAN_SRC_0,
SYNTH_PARAM_ENV_0_A, SYNTH_PARAM_VCF_ENV_A = SYNTH_PARAM_ENV_0_A,
SYNTH_PARAM_ENV_1_A, SYNTH_PARAM_VCA_ENV_A = SYNTH_PARAM_ENV_1_A,
SYNTH_PARAM_ENV_2_A,
SYNTH_PARAM_ENV_3_A,
SYNTH_PARAM_ENV_0_D, SYNTH_PARAM_VCF_ENV_D = SYNTH_PARAM_ENV_0_D,
SYNTH_PARAM_ENV_1_D, SYNTH_PARAM_VCA_ENV_D = SYNTH_PARAM_ENV_1_D,
SYNTH_PARAM_ENV_2_D,
SYNTH_PARAM_ENV_3_D,
SYNTH_PARAM_ENV_0_S, SYNTH_PARAM_VCF_ENV_S = SYNTH_PARAM_ENV_0_S,
SYNTH_PARAM_ENV_1_S, SYNTH_PARAM_VCA_ENV_S = SYNTH_PARAM_ENV_1_S,
SYNTH_PARAM_ENV_2_S,
SYNTH_PARAM_ENV_3_S,
SYNTH_PARAM_ENV_0_R, SYNTH_PARAM_VCF_ENV_R = SYNTH_PARAM_ENV_0_R,
SYNTH_PARAM_ENV_1_R, SYNTH_PARAM_VCA_ENV_R = SYNTH_PARAM_ENV_1_R,
SYNTH_PARAM_ENV_2_R,
SYNTH_PARAM_ENV_3_R,
SYNTH_PARAM_VCF_TYPE,
SYNTH_PARAM_VCF_ORDER,
SYNTH_PARAM_VCF_F,
SYNTH_PARAM_VCF_Q,
SYNTH_PARAM_VCF_ENV_AMT,
SYNTH_PARAM_VCF_F_AMT_0,
SYNTH_PARAM_VCF_F_AMT_1,
SYNTH_PARAM_VCF_F_SRC_0,
SYNTH_PARAM_VCF_F_SRC_1,
SYNTH_PARAM_VCF_F_SRC_OP,
SYNTH_PARAM_VCF_Q_AMT_0,
SYNTH_PARAM_VCF_Q_AMT_1,
SYNTH_PARAM_VCF_Q_SRC_0,
SYNTH_PARAM_VCF_Q_SRC_1,
SYNTH_PARAM_VCF_Q_SRC_OP,
SYNTH_PARAM_LFO_0_SPEED,
SYNTH_PARAM_LFO_1_SPEED,
SYNTH_PARAM_LFO_2_SPEED,
SYNTH_PARAM_LFO_3_SPEED,
SYNTH_PARAM_LFO_0_SMOOTH,
SYNTH_PARAM_LFO_1_SMOOTH,
SYNTH_PARAM_LFO_2_SMOOTH,
SYNTH_PARAM_LFO_3_SMOOTH,
SYNTH_PARAM_LFO_0_DELAY,
SYNTH_PARAM_LFO_1_DELAY,
SYNTH_PARAM_LFO_2_DELAY,
SYNTH_PARAM_LFO_3_DELAY,
SYNTH_PARAM_LFO_0_ATTACK,
SYNTH_PARAM_LFO_1_ATTACK,
SYNTH_PARAM_LFO_2_ATTACK,
SYNTH_PARAM_LFO_3_ATTACK,
SYNTH_PARAM_LFO_0_SHAPE,
SYNTH_PARAM_LFO_1_SHAPE,
SYNTH_PARAM_LFO_2_SHAPE,
SYNTH_PARAM_LFO_3_SHAPE,
SYNTH_PARAM_LFO_0_MODE,
SYNTH_PARAM_LFO_1_MODE,
SYNTH_PARAM_LFO_2_MODE,
SYNTH_PARAM_LFO_3_MODE,
SYNTH_PARAM_LFO_0_SYNC,
SYNTH_PARAM_LFO_1_SYNC,
SYNTH_PARAM_LFO_2_SYNC,
SYNTH_PARAM_LFO_3_SYNC,
SYNTH_PARAM_LFO_0_SYMMETRY,
SYNTH_PARAM_LFO_1_SYMMETRY,
SYNTH_PARAM_LFO_2_SYMMETRY,
SYNTH_PARAM_LFO_3_SYMMETRY,
SYNTH_NUM_PARAMS
};
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
typedef struct _sparam_info_t
{
UINT32 id;
char *pName;
synth_float_t base, kexp, scenter, pmin, pcenter, pmax, pinterval;
} param_info_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void paramInfoInit(param_info_t *pObj, UINT32 id, char *pName);
void paramInfoFree(param_info_t *pObj);
void paramInfoSetPMIN(param_info_t *pObj, synth_float_t value);
void paramInfoSetPMAX(param_info_t *pObj, synth_float_t value);
void paramInfoSet(param_info_t *pObj,
synth_float_t base,
synth_float_t kexp,
synth_float_t scenter,
synth_float_t pmin,
synth_float_t pcenter,
synth_float_t pmax,
synth_float_t pinterval);
void paramInfoCopy(param_info_t *pDst, param_info_t *pSrc);
synth_float_t clampParam(param_info_t *pObj, synth_float_t p);
synth_float_t toParam(param_info_t *pObj, synth_float_t s);
synth_float_t toSlider(param_info_t *pObj, synth_float_t p);
param_info_t* getParamInfo(UINT32 type);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _PARAM_SCALE_H_
+97
View File
@@ -0,0 +1,97 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "synth_defs.h"
#include "sine.h"
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Sine_Init(sine_gen_t *pObj, synth_float_t fs)
{
Sine_SetFS(pObj, fs);
Sine_Prepare(pObj);
}
void Sine_Free(sine_gen_t *pObj)
{
}
void Sine_SetFS(sine_gen_t *pObj, synth_float_t fs)
{
pObj->fs = SINE_OVERSAMPLING*fs;
pObj->pitch = -1;
}
void Sine_Reset(sine_gen_t *pObj, synth_float_t phase)
{
pObj->y[0] = cos(2*pi*phase);
pObj->y[1] = sin(2*pi*phase);
pObj->fscale = 1;
}
void Sine_Start(sine_gen_t *pObj)
{
pObj->pitch = -1;
pObj->CV_fm = -1;
}
void Sine_Prepare(sine_gen_t *pObj)
{
Sine_Reset(pObj, (synth_float_t)rand()/RAND_MAX);
}
void Sine_Update(sine_gen_t *pObj)
{
synth_float_t freq;
freq = pObj->fscale * pObj->pitch;
pObj->b = 2.0 * sin(freq*pi / pObj->fs);
}
synth_float_t Sine_Process_Scalar(sine_gen_t *pObj, synth_float_t pitch, synth_float_t CV_fm)
{
int i;
synth_float_t a, phi;
// ToDo: amplitude drift correction
// y[0]^2 + y[1]^2 = a;
if (pObj->CV_fm != CV_fm)
{
pObj->CV_fm = CV_fm;
pObj->fscale = (synth_float_t)pow((synth_float_t)2, CV_fm);
Sine_Update(pObj);
}
if (pObj->pitch != pitch)
{
pObj->pitch = pitch;
Sine_Update(pObj);
}
for (i=0; i < SINE_OVERSAMPLING; i++)
{
pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1];
pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0];
}
a = pObj->y[0]*pObj->y[0] + pObj->y[1]*pObj->y[1];
if (fabs(a - 1) > 0.5)
{
phi = atan2(pObj->y[0], pObj->y[1]);
pObj->y[0] = sin(phi);
pObj->y[1] = cos(phi);
}
return -pObj->y[0];
}
+43
View File
@@ -0,0 +1,43 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _SINE_H_
#define _SINE_H_
#include "synth_defs.h"
#define SINE_OVERSAMPLING 3
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
typedef struct _ssine_gen_t
{
synth_float_t fs, fscale, pitch, CV_fm;
synth_float_t b, y[2];
} sine_gen_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Sine_Init(sine_gen_t *pObj, synth_float_t fs);
void Sine_Free(sine_gen_t *pObj);
void Sine_SetFS(sine_gen_t *pObj, synth_float_t fs);
void Sine_Reset(sine_gen_t *pObj, synth_float_t phi);
void Sine_Prepare(sine_gen_t *pObj);
void Sine_Start(sine_gen_t *pObj);
void Sine_Update(sine_gen_t *pObj);
synth_float_t Sine_Process_Scalar(sine_gen_t *pObj, synth_float_t pitch, synth_float_t CV_fm);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _SINE_H_
+129
View File
@@ -0,0 +1,129 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "smooth.h"
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Smooth_Update(smooth_t *pObj)
{
pObj->a_r = (synth_float_t)1/(pObj->fs*pObj->T_r*SMOOTH_KE);
pObj->a_f = (synth_float_t)1/(pObj->fs*pObj->T_f);
}
void Smooth_Init(smooth_t *pObj, synth_float_t fs, synth_float_t T_r, synth_float_t T_f, synth_float_t inital_value)
{
pObj->fs = fs;
pObj->T_r = T_r;
pObj->T_f = T_f;
pObj->y = inital_value;
Smooth_Update(pObj);
}
void Smooth_Free(smooth_t *pObj)
{
}
void Smooth_SetValue(smooth_t *pObj, synth_float_t value)
{
pObj->y = value;
}
void Smooth_SetFS(smooth_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
Smooth_Update(pObj);
}
void Smooth_SetT(smooth_t *pObj, synth_float_t T_r, synth_float_t T_f)
{
pObj->T_r = T_r;
pObj->T_f = T_f;
Smooth_Update(pObj);
}
synth_float_t Smooth_ProcessScalar(smooth_t *pObj, synth_float_t x_hard, synth_float_t in)
{
if (pObj->y < x_hard)
pObj->y += pObj->a_r*(x_hard - pObj->y);
else
pObj->y += pObj->a_f*(x_hard - pObj->y);
return pObj->y*in;
}
void Smooth_Process_VV(smooth_t *pObj, synth_float_t x_hard, synth_float_t *pIn, synth_float_t *pOut, UINT32 len)
{
UINT32 i;
if (Smooth_is_settled(pObj, x_hard) && (fabs(x_hard) < 1E-18))
{
for (i = 0; i < len; i++)
{
pOut[i] = 0;
}
return;
}
if (Smooth_is_settled(pObj, x_hard))
{
for (i = 0; i < len; i++)
{
pOut[i] = x_hard*pIn[i];
}
return;
}
for (i = 0; i < len; i++)
{
if (pObj->y < x_hard)
pObj->y += pObj->a_r*(x_hard - pObj->y);
else
pObj->y += pObj->a_f*(x_hard - pObj->y);
pOut[i] = pObj->y*pIn[i];
}
}
void Smooth_Process_V(smooth_t *pObj, synth_float_t x_hard, synth_float_t *pOut, UINT32 len)
{
UINT32 i;
if (Smooth_is_settled(pObj, x_hard) && (fabs(x_hard) < 1E-18))
{
for (i = 0; i < len; i++)
{
pOut[i] = 0;
}
return;
}
if (Smooth_is_settled(pObj, x_hard))
{
for (i = 0; i < len; i++)
{
pOut[i] = x_hard;
}
return;
}
for (i = 0; i < len; i++)
{
if (pObj->y < x_hard)
pObj->y += pObj->a_r*(x_hard - pObj->y);
else
pObj->y += pObj->a_f*(x_hard - pObj->y);
pOut[i] = pObj->y;
}
}
UINT32 Smooth_is_settled(smooth_t *pObj, synth_float_t x_hard)
{
return (fabs(pObj->y - x_hard) < SMOOTH_TOL);
}
+46
View File
@@ -0,0 +1,46 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _SMOOTH_H_
#define _SMOOTH_H_
#include "synth_defs.h"
#define SMOOTH_TOL ((synth_float_t)(1E-4))
#define SMOOTH_KE ((synth_float_t)(1-exp(-1)))
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
typedef struct _ssmooth_t
{
synth_float_t y, fs;
synth_float_t T_r, a_r;
synth_float_t T_f, a_f;
} smooth_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Smooth_Init(smooth_t *pObj, synth_float_t fs, synth_float_t T_r, synth_float_t T_f, synth_float_t inital_value);
void Smooth_Free(smooth_t *pObj);
void Smooth_SetValue(smooth_t *pObj, synth_float_t value);
void Smooth_SetFS(smooth_t *pObj, synth_float_t fs);
void Smooth_SetT(smooth_t *pObj, synth_float_t T_r, synth_float_t T_f);
synth_float_t Smooth_ProcessScalar(smooth_t *pObj, synth_float_t x_hard, synth_float_t in);
void Smooth_Process_VV(smooth_t *pObj, synth_float_t x_hard, synth_float_t *pIn, synth_float_t *pOut, UINT32 len);
void Smooth_Process_V(smooth_t *pObj, synth_float_t x_hard, synth_float_t *pOut, UINT32 len);
UINT32 Smooth_is_settled(smooth_t *pObj, synth_float_t x_hard);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _SMOOTH_H_
+33
View File
@@ -0,0 +1,33 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <windows.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void SynthDebug(char *fmtstr, ...)
{
#ifndef SYNTH_DEBUG
/* Empty body, so a good compiler will optimise calls
to pmesg away */
#else
char buf[1024];
va_list args;
va_start(args, fmtstr);
vsprintf(buf, fmtstr, args);
va_end(args);
OutputDebugString(buf);
#endif /* SYNTH_DEBUG */
}
+79
View File
@@ -0,0 +1,79 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _SYNTH_DEFS_H_
#define _SYNTH_DEFS_H_
#include "synth_types.h"
// --------------------------------------------------------------
// Defs
// --------------------------------------------------------------
#define GAIN_EPSILON 10.0
#define MAX_POLYPHONY 256
#define SYNTH_BANDWIDTH 0.833
#define NUM_PROGRAMS 64
#define NUM_FREQS 128
#define NUM_MIDI_CONTROLLERS 128
#define VOICE_NUM_OSC 2
#define VOICE_NUM_LFO 4
#define VOICE_NUM_ENV 4
#define FILTER_ORDER 2
#define FILTER_SWEEP_BASE ((synth_float_t)10)
#define FILTER_MAX_ORDER 4
#define FILTER_F_MIN ((synth_float_t)18)
#define FILTER_F_MAX ((synth_float_t)18000)
#define FILTER_Q_MIN 0.7
#define FILTER_Q_MAX 100
#define FILTER_TABLE_SIZE (4096)
#define FILTER_INTEROLATION_ORDER 1
#define BLIT_NUM_HARM_MAX (900)
#define BLIT_TABLE_SIZE_MIN (1024)
#define BLIT_TABLE_SIZE_MAX (4096)
#define BLIT_TABLE_OVERSAMPLING (4)
#define BLIT_INTEROLATION_ORDER (2)
#define SYNTH_LIMITER_RISE_TIME 0.001 //s
#define SYNTH_LIMITER_FALL_TIME 1.000 //s
#define SYNTH_LIMITER_THRESHOLD 3 // dbFS
#define SYNTH_MAX_BUFSIZE 8192
#ifndef pi
#define pi 3.1415926535897932384626433832795
#define pi_mult_2 (2*pi)
#define pi_div_2 (0.5*pi)
#endif
#if defined(__cplusplus)
extern "C" {
#endif
void SynthDebug(char *fmtstr, ...);
#if defined(__cplusplus)
}
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#include "voice.h"
#include "vco.h"
#include "noise.h"
#include "smooth.h"
#include "vcf.h"
#include "lfo.h"
#include "env.h"
#include "param_scale.h"
#endif // _SYNTH_DEFS_H_
+38
View File
@@ -0,0 +1,38 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _SYNTH_TYPES_H_
#define _SYNTH_TYPES_H_
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
#define synth_float_t double
#ifndef UINT32
#define UINT32 unsigned int
#endif
#ifndef INT32
#define INT32 signed int
#endif
#ifndef UINT16
#define UINT16 unsigned short
#endif
#ifndef INT16
#define INT16 signed short
#endif
//#define SYNTH_DOUBLE_PRECISION 1
//typedef struct _ssynth_gbl_data_t
//{
// synth_float_t **osc_ppH;
// iir_coef_t **ppIIR_coef;
//} synth_gbl_data_t;
//extern synth_gbl_data_t g_synth_data;
#endif // _SYNTH_TYPES_H_
+485
View File
@@ -0,0 +1,485 @@
/*************************************************************************/
/* vcf.c */
/*************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "vcf.h"
#include "fast_trig/fast_trig.h"
/*************************************************************************/
/* Global Variables */
/*************************************************************************/
/******************************************************************************/
void VCF_Init(vcf_t *pObj, UINT32 id, vcf_common_t *pCom, synth_float_t fs)
{
pObj->pCom = pCom;
pObj->id = id;
pObj->fs = fs;
if (id == 0)
{
VCF_ModInit(pObj);
}
pObj->pOut = NULL;
pObj->pCoef = NULL;
pObj->bufsize = 0;
VCF_SetType(pObj, VCF_FILTERTYPE_LOWPASS);
VCF_SetOrder(pObj, 4);
pObj->req_filter_update = 0;
VCF_clear_state(pObj);
VCF_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
VCF_FilterParamUpdate(pObj);
VCF_SetF(pObj, 20000);
VCF_SetQ(pObj, 1);
}
void VCF_Free(vcf_t *pObj)
{
VCF_SetBufsize(pObj, 0);
if (pObj->id == 0)
{
VCF_ModFree(pObj);
}
}
void VCF_ModInit(vcf_t *pObj)
{
vcf_common_t *pCom = pObj->pCom;
pCom->pLUT_cos = (synth_float_t*)malloc(FILTER_TABLE_SIZE*sizeof(synth_float_t));
pCom->pLUT_sin = (synth_float_t*)malloc(FILTER_TABLE_SIZE*sizeof(synth_float_t));
}
void VCF_ModFree(vcf_t *pObj)
{
vcf_common_t *pCom = pObj->pCom;
free(pCom->pLUT_cos);
free(pCom->pLUT_sin);
}
void VCF_LUT_gen(vcf_t *pObj)
{
int i;
synth_float_t cv, omega;
vcf_common_t *pCom = pObj->pCom;
for (i=0; i < FILTER_TABLE_SIZE; i++)
{
cv = (synth_float_t)i/(FILTER_TABLE_SIZE-1);
omega = VCF_cv2omega(pObj, cv);
pCom->pLUT_cos[i] = cos(pi*omega);
pCom->pLUT_sin[i] = sin(pi*omega);
}
}
void VCF_FilterParamUpdate(vcf_t *pObj)
{
pObj->omega_max = 2*FILTER_F_MAX/pObj->fs;
pObj->omega_min = 2*FILTER_F_MIN/pObj->fs;
pObj->num_octaves = log(FILTER_F_MAX/FILTER_F_MIN)/log(FILTER_SWEEP_BASE);
if (pObj->id == 0)
{
VCF_LUT_gen(pObj);
}
}
synth_float_t VCF_LUT_get_cos(vcf_t *pObj, synth_float_t cv)
{
int ni, ni_next;
synth_float_t n, nf;
vcf_common_t *pCom = pObj->pCom;
n = min(1, max(0, cv))*(FILTER_TABLE_SIZE-1);
ni = (int)n;
nf = n - (synth_float_t)ni;
ni_next = min(FILTER_TABLE_SIZE-1, ni+1);
return (pCom->pLUT_cos[ni_next] - pCom->pLUT_cos[ni])*nf + pCom->pLUT_cos[ni];
}
synth_float_t VCF_LUT_get_sin(vcf_t *pObj, synth_float_t cv)
{
int ni, ni_next;
synth_float_t n, nf;
vcf_common_t *pCom = pObj->pCom;
n = min(1, max(0, cv))*(FILTER_TABLE_SIZE-1);
ni = (int)n;
nf = n - (synth_float_t)ni;
ni_next = min(FILTER_TABLE_SIZE-1, ni+1);
return (pCom->pLUT_sin[ni_next] - pCom->pLUT_sin[ni])*nf + pCom->pLUT_sin[ni];
}
void VCF_SetBufsize(vcf_t *pObj, UINT32 size)
{
if (pObj->bufsize == size)
return;
pObj->bufsize = size;
if (pObj->pOut)
free(pObj->pOut);
if (pObj->pCoef)
free(pObj->pCoef);
pObj->pOut = NULL;
pObj->pCoef = NULL;
if (!size)
return;
pObj->pOut = (synth_float_t*)malloc(pObj->bufsize*sizeof(synth_float_t));
pObj->pCoef = (vcf_coef_t*)malloc(pObj->bufsize*sizeof(vcf_coef_t));
pObj->pCoeff_last = pObj->pCoef;
VCF_Coeff_update(pObj);
}
void VCF_SetFS(vcf_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
VCF_FilterParamUpdate(pObj);
pObj->req_filter_update = 1;
}
void VCF_SetF(vcf_t *pObj, synth_float_t f)
{
if (f > pObj->fs/2)
f = FILTER_F_MAX;
if (f < FILTER_F_MIN)
f = FILTER_F_MIN;
if (f < 0)
f = FILTER_F_MIN;
pObj->cv_f_bias = VCF_omega2cv(pObj, 2*f/pObj->fs);
pObj->req_filter_update = 1;
}
void VCF_SetQ(vcf_t *pObj, synth_float_t q)
{
pObj->cv_q_bias = max(FILTER_Q_MIN, q);
pObj->req_filter_update = 1;
}
void VCF_SetType(vcf_t *pObj, UINT32 type)
{
pObj->type = type;
VCF_SetQ(pObj, pObj->cv_q_bias);
VCF_Coeff_update(pObj);
}
synth_float_t IIRCalcQp(unsigned p, unsigned N)
{
return 1.0f/(synth_float_t)(2*sin(pi*(2*p-1)/(2*N)));
}
void VCF_SetOrder(vcf_t *pObj, UINT32 order)
{
UINT32 p;
if (pObj->order == order)
return;
if (order % 2)
return;
if (order > FILTER_MAX_ORDER)
return;
pObj->order = order;
pObj->num_sections = pObj->order/2;
for(p=0; p < pObj->num_sections; p++)
{
pObj->pQP_inv[p] = (synth_float_t)1.0/IIRCalcQp(p+1, pObj->order);
}
VCF_clear_state(pObj);
VCF_SetQ(pObj, pObj->cv_q_bias);
VCF_Coeff_update(pObj);
}
void VCF_Coeff_update(vcf_t *pObj)
{
pObj->req_filter_update = 1;
}
void VCF_clear_state(vcf_t *pObj)
{
UINT32 p;
for(p=0; p < pObj->num_sections; p++)
{
pObj->pState[p].xn1 = 0;
pObj->pState[p].xn2 = 0;
pObj->pState[p].yn1 = 0;
pObj->pState[p].yn2 = 0;
}
VCF_Coeff_update(pObj);
}
synth_float_t VCF_omega2cv(vcf_t *pObj, synth_float_t omega)
{
synth_float_t cv;
cv = log(omega/pObj->omega_min)/(pObj->num_octaves * log(FILTER_SWEEP_BASE));
return min(1, max(0, cv));
}
synth_float_t VCF_cv2omega(vcf_t *pObj, synth_float_t cv)
{
synth_float_t omega;
omega = pObj->omega_min*pow(FILTER_SWEEP_BASE, pObj->num_octaves*min(1, max(0, cv)));
return omega;
}
void VCF_CalcCoeff_LPF(vcf_t *pObj, vcf_coef_t *pCoeff, synth_float_t *pCV_f, synth_float_t *pCV_q, UINT32 len)
{
synth_float_t a0_inv;
synth_float_t alpha, ks, kc, Q_inv, q, cv;
unsigned p, n, filter_changed;
ks = 0;
kc = 0;
Q_inv = 0;
for(n=0; n < len; n++)
{
filter_changed = pObj->req_filter_update;
if (fabs(pObj->cv_f_last - pCV_f[n]) > FILTER_RECALC_F_THRESH)
filter_changed = 1;
if (fabs(pObj->cv_q_last - pCV_q[n]) > FILTER_RECALC_Q_THRESH)
filter_changed = 1;
if (filter_changed)
{
pObj->req_filter_update = 0;
pObj->cv_f_last = pCV_f[n];
cv = pObj->cv_f_bias + pCV_f[n];
ks = VCF_LUT_get_sin(pObj, cv);
kc = VCF_LUT_get_cos(pObj, cv);
q = min(FILTER_Q_MAX, max(FILTER_Q_MIN, pObj->cv_q_bias + FILTER_Q_MAX*pCV_q[n]));
pObj->cv_q_last = q;
if (pObj->order == 2)
q *= q;
Q_inv = (synth_float_t)1.0/q;
pObj->pCoeff_last = pCoeff;
}
for(p=0; p < pObj->num_sections; p++)
{
if (filter_changed)
{
alpha = 0.5f*ks * Q_inv * pObj->pQP_inv[p];
a0_inv = (synth_float_t)1.0/(1 + alpha);
(*pCoeff).ak1 = -2.0f*kc *a0_inv;
(*pCoeff).ak2 = (1 - alpha) *a0_inv;
(*pCoeff).bk1 = (1 - kc) *a0_inv;
(*pCoeff).bk0 = 0.5f*(1 - kc) *a0_inv;
(*pCoeff).bk2 = (*pCoeff).bk0;
}
else
{
*pCoeff = pObj->pCoeff_last[p];
}
pCoeff++;
}
}
}
void VCF_CalcCoeff_HPF(vcf_t *pObj, vcf_coef_t *pCoeff, synth_float_t *pCV_f, synth_float_t *pCV_q, UINT32 len)
{
synth_float_t a0_inv;
synth_float_t alpha, ks, kc, Q_inv, q, cv;
unsigned p, n, filter_changed;
ks = 0;
kc = 0;
Q_inv = 0;
for(n=0; n < len; n++)
{
filter_changed = pObj->req_filter_update;
if (fabs(pObj->cv_f_last - pCV_f[n]) > FILTER_RECALC_F_THRESH)
filter_changed = 1;
if (fabs(pObj->cv_q_last - pCV_q[n]) > FILTER_RECALC_Q_THRESH)
filter_changed = 1;
if (filter_changed)
{
pObj->req_filter_update = 0;
pObj->cv_f_last = pCV_f[n];
cv = pObj->cv_f_bias + pCV_f[n];
ks = VCF_LUT_get_sin(pObj, cv);
kc = VCF_LUT_get_cos(pObj, cv);
q = min(FILTER_Q_MAX, max(FILTER_Q_MIN, pObj->cv_q_bias + FILTER_Q_MAX*pCV_q[n]));
pObj->cv_q_last = q;
if (pObj->order == 2)
q *= q;
Q_inv = (synth_float_t)1.0/q;
pObj->pCoeff_last = pCoeff;
}
for(p=0; p < pObj->num_sections; p++)
{
if (filter_changed)
{
alpha = 0.5f*ks * Q_inv * pObj->pQP_inv[p];
a0_inv = (synth_float_t)1.0/(1 + alpha);
(*pCoeff).ak1 = -2.0f*kc *a0_inv;
(*pCoeff).ak2 = (1 - alpha) *a0_inv;
(*pCoeff).bk1 = - (1 + kc) *a0_inv;
(*pCoeff).bk0 = 0.5f*(1 + kc) *a0_inv;
(*pCoeff).bk2 = (*pCoeff).bk0;
}
else
{
*pCoeff = pObj->pCoeff_last[p];
}
pCoeff++;
}
}
}
void VCF_CalcCoeff_BPF(vcf_t *pObj, vcf_coef_t *pCoeff, synth_float_t *pCV_f, synth_float_t *pCV_q, UINT32 len)
{
synth_float_t a0_inv;
synth_float_t alpha, ks, kc, Q_inv, q, cv;
unsigned p, n, filter_changed;
ks = 0;
kc = 0;
Q_inv = 0;
for(n=0; n < len; n++)
{
filter_changed = pObj->req_filter_update;
if (fabs(pObj->cv_f_last - pCV_f[n]) > FILTER_RECALC_F_THRESH)
filter_changed = 1;
if (fabs(pObj->cv_q_last - pCV_q[n]) > FILTER_RECALC_Q_THRESH)
filter_changed = 1;
if (filter_changed)
{
pObj->req_filter_update = 0;
pObj->cv_f_last = pCV_f[n];
cv = pObj->cv_f_bias + pCV_f[n];
ks = VCF_LUT_get_sin(pObj, cv);
kc = VCF_LUT_get_cos(pObj, cv);
q = min(FILTER_Q_MAX, max(FILTER_Q_MIN, pObj->cv_q_bias + FILTER_Q_MAX*pCV_q[n]));
pObj->cv_q_last = q;
if (pObj->order == 2)
q *= q;
Q_inv = (synth_float_t)1.0/q;
pObj->pCoeff_last = pCoeff;
}
for(p=0; p < pObj->num_sections; p++)
{
if (filter_changed)
{
alpha = 0.5f*ks * Q_inv * pObj->pQP_inv[p];
a0_inv = (synth_float_t)1.0/(1 + alpha);
(*pCoeff).ak1 = -2.0f*kc *a0_inv;
(*pCoeff).ak2 = (1 - alpha) *a0_inv;
(*pCoeff).bk1 = 0;
(*pCoeff).bk0 = 0.5*ks *a0_inv;
(*pCoeff).bk2 = -(*pCoeff).bk0;
}
else
{
*pCoeff = pObj->pCoeff_last[p];
}
pCoeff++;
}
}
}
void VCF_CalcCoeff(vcf_t *pObj, vcf_coef_t *pCoeff, synth_float_t *pFG, synth_float_t *pQ, UINT32 len)
{
switch(pObj->type)
{
case VCF_FILTERTYPE_LOWPASS:
VCF_CalcCoeff_LPF(pObj, pCoeff, pFG, pQ, len);
break;
case VCF_FILTERTYPE_HIGHPASS:
VCF_CalcCoeff_HPF(pObj, pCoeff, pFG, pQ, len);
break;
case VCF_FILTERTYPE_BANDPASS:
VCF_CalcCoeff_BPF(pObj, pCoeff, pFG, pQ, len);
break;
default:
VCF_CalcCoeff_LPF(pObj, pCoeff, pFG, pQ, len);
break;
}
}
synth_float_t* VCF_ProcessDataV(vcf_t *pObj, synth_float_t *pCV_f, synth_float_t *pCV_q, synth_float_t *pX, UINT32 len)
{
synth_float_t xp, yp, *pY;
unsigned i, p;
vcf_state_t *pState = pObj->pState;
vcf_coef_t *pCoeff;
VCF_CalcCoeff(pObj, pObj->pCoef, pCV_f, pCV_q, len);
pCoeff = pObj->pCoef;
yp = 0;
pY = pObj->pOut;
for (i=0; i<len; i++)
{
xp = pX[i];
for (p=0; p < pObj->num_sections; p++)
{
yp = (*pCoeff).bk0*xp
+ (*pCoeff).bk1*pState[p].xn1
+ (*pCoeff).bk2*pState[p].xn2
- (*pCoeff).ak1*pState[p].yn1
- (*pCoeff).ak2*pState[p].yn2;
pCoeff++;
pState[p].yn2 = pState[p].yn1;
pState[p].yn1 = yp;
pState[p].xn2 = pState[p].xn1;
pState[p].xn1 = xp;
xp = yp;
}
pY[i] = yp;
}
return pObj->pOut;
}
+109
View File
@@ -0,0 +1,109 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _FILTER_H_
#define _FILTER_H_
#include "synth_defs.h"
#define FILTER_RECALC_F_THRESH (0.000)
#define FILTER_RECALC_Q_THRESH (0.000)
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
VCF_FILTERTYPE_LOWPASS = 0,
VCF_FILTERTYPE_HIGHPASS,
VCF_FILTERTYPE_BANDPASS,
VCF_NUM_FILTERTYPES
};
enum
{
VCF_FILTERORDER_2 = 0,
VCF_FILTERORDER_4,
VCF_NUM_FILTERORDER
};
typedef struct _svcf_coef_t
{
synth_float_t ak0, ak1, ak2;
synth_float_t bk0, bk1, bk2;
} vcf_coef_t;
typedef struct _svcf_state_t
{
synth_float_t xn1, xn2;
synth_float_t yn1, yn2;
} vcf_state_t;
typedef struct _svcf_common_t
{
synth_float_t *pLUT_cos;
synth_float_t *pLUT_sin;
} vcf_common_t;
typedef struct _svcf_t
{
vcf_common_t *pCom;
UINT32 id;
UINT32 type;
UINT32 order;
UINT32 num_sections;
synth_float_t fs;
vcf_coef_t *pCoef;
vcf_coef_t *pCoeff_last;
vcf_state_t pState[FILTER_MAX_ORDER/2];
synth_float_t pQP_inv[FILTER_MAX_ORDER/2];
synth_float_t *pOut;
synth_float_t cv_f_bias;
synth_float_t cv_q_bias;
synth_float_t cv_f_last;
synth_float_t cv_q_last;
UINT32 req_filter_update;
UINT32 bufsize;
synth_float_t num_octaves;
synth_float_t omega_min;
synth_float_t omega_max;
} vcf_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void VCF_ModInit(vcf_t *pObj);
void VCF_ModFree(vcf_t *pObj);
void VCF_Init(vcf_t *pObj, UINT32 id, vcf_common_t *pCom, synth_float_t fs);
void VCF_Free(vcf_t *pObj);
void VCF_SetBufsize(vcf_t *pObj, UINT32 bufsize);
void VCF_FilterParamUpdate(vcf_t *pObj);
void VCF_Coeff_update(vcf_t *pObj);
void VCF_SetFS(vcf_t *pObj, synth_float_t fs);
void VCF_SetF(vcf_t *pObj, synth_float_t f);
void VCF_SetQ(vcf_t *pObj, synth_float_t q);
void VCF_SetType(vcf_t *pObj, UINT32 type);
void VCF_SetOrder(vcf_t *pObj, UINT32 order);
synth_float_t VCF_cv2omega(vcf_t *pObj, synth_float_t omega);
synth_float_t VCF_omega2cv(vcf_t *pObj, synth_float_t cv);
void VCF_clear_state(vcf_t *pObj);
void VCF_CalcCoeff(vcf_t *pObj, vcf_coef_t *pCoeff, synth_float_t *pCV_f, synth_float_t *pCV_q, UINT32 len);
synth_float_t* VCF_ProcessDataV(vcf_t *pObj, synth_float_t *pCV_f, synth_float_t *pCV_q, synth_float_t *pX, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _FILTER_H_
+209
View File
@@ -0,0 +1,209 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "blit.h"
#include "vco.h"
#include "wavetable.h"
#include "fir/fir2.h"
extern unsigned char _g_wave_rawdata[38400];
extern wt_descr_t _g_wt_descr[WT_NUM_WAVETABLES];
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void VCO_ModInit(vco_common_t *pCom)
{
BLIT_ModInit(&pCom->blit);
}
void VCO_ModFree(vco_common_t *pCom)
{
BLIT_ModFree(&pCom->blit);
}
void VCO_Init(osc_t *pObj, UINT32 id, vco_common_t *pCom, synth_float_t fs)
{
pObj->pCom = pCom;
pObj->id = id;
pObj->fs = fs;
if (pObj->id == 0)
{
VCO_ModInit(pCom);
}
pObj->pOut = NULL;
pObj->bufsize = 0;
VCO_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
pObj->param[OSC_PARAM2_WAVEFORM] = OSC_WAVEFORM_SAWTOOTH;
Sine_Init(&pObj->sine, fs);
BLIT_Init(&pObj->blep, &pCom->blit, fs);
WT_Init(&pObj->wt, id, &pCom->wt, fs);
pObj->impulse = 10;
}
void VCO_Free(osc_t *pObj)
{
Sine_Free(&pObj->sine);
BLIT_Free(&pObj->blep);
WT_Free(&pObj->wt);
VCO_SetBufsize(pObj, 0);
if (pObj->id == 0)
{
VCO_ModFree(pObj->pCom);
}
}
void VCO_SetFS(osc_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
Sine_SetFS(&pObj->sine, fs);
BLIT_SetFS(&pObj->blep, fs);
WT_SetFS(&pObj->wt, fs);
}
void VCO_SetBufsize(osc_t *pObj, UINT32 size)
{
BLIT_SetBufsize(&pObj->blep, size);
if (pObj->bufsize == size)
return;
pObj->bufsize = size;
if (pObj->pOut)
free(pObj->pOut);
pObj->pOut = NULL;
if (!size)
return;
pObj->pOut = (synth_float_t*)malloc(pObj->bufsize*sizeof(synth_float_t));
}
void VCO_Reset(osc_t *pObj, synth_float_t phase)
{
Sine_Reset(&pObj->sine, phase);
BLIT_Reset(&pObj->blep, phase);
WT_Reset(&pObj->wt, phase);
pObj->impulse = 10;
}
void VCO_Start(osc_t *pObj)
{
Sine_Start(&pObj->sine);
BLIT_Start(&pObj->blep);
WT_Start(&pObj->wt);
}
void VCO_Param2Set(osc_t *pObj, UINT32 type, synth_float_t value)
{
UINT32 wt_table;
switch(type)
{
case OSC_PARAM2_WAVEFORM:
if (pObj->param[type] == (UINT32)value)
break;
pObj->param[type] = (UINT32)value;
if ((pObj->param[OSC_PARAM2_WAVEFORM] >= OSC_WAVEFORM_WAVETABLE) && (pObj->param[OSC_PARAM2_WAVEFORM] < (OSC_WAVEFORM_WAVETABLE+WT_NUM_WAVETABLES)))
{
wt_table = (UINT32)(pObj->param[OSC_PARAM2_WAVEFORM]-OSC_WAVEFORM_WAVETABLE);
// WT_Param2Set(&pObj->wt, WT_PARAM2_WAVEFORM, WT_WAVEFORM_REGULAR);
WT_Param2Set(&pObj->wt, WT_PARAM2_WAVEFORM, WT_WAVEFORM_INTERPOLATED);
WT_Param2Set(&pObj->wt, WT_PARAM2_WAVETABLE_ID, wt_table);
}
Sine_Prepare(&pObj->sine);
BLIT_Prepare(&pObj->blep, 1024);
WT_Prepare(&pObj->wt);
break;
case OSC_PARAM2_DUTYCYCLE:
pObj->param[type] = value;
BLIT_SetDutyCycle(&pObj->blep, value);
WT_Param2Set(&pObj->wt, WT_PARAM2_WAVETABLE_ENTRY, value);
break;
default:
break;
}
}
void VCO_ProcessDataV(osc_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, UINT32 *pSyncIn, UINT32 *pSyncOut, UINT32 len)
{
UINT32 i, is_slave;
synth_float_t *pOut;
synth_float_t out;
pOut = pObj->pOut;
is_slave = (pSyncIn != NULL) && (pSyncOut == NULL);
if (pSyncOut)
memset(pSyncOut, 0, len*sizeof(synth_float_t));
// Create output
if (pObj->param[OSC_PARAM2_WAVEFORM] == OSC_WAVEFORM_SAWTOOTH)
{
BLIT_Process_SAW_Vector(&pObj->blep, pPitch, pCV_fm, pSyncIn, pSyncOut, pObj->pOut, len);
}
if (pObj->param[OSC_PARAM2_WAVEFORM] == OSC_WAVEFORM_SQUARE)
{
BLIT_Process_SQR_Vector(&pObj->blep, pPitch, pCV_fm, pCV_pwm, pSyncIn, pSyncOut, pObj->pOut, len);
}
if (pObj->param[OSC_PARAM2_WAVEFORM] == OSC_WAVEFORM_TRIANGLE)
{
BLIT_Process_TRI_Vector(&pObj->blep, pPitch, pCV_fm, pSyncIn, pSyncOut, pObj->pOut, len);
}
if (pObj->param[OSC_PARAM2_WAVEFORM] == OSC_WAVEFORM_SINE)
{
for (i=0; i< len; i++)
{
out = Sine_Process_Scalar(&pObj->sine, pPitch[i], pCV_fm[i]);
if(is_slave && pSyncIn[i])
{
Sine_Reset(&pObj->sine, 0);
}
*(pOut++) = out;
}
}
if (pObj->param[OSC_PARAM2_WAVEFORM] == OSC_WAVEFORM_IMPULSE)
{
for (i=0; i< len; i++)
{
out = pObj->impulse;
pObj->impulse = 0;
*(pOut++) = out;
}
}
if ((pObj->param[OSC_PARAM2_WAVEFORM] >= OSC_WAVEFORM_WAVETABLE) && (pObj->param[OSC_PARAM2_WAVEFORM] < (OSC_WAVEFORM_WAVETABLE+WT_NUM_WAVETABLES)))
{
WT_ProcessDataV(&pObj->wt, pPitch, pCV_fm, pCV_pwm, pObj->pOut, len);
}
}
synth_float_t* VCO_GetProcessBuffer(osc_t *pObj)
{
return pObj->pOut;
}
+83
View File
@@ -0,0 +1,83 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _VCO_H_
#define _VCO_H_
#include "synth_types.h"
#include "noise.h"
#include "sine.h"
#include "blit.h"
#include "wavetable.h"
#define OSC_RECALC_THRESH 0.001f
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
OSC_WAVEFORM_SAWTOOTH,
OSC_WAVEFORM_SQUARE,
OSC_WAVEFORM_TRIANGLE,
OSC_WAVEFORM_SINE,
OSC_WAVEFORM_IMPULSE,
OSC_WAVEFORM_WAVETABLE,
OSC_NUM_WAVEFORMS = OSC_WAVEFORM_WAVETABLE+WT_NUM_WAVETABLES
};
enum
{
OSC_PARAM2_WAVEFORM,
OSC_PARAM2_DUTYCYCLE,
OSC_NUM_PARAMS
};
typedef struct _svco_common_t
{
blit_common_t blit;
wt_common_t wt;
// synth_float_t wavetable[300][128];
} vco_common_t;
typedef struct _sosc_t
{
UINT32 id;
vco_common_t *pCom;
synth_float_t param[OSC_NUM_PARAMS];
synth_float_t fs;
blit_t blep;
wt_t wt;
UINT32 bufsize;
synth_float_t *pOut;
sine_gen_t sine;
synth_float_t impulse;
} osc_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void VCO_ModInit(vco_common_t *pCom);
void VCO_ModFree(vco_common_t *pCom);
void VCO_Init(osc_t *pObj, UINT32 id, vco_common_t *pCom, synth_float_t fs);
void VCO_Free(osc_t *pObj);
void VCO_SetBufsize(osc_t *pObj, UINT32 size);
void VCO_SetFS(osc_t *pObj, synth_float_t fs);
void VCO_Reset(osc_t *pObj, synth_float_t phase);
void VCO_Start(osc_t *pObj);
void VCO_Param2Set(osc_t *pObj, UINT32 type, synth_float_t value);
void VCO_ProcessDataV(osc_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, UINT32 *pSyncIn, UINT32 *pSyncOut, UINT32 len);
synth_float_t* VCO_GetProcessBuffer(osc_t *pObj);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _VCO_H_
+191
View File
@@ -0,0 +1,191 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "vector_utils.h"
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Add_inplace_VS(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t src2, UINT32 len)
{
if (gain1 == 0)
{
while(len--)
{
*(pSrcDst1) = src2;
pSrcDst1++;
}
return;
}
while(len--)
{
*(pSrcDst1) = *(pSrcDst1)*gain1 + src2;
pSrcDst1++;
}
}
void Add_inplace_VV(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len)
{
if (gain1 == 0)
{
while(len--)
{
*(pSrcDst1++) = *(pSrc2++)*gain2;
}
return;
}
if ((gain1 == 1.0) && (gain2 == 1.0))
{
while(len--)
{
*(pSrcDst1++) += *(pSrc2++);
}
return;
}
while(len--)
{
*(pSrcDst1) = *(pSrcDst1)*gain1 + *(pSrc2++)*gain2;
pSrcDst1++;
}
}
void Add_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++)*gain1 + src2;
}
}
void Add_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++)*gain1 + *(pSrc2++)*gain2;
}
}
void Sub_inplace_VS(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pSrcDst1) = *(pSrcDst1)*gain1 - src2;
pSrcDst1++;
}
}
void Sub_inplace_VV(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len)
{
while(len--)
{
*(pSrcDst1) = *(pSrcDst1)*gain1 - *(pSrc2++)*gain2;
pSrcDst1++;
}
}
void Sub_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++)*gain1 - src2;
}
}
void Sub_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++)*gain1 - *(pSrc2++)*gain2;
}
}
void Mul_inplace_VS(synth_float_t *pSrcDst, synth_float_t src, UINT32 len)
{
while(len--)
{
*(pSrcDst++) *= src;
}
}
void Mul_inplace_VV(synth_float_t *pSrcDst, synth_float_t *pSrc, UINT32 len)
{
while(len--)
{
*(pSrcDst++) *= *(pSrc++);
}
}
void Mul_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++) * src2;
}
}
void Mul_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++) * *(pSrc2++);
}
}
void Clamp_inplace_V(synth_float_t *pSrcDst, synth_float_t minimum, synth_float_t maximum, UINT32 len)
{
while(len--)
{
*(pSrcDst) = max(minimum, min(maximum, *(pSrcDst)));
pSrcDst++;
}
}
void Clamp_V(synth_float_t *pDst, synth_float_t *pSrc, synth_float_t minimum, synth_float_t maximum, UINT32 len)
{
while(len--)
{
*(pDst++) = max(minimum, min(maximum, *(pSrc++)));
}
}
void uMax_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pDst++) = max(fabs(*(pSrc1++)), src2);
}
}
void uMax_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len)
{
while(len--)
{
*(pDst++) = max(fabs(*(pSrc1++)), *(pSrc2++));
}
}
void uMin_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pDst++) = min(fabs(*(pSrc1++)), src2);
}
}
void uMin_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len)
{
while(len--)
{
*(pDst++) = min(fabs(*(pSrc1++)), *(pSrc2++));
}
}
+45
View File
@@ -0,0 +1,45 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _VECTOR_UTILS_H_
#define _VECTOR_UTILS_H_
#include "synth_defs.h"
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Add_inplace_VS(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t src2, UINT32 len);
void Add_inplace_VV(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len);
void Add_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t src2, UINT32 len);
void Add_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len);
void Sub_inplace_VS(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t src2, UINT32 len);
void Sub_inplace_VV(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len);
void Sub_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t src2, UINT32 len);
void Sub_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len);
void Mul_inplace_VS(synth_float_t *pSrcDst, synth_float_t src, UINT32 len);
void Mul_inplace_VV(synth_float_t *pSrcDst, synth_float_t *pSrc, UINT32 len);
void Mul_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len);
void Mul_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len);
void Clamp_inplace_V(synth_float_t *pSrcDst, synth_float_t minimum, synth_float_t maximum, UINT32 len);
void Clamp_V(synth_float_t *pDst, synth_float_t *pSrc, synth_float_t minimum, synth_float_t maximum, UINT32 len);
void uMax_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len);
void uMax_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len);
void uMin_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len);
void uMin_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _VECTOR_UTILS_H_
+1230
View File
File diff suppressed because it is too large Load Diff
+322
View File
@@ -0,0 +1,322 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _VOICE_H_
#define _VOICE_H_
#include "synth_defs.h"
#include "env.h"
#include "vco.h"
#include "vcf.h"
#include "lfo.h"
#include "smooth.h"
#define VOICE_OSC_SPREAD_PHASE_AMT 0.01
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
VOICE_PARAM_MASTER_TUNE = 0,
VOICE_PARAM_MASTER_FREF,
VOICE_PARAM_VOICE_PAN,
VOICE_PARAM_PORTAMENTO_TIME,
VOICE_PARAM_OSC_0_ENABLE,
VOICE_PARAM_OSC_1_ENABLE,
VOICE_PARAM_OSC_0_RESTART_ON_TRIGGER,
VOICE_PARAM_OSC_1_RESTART_ON_TRIGGER,
VOICE_PARAM_OSC_0_LEVEL,
VOICE_PARAM_OSC_1_LEVEL,
VOICE_PARAM_OSC_0_PHASE,
VOICE_PARAM_OSC_1_PHASE,
VOICE_PARAM_OSC_0_DUTYCYCLE,
VOICE_PARAM_OSC_1_DUTYCYCLE,
VOICE_PARAM_OSC_0_DETUNE,
VOICE_PARAM_OSC_1_DETUNE,
VOICE_PARAM_OSC_0_TRANSPOSE,
VOICE_PARAM_OSC_1_TRANSPOSE,
VOICE_PARAM_OSC_0_SCALE,
VOICE_PARAM_OSC_1_SCALE,
VOICE_PARAM_OSC_0_WAVEFORM,
VOICE_PARAM_OSC_1_WAVEFORM,
VOICE_PARAM_OSC_0_FM_AMT_0,
VOICE_PARAM_OSC_1_FM_AMT_0,
VOICE_PARAM_OSC_0_FM_AMT_1,
VOICE_PARAM_OSC_1_FM_AMT_1,
VOICE_PARAM_OSC_0_FM_SRC_0,
VOICE_PARAM_OSC_1_FM_SRC_0,
VOICE_PARAM_OSC_0_FM_SRC_1,
VOICE_PARAM_OSC_1_FM_SRC_1,
VOICE_PARAM_OSC_0_FM_SRC_OP,
VOICE_PARAM_OSC_1_FM_SRC_OP,
VOICE_PARAM_OSC_0_AM_AMT_0,
VOICE_PARAM_OSC_1_AM_AMT_0,
VOICE_PARAM_OSC_0_AM_AMT_1,
VOICE_PARAM_OSC_1_AM_AMT_1,
VOICE_PARAM_OSC_0_AM_SRC_0,
VOICE_PARAM_OSC_1_AM_SRC_0,
VOICE_PARAM_OSC_0_AM_SRC_1,
VOICE_PARAM_OSC_1_AM_SRC_1,
VOICE_PARAM_OSC_0_AM_SRC_OP,
VOICE_PARAM_OSC_1_AM_SRC_OP,
VOICE_PARAM_OSC_0_PWM_AMT_0,
VOICE_PARAM_OSC_1_PWM_AMT_0,
VOICE_PARAM_OSC_0_PWM_AMT_1,
VOICE_PARAM_OSC_1_PWM_AMT_1,
VOICE_PARAM_OSC_0_PWM_SRC_0,
VOICE_PARAM_OSC_1_PWM_SRC_0,
VOICE_PARAM_OSC_0_PWM_SRC_1,
VOICE_PARAM_OSC_1_PWM_SRC_1,
VOICE_PARAM_OSC_0_PWM_SRC_OP,
VOICE_PARAM_OSC_1_PWM_SRC_OP,
VOICE_PARAM_NOISE_ENABLE,
VOICE_PARAM_NOISE_LEVEL,
VOICE_PARAM_NOISE_SHAPE,
VOICE_PARAM_KEY,
VOICE_PARAM_VCA_ENV_GAIN,
VOICE_PARAM_VCA_AM_AMT_0,
VOICE_PARAM_VCA_AM_SRC_0,
VOICE_PARAM_VCA_PAN_AMT_0,
VOICE_PARAM_VCA_PAN_SRC_0,
VOICE_PARAM_ENV_0_A, VOICE_PARAM_VCF_ENV_A = VOICE_PARAM_ENV_0_A,
VOICE_PARAM_ENV_1_A, VOICE_PARAM_VCA_ENV_A = VOICE_PARAM_ENV_1_A,
VOICE_PARAM_ENV_2_A,
VOICE_PARAM_ENV_3_A,
VOICE_PARAM_ENV_0_S, VOICE_PARAM_VCF_ENV_S = VOICE_PARAM_ENV_0_S,
VOICE_PARAM_ENV_1_S, VOICE_PARAM_VCA_ENV_S = VOICE_PARAM_ENV_1_S,
VOICE_PARAM_ENV_2_S,
VOICE_PARAM_ENV_3_S,
VOICE_PARAM_ENV_0_D, VOICE_PARAM_VCF_ENV_D = VOICE_PARAM_ENV_0_D,
VOICE_PARAM_ENV_1_D, VOICE_PARAM_VCA_ENV_D = VOICE_PARAM_ENV_1_D,
VOICE_PARAM_ENV_2_D,
VOICE_PARAM_ENV_3_D,
VOICE_PARAM_ENV_0_R, VOICE_PARAM_VCF_ENV_R = VOICE_PARAM_ENV_0_R,
VOICE_PARAM_ENV_1_R, VOICE_PARAM_VCA_ENV_R = VOICE_PARAM_ENV_1_R,
VOICE_PARAM_ENV_2_R,
VOICE_PARAM_ENV_3_R,
VOICE_PARAM_VCF_TYPE,
VOICE_PARAM_VCF_ORDER,
VOICE_PARAM_VCF_F,
VOICE_PARAM_VCF_Q,
VOICE_PARAM_VCF_Q_GAIN_0,
VOICE_PARAM_VCF_Q_CTRL_0,
VOICE_PARAM_VCF_ENV_GAIN,
VOICE_PARAM_VCF_F_AMT_0,
VOICE_PARAM_VCF_F_AMT_1,
VOICE_PARAM_VCF_F_SRC_0,
VOICE_PARAM_VCF_F_SRC_1,
VOICE_PARAM_VCF_F_SRC_OP,
VOICE_PARAM_VCF_Q_AMT_0,
VOICE_PARAM_VCF_Q_AMT_1,
VOICE_PARAM_VCF_Q_SRC_0,
VOICE_PARAM_VCF_Q_SRC_1,
VOICE_PARAM_VCF_Q_SRC_OP,
VOICE_PARAM_LFO_0_SPEED,
VOICE_PARAM_LFO_1_SPEED,
VOICE_PARAM_LFO_2_SPEED,
VOICE_PARAM_LFO_3_SPEED,
VOICE_PARAM_LFO_0_SMOOTH,
VOICE_PARAM_LFO_1_SMOOTH,
VOICE_PARAM_LFO_2_SMOOTH,
VOICE_PARAM_LFO_3_SMOOTH,
VOICE_PARAM_LFO_0_DELAY,
VOICE_PARAM_LFO_1_DELAY,
VOICE_PARAM_LFO_2_DELAY,
VOICE_PARAM_LFO_3_DELAY,
VOICE_PARAM_LFO_0_ATTACK,
VOICE_PARAM_LFO_1_ATTACK,
VOICE_PARAM_LFO_2_ATTACK,
VOICE_PARAM_LFO_3_ATTACK,
VOICE_PARAM_LFO_0_SHAPE,
VOICE_PARAM_LFO_1_SHAPE,
VOICE_PARAM_LFO_2_SHAPE,
VOICE_PARAM_LFO_3_SHAPE,
VOICE_PARAM_LFO_0_MODE,
VOICE_PARAM_LFO_1_MODE,
VOICE_PARAM_LFO_2_MODE,
VOICE_PARAM_LFO_3_MODE,
VOICE_PARAM_LFO_0_SYNC,
VOICE_PARAM_LFO_1_SYNC,
VOICE_PARAM_LFO_2_SYNC,
VOICE_PARAM_LFO_3_SYNC,
VOICE_PARAM_LFO_0_SYMMETRY,
VOICE_PARAM_LFO_1_SYMMETRY,
VOICE_PARAM_LFO_2_SYMMETRY,
VOICE_PARAM_LFO_3_SYMMETRY,
VOICE_NUM_PARAMS
};
enum
{
VOICE_ENV_ENV_0 = 0,
VOICE_ENV_VCF = VOICE_ENV_ENV_0,
VOICE_ENV_ENV_1,
VOICE_ENV_VCA = VOICE_ENV_ENV_1,
VOICE_ENV_2,
VOICE_ENV_3,
};
enum
{
VOICE_MOD_SRC_ZEROS = 0,
VOICE_MOD_SRC_LFO_0,
VOICE_MOD_SRC_LFO_1,
VOICE_MOD_SRC_LFO_2,
VOICE_MOD_SRC_LFO_3,
VOICE_MOD_SRC_ENV_0,
VOICE_MOD_SRC_ENV_1,
VOICE_MOD_SRC_ENV_2,
VOICE_MOD_SRC_ENV_3,
VOICE_MOD_SRC_VCO_0,
VOICE_MOD_SRC_VCO_1,
VOICE_NUM_MOD_SOURCES
};
enum
{
VOICE_MOD_SRC_0_DISABLED = 0,
VOICE_MOD_SRC_0_LFO_0,
VOICE_MOD_SRC_0_LFO_1,
VOICE_MOD_SRC_0_LFO_2,
VOICE_MOD_SRC_0_LFO_3,
VOICE_MOD_SRC_0_ENV_0,
VOICE_MOD_SRC_0_ENV_1,
VOICE_MOD_SRC_0_ENV_2,
VOICE_MOD_SRC_0_ENV_3,
VOICE_MOD_SRC_0_VCO_0,
VOICE_NUM_MOD_SOURCES_0
};
enum
{
VOICE_MOD_SRC_1_DISABLED = 0,
VOICE_MOD_SRC_1_LFO_0,
VOICE_MOD_SRC_1_LFO_1,
VOICE_MOD_SRC_1_LFO_2,
VOICE_MOD_SRC_1_LFO_3,
VOICE_MOD_SRC_1_ENV_0,
VOICE_MOD_SRC_1_ENV_1,
VOICE_MOD_SRC_1_ENV_2,
VOICE_MOD_SRC_1_ENV_3,
VOICE_NUM_MOD_SOURCES_1
};
enum
{
VOICE_MOD_SRC_OP_ADD = 0,
VOICE_MOD_SRC_OP_MUL,
VOICE_NUM_MOD_OPS
};
enum
{
VOICE_LFO_MODE_GLOBAL,
VOICE_LFO_MODE_INDIVIDUAL,
VOICE_LFO_NUM_MODES
};
enum
{
VOICE_LFO_SYNC_FREE,
VOICE_LFO_SYNC_RESTART,
VOICE_LFO_NUM_SYNCS
};
enum
{
VOICE_NOISE_SHAPE_WHITE,
VOICE_NOISE_SHAPE_PINK,
VOICE_NOISE_NUM_SHAPES
};
enum
{
note_state_idle = 0,
note_state_triggered,
note_state_released
};
enum
{
voice_event_shutdown = 0,
voice_event_trigger,
voice_event_retrigger,
voice_event_release
};
typedef struct _svoice_common_t
{
synth_float_t freqTab[NUM_FREQS];
// Global LFO
lfo_t glfo[VOICE_NUM_LFO];
// Global Envelopes
envgen_t genv[VOICE_NUM_ENV];
// Global VCF
vcf_t gvcf[2];
// Global Noise generator
noise_gen_t gnoise;
synth_float_t pBuf_zeros[SYNTH_MAX_BUFSIZE];
synth_float_t pBuf_ones[SYNTH_MAX_BUFSIZE];
synth_float_t *pBuf_LFO_gbl[VOICE_NUM_LFO];
synth_float_t *pBuf_ENV_gbl[VOICE_NUM_ENV];
synth_float_t *pBuf_VCF_gbl_in;
synth_float_t *pBuf_VCF_gbl_out;
synth_float_t noise_out[SYNTH_MAX_BUFSIZE];
vco_common_t vco;
vcf_common_t vcf;
} voice_common_t;
typedef struct _svoice_t
{
voice_common_t *pCom;
UINT32 id;
UINT32 state;
UINT32 bufsize;
envgen_t env[VOICE_NUM_ENV];
synth_float_t fs;
osc_t vco[VOICE_NUM_OSC];
lfo_t lfo[VOICE_NUM_LFO];
vcf_t vcf;
synth_float_t param[VOICE_NUM_PARAMS];
synth_float_t *pBuf_Q;
smooth_t smooth_vco_enable[VOICE_NUM_OSC];
smooth_t smooth_vco_portamento[VOICE_NUM_OSC];
synth_float_t vco_pitch[VOICE_NUM_OSC];
// smooth_t *pParam_smoother[VOICE_NUM_PARAMS];
// synth_float_t param_smoothed[VOICE_NUM_PARAMS][SYNTH_MAX_BUFSIZE];
} voice_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Voice_ModInit(voice_common_t *pCom);
void Voice_ModFree(voice_common_t *pCom);
void VoiceInit(voice_t *pObj, voice_common_t *pCom, UINT32 id, synth_float_t fs);
void VoiceFree(voice_t *pObj);
void VoiceSetFS(voice_t *pObj, synth_float_t fs);
void VoiceSetBufsize(voice_t *pObj, UINT32 size);
void VoiceEvent(voice_t *pObj, UINT32 type);
void VoiceParam2Set(voice_t *pObj, UINT32 type, synth_float_t value);
synth_float_t VoiceParamGet(voice_t *pObj, UINT32 type);
UINT32 VoiceStateGet(voice_t *pObj);
void VoiceProcessDataV(voice_t *pObj, float *pOut1, float *pOut2, UINT32 len);
void VoiceProcessDataV_Common(voice_t *pObj, float *pOut1, float *pOut2, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _VOICE_H_
+358
View File
@@ -0,0 +1,358 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "blit.h"
#include "vco.h"
#include "vector_utils.h"
#include "wavetable.h"
const wt_descr_t _g_wt_descr[WT_NUM_WAVETABLES] =
{
{8, 0, 101, 8, 69, 16, 70, 24, 71, 32, 72, 40, 73, 48, 74, 60, 75},
{8, 0, 77, 8, 78, 16, 79, 24, 80, 32, 81, 40, 82, 48, 83, 60, 84},
{6, 0, 101, 30, 47, 38, 131, 46, 132, 54, 141, 60, 142},
{7, 0, 101, 8, 94, 16, 95, 24, 96, 32, 97, 40, 98, 60, 100},
{3, 0, 2, 24, 1, 60, 1},
{6, 0, 131, 8, 132, 16, 141, 24, 142, 32, 143, 60, 144},
{9, 0, 101, 8, 54, 16, 55, 24, 56, 32, 57, 40, 88, 48, 89, 54, 53, 60, 104},
{4, 0, 114, 20, 115, 40, 116, 60, 99},
{4, 0, 108, 24, 65, 40, 63, 60, 90},
{7, 0, 101, 8, 61, 16, 62, 24, 63, 32, 66, 40, 67, 60, 68},
{5, 0, 42, 14, 43, 30, 44, 46, 45, 60, 46},
{5, 0, 41, 16, 40, 32, 39, 48, 38, 60, 37},
{8, 0, 101, 8, 54, 16, 55, 24, 56, 32, 57, 40, 58, 48, 59, 60, 60},
{8, 0, 241, 8, 242, 16, 243, 24, 244, 32, 245, 40, 241, 48, 242, 60, 243},
{6, 0, 101, 12, 5, 24, 6, 36, 85, 48, 8, 60, 48},
{4, 0, 12, 20, 11, 50, 53, 60, 104},
{31, 0, 146, 2, 147, 4, 148, 6, 149, 8, 150, 10, 151, 12, 152, 14, 153, 16, 154, 18, 155, 20, 156, 22, 157, 24, 158, 26, 159, 28, 160, 30, 161, 32, 162, 34, 163, 36, 164, 38, 165, 40, 166, 42, 167, 44, 168, 46, 169, 48, 170, 50, 171, 52, 172, 54, 173, 56, 174, 58, 175, 60, 176},
{6, 0, 106, 8, 109, 14, 113, 22, 90, 28, 13, 60, 113},
{9, 0, 85, 8, 85, 16, 86, 24, 91, 32, 62, 40, 71, 48, 86, 56, 85, 60, 85},
{5, 0, 117, 28, 117, 40, 116, 52, 119, 60, 119},
{26, 0, 101, 3, 101, 4, 80, 7, 80, 8, 69, 11, 69, 12, 81, 15, 81, 16, 70, 19, 70, 20, 82, 23, 82, 24, 71, 27, 71, 28, 83, 31, 83, 32, 72, 35, 72, 36, 84, 39, 84, 40, 73, 43, 73, 44, 85, 47, 85, 48, 74, 60, 74},
{12, 0, 32, 12, 30, 17, 29, 22, 28, 27, 27, 32, 26, 37, 25, 42, 24, 46, 23, 50, 22, 54, 21, 60, 21},
{8, 0, 32, 14, 33, 15, 32, 29, 34, 30, 32, 43, 35, 44, 32, 60, 36},
{7, 0, 136, 8, 136, 20, 137, 32, 138, 44, 139, 56, 140, 60, 140},
{7, 0, 106, 10, 107, 20, 108, 30, 109, 40, 110, 50, 111, 60, 112},
{8, 0, 101, 16, 112, 17, 101, 32, 113, 33, 101, 48, 112, 49, 101, 60, 91},
{31, 0, 178, 2, 179, 4, 180, 6, 181, 8, 182, 10, 183, 12, 184, 14, 185, 16, 186, 18, 187, 20, 188, 22, 189, 24, 190, 26, 191, 28, 192, 30, 193, 32, 194, 34, 195, 36, 196, 38, 197, 40, 198, 42, 199, 44, 200, 46, 201, 48, 202, 50, 203, 52, 204, 54, 205, 56, 206, 58, 207, 60, 208},
{31, 0, 211, 2, 212, 4, 213, 6, 214, 8, 215, 10, 216, 12, 217, 14, 218, 16, 219, 18, 220, 20, 221, 22, 222, 24, 223, 26, 224, 28, 225, 30, 226, 32, 227, 34, 228, 36, 229, 38, 230, 40, 231, 42, 232, 44, 233, 46, 234, 48, 235, 50, 236, 52, 237, 54, 238, 56, 239, 58, 240, 60, 241},
{17, 0, 8, 4, 9, 8, 10, 12, 11, 16, 12, 20, 13, 24, 14, 28, 15, 32, 16, 36, 17, 40, 18, 44, 19, 48, 20, 52, 21, 56, 22, 60, 23, 63, 22},
{16, 0, 3, 4, 24, 8, 19, 12, 219, 16, 382, 20, 376, 24, 370, 28, 143, 32, 377, 36, 15, 40, 20, 44, 241, 48, 243, 52, 93, 56, 121, 60, 126},
{16, 0, 239, 4, 240, 8, 241, 12, 242, 16, 243, 20, 244, 24, 245, 28, 368, 32, 391, 36, 388, 40, 392, 44, 386, 48, 384, 52, 382, 56, 133, 60, 375},
{16, 0, 382, 4, 30, 8, 31, 12, 32, 16, 33, 20, 34, 24, 35, 28, 36, 32, 240, 36, 241, 40, 242, 44, 243, 48, 244, 52, 245, 56, 140, 60, 369},
{12, 0, 3, 5, 4, 11, 7, 16, 9, 22, 10, 27, 14, 33, 15, 38, 16, 44, 17, 49, 18, 53, 19, 60, 20},
{12, 0, 31, 1, 49, 2, 50, 3, 51, 4, 52, 7, 64, 13, 76, 18, 87, 23, 92, 37, 93, 47, 102, 60, 103},
{20, 0, 105, 2, 118, 5, 120, 8, 121, 10, 122, 12, 123, 16, 124, 19, 125, 23, 126, 26, 127, 30, 128, 32, 129, 35, 130, 39, 133, 42, 134, 45, 135, 49, 145, 54, 177, 58, 209, 60, 210},
{16, 0, 368, 4, 369, 8, 370, 12, 371, 16, 372, 20, 373, 24, 374, 28, 375, 32, 376, 36, 377, 40, 378, 44, 379, 48, 380, 52, 381, 56, 382, 60, 383},
{5, 0, 384, 15, 385, 30, 386, 45, 387, 60, 388},
{6, 0, 389, 12, 390, 24, 391, 36, 392, 48, 393, 60, 394},
{5, 0, 395, 10, 396, 26, 397, 43, 398, 60, 399},
{22, 0, 400, 1, 401, 4, 402, 8, 403, 11, 404, 13, 405, 17, 406, 19, 407, 22, 408, 25, 409, 29, 410, 30, 411, 34, 412, 36, 413, 39, 414, 43, 415, 48, 416, 52, 417, 53, 418, 54, 419, 59, 420, 60, 421}
};
void WT_ModInit(wt_common_t *pCom)
{
UINT32 i, j, k, offset, last_pos, distance;
INT16 sample, wave[WT_WAVE_SIZE];
wt_descr_t *pDesc;
synth_float_t kmix;
synth_float_t x, dx, wave_tri[WT_WAVE_SIZE], wave_sqr[WT_WAVE_SIZE], wave_saw[WT_WAVE_SIZE];
// Create waves from 16-bit raw data
offset = 0;
for (i=0; i < 300; i++)
{
if (i > 245)
offset = 122;
for (j=0; j < 64; j++)
{
sample = ((INT16)pCom->wave_rawdata[128*i + 2*j + 0] << 8) + pCom->wave_rawdata[128*i + 2*j + 1];
wave[j] = sample;
}
// Possible assembly 1
wave[64] = 0;
for (j=0; j < 63; j++)
{
wave[65+j] = -wave[63-j];
}
// Possible assembly 2
// for (j=0; j < 64; j++)
// {
// wave[64+j] = -wave[63-j];
// }
for (j=0; j < WT_WAVE_SIZE; j++)
{
pCom->waves[offset+i][j] = (synth_float_t)wave[j]/8192;
}
#if 0
//#ifdef SYNTH_DEBUG
{
FILE *pFile = NULL;
char filename[128] = {0};
sprintf(filename, "C:\\Users\\jens\\JaySynth\\wave_%03d.pcm", offset+i);
pFile = fopen(filename, "wb");
if (pFile)
{
fwrite(wave, 2, WT_WAVE_SIZE, pFile);
fclose(pFile);
}
}
#endif
}
// Create classic waveforms
// Saw
x = 1;
dx = 2./WT_WAVE_SIZE;
for (i=0; i < WT_WAVE_SIZE; i++)
{
wave_saw[i] = x;
x -= dx;
}
// Sqr
x = 1;
for (i=0; i < WT_WAVE_SIZE/2; i++)
{
wave_sqr[i] = x;
}
for (i=i; i < WT_WAVE_SIZE; i++)
{
wave_sqr[i] = -x;
}
// Tri
x = 0;
dx = 4./WT_WAVE_SIZE;
for (i=0; i < WT_WAVE_SIZE/4; i++)
{
wave_tri[i] = x;
x += dx;
}
for (i=i; i < WT_WAVE_SIZE/2; i++)
{
wave_tri[i] = x;
x -= dx;
}
for (i=i; i < 3*WT_WAVE_SIZE/4; i++)
{
wave_tri[i] = x;
x -= dx;
}
for (i=i; i < WT_WAVE_SIZE; i++)
{
wave_tri[i] = x;
x += dx;
}
// Create wavetables from waves
// Allocate memory
for (i=0; i < WT_NUM_WAVETABLES; i++)
{
pCom->ppWavetables[i] = (synth_float_t**)malloc(WT_WAVETABLE_SIZE*sizeof(synth_float_t*));
for (j=0; j < WT_WAVETABLE_SIZE; j++)
{
pCom->ppWavetables[i][j] = (synth_float_t*)malloc(WT_WAVE_SIZE*sizeof(synth_float_t));
}
}
for (i=0; i < WT_NUM_WAVETABLES; i++)
{
pDesc = &_g_wt_descr[i];
// Create first wavetable entry
j = 0;
for (j=0; j < pDesc->num_entries; j++)
{
memcpy(pCom->ppWavetables[i][pDesc->pEntry[j].pos], pCom->waves[pDesc->pEntry[j].wave_id], WT_WAVE_SIZE*sizeof(synth_float_t));
last_pos = pDesc->pEntry[j].pos;
if ((j+1) == pDesc->num_entries)
continue;
distance = pDesc->pEntry[j+1].pos - last_pos;
for (k=1; k < distance; k++)
{
kmix = 1 - (synth_float_t)k/distance;
Add_VV(pCom->ppWavetables[i][last_pos+k], pCom->ppWavetables[i][last_pos], kmix, pCom->waves[pDesc->pEntry[j+1].wave_id], 1-kmix, WT_WAVE_SIZE);
}
}
memcpy(pCom->ppWavetables[i][61], wave_tri, WT_WAVE_SIZE*sizeof(synth_float_t));
memcpy(pCom->ppWavetables[i][62], wave_sqr, WT_WAVE_SIZE*sizeof(synth_float_t));
memcpy(pCom->ppWavetables[i][63], wave_saw, WT_WAVE_SIZE*sizeof(synth_float_t));
}
}
void WT_ModFree(wt_common_t *pCom)
{
int i, j;
for (i=0; i < WT_NUM_WAVETABLES; i++)
{
for (j=0; j < WT_WAVETABLE_SIZE; j++)
{
free(pCom->ppWavetables[i][j]);
}
free(pCom->ppWavetables[i]);
}
}
void WT_Init(wt_t *pObj, UINT32 id, wt_common_t *pCom, synth_float_t fs)
{
pObj->pCom = pCom;
pObj->id = id;
pObj->fs = fs;
pObj->fm = 1;
if (pObj->id == 0)
{
WT_ModInit(pCom);
}
WT_Prepare(pObj);
}
void WT_Free(wt_t *pObj)
{
if (pObj->id == 0)
{
WT_ModFree(pObj->pCom);
}
}
void WT_SetFS(wt_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
pObj->startup = 1;
}
void WT_Reset(wt_t *pObj, synth_float_t phase)
{
pObj->x = fmod(phase, 1);
pObj->startup = 1;
}
void WT_Prepare(wt_t *pObj)
{
WT_Reset(pObj, (synth_float_t)rand()/RAND_MAX);
}
void WT_Param2Set(wt_t *pObj, UINT32 type, synth_float_t value)
{
switch(type)
{
case WT_PARAM2_WAVEFORM:
if (pObj->param[type] == (UINT32)value)
break;
pObj->param[type] = (UINT32)value;
pObj->startup = 1;
break;
case WT_PARAM2_WAVETABLE_ID:
if (pObj->param[type] == (UINT32)value)
break;
pObj->param[type] = value;
pObj->startup = 1;
break;
case WT_PARAM2_WAVETABLE_ENTRY:
pObj->param[type] = value;
break;
default:
break;
}
}
void WT_Start(wt_t *pObj)
{
pObj->startup = 1;
}
void WT_ProcessDataV(wt_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, synth_float_t *pOut, UINT32 len)
{
UINT32 i, ni, wt_table, ni_next;
synth_float_t out, dx, nn, nf, kmix, w1, w2;
if (pObj->param[WT_PARAM2_WAVEFORM] == WT_WAVEFORM_REGULAR)
{
wt_table = (UINT32)pObj->param[WT_PARAM2_WAVETABLE_ID];
for (i=0; i< len; i++)
{
if (pObj->x >= 1 || pObj->startup)
{
pObj->x -= 1;
if (pObj->startup)
pObj->x = 0;
pObj->wt_index = (WT_WAVETABLE_SIZE-1)*max(0, min(1, pObj->param[WT_PARAM2_WAVETABLE_ENTRY] + pCV_pwm[i]));
pObj->wt_start = (UINT32)pObj->wt_index;
if (pCV_fm)
{
pObj->fm = (synth_float_t)pow((synth_float_t)2, pCV_fm[i]);
}
pObj->startup = 0;
}
ni = (UINT32)(pObj->x*(WT_WAVE_SIZE));
w1 = pObj->pCom->ppWavetables[wt_table][pObj->wt_start][ni];
w2 = pObj->pCom->ppWavetables[wt_table][min((WT_WAVETABLE_SIZE-1), pObj->wt_start+1)][ni];
kmix = pObj->wt_index - (UINT32)pObj->wt_index;
out = w1*(1-kmix) + w2*kmix;
dx = pObj->fm*pPitch[i]/pObj->fs;
pObj->x += dx;
*(pOut++) = out;
}
}
if (pObj->param[WT_PARAM2_WAVEFORM] == WT_WAVEFORM_INTERPOLATED)
{
wt_table = (UINT32)pObj->param[WT_PARAM2_WAVETABLE_ID];
for (i=0; i< len; i++)
{
if (pObj->x >= 1 || pObj->startup)
{
pObj->x -= 1;
if (pObj->startup)
pObj->x = 0;
pObj->wt_index = (WT_WAVETABLE_SIZE-1)*max(0, min(1, pObj->param[WT_PARAM2_WAVETABLE_ENTRY] + pCV_pwm[i]));
pObj->wt_start = (UINT32)pObj->wt_index;
if (pCV_fm)
{
pObj->fm = (synth_float_t)pow((synth_float_t)2, pCV_fm[i]);
}
pObj->startup = 0;
}
nn = pObj->x*(WT_WAVE_SIZE);
ni = (UINT32)nn;
nf = nn - ni;
ni_next = (ni + 1)&(WT_WAVE_SIZE-1);
w1 = (pObj->pCom->ppWavetables[wt_table][pObj->wt_start][ni_next] - pObj->pCom->ppWavetables[wt_table][pObj->wt_start][ni])*nf + pObj->pCom->ppWavetables[wt_table][pObj->wt_start][ni];
w2 = (pObj->pCom->ppWavetables[wt_table][min((WT_WAVETABLE_SIZE-1), pObj->wt_start+1)][ni_next] - pObj->pCom->ppWavetables[wt_table][min((WT_WAVETABLE_SIZE-1), pObj->wt_start+1)][ni])*nf + pObj->pCom->ppWavetables[wt_table][min((WT_WAVETABLE_SIZE-1), pObj->wt_start+1)][ni];
kmix = pObj->wt_index - (UINT32)pObj->wt_index;
out = w1*(1-kmix) + w2*kmix;
dx = pObj->fm*pPitch[i]/pObj->fs;
pObj->x += dx;
*(pOut++) = out;
}
}
}
+89
View File
@@ -0,0 +1,89 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _WAVETABLE_H_
#define _WAVETABLE_H_
#include "synth_types.h"
#define WT_NUM_WAVES 422
#define WT_WAVE_SIZE 128
#define WT_NUM_WAVETABLES 40
#define WT_WAVETABLE_SIZE 64
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
WT_WAVEFORM_REGULAR,
WT_WAVEFORM_INTERPOLATED,
WT_NUM_WAVEFORMS
};
enum
{
WT_PARAM2_WAVEFORM,
WT_PARAM2_WAVETABLE_ID,
WT_PARAM2_WAVETABLE_ENTRY,
WT_NUM_PARAMS
};
typedef struct _swt_descr_entry_t
{
UINT32 pos, wave_id;
} wt_descr_entry_t;
typedef struct _swt_descr_t
{
UINT32 num_entries;
wt_descr_entry_t pEntry[WT_WAVETABLE_SIZE];
} wt_descr_t;
typedef struct _swt_common_t
{
unsigned char wave_rawdata[38400];
synth_float_t waves[WT_NUM_WAVES][WT_WAVE_SIZE];
synth_float_t **ppWavetables[WT_NUM_WAVETABLES]; //[WT_WAVETABLE_SIZE][WT_WAVE_SIZE];
} wt_common_t;
typedef struct _swt_t
{
UINT32 id;
wt_common_t *pCom;
synth_float_t fm, x, dx, wt_index;
UINT32 startup, wt_start;
synth_float_t param[WT_NUM_PARAMS];
synth_float_t fs;
} wt_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void WT_ModInit(wt_common_t *pCom);
void WT_ModFree(wt_common_t *pCom);
void WT_Init(wt_t *pObj, UINT32 id, wt_common_t *pCom, synth_float_t fs);
void WT_Free(wt_t *pObj);
void WT_SetFS(wt_t *pObj, synth_float_t fs);
void WT_Reset(wt_t *pObj, synth_float_t phase);
void WT_Param2Set(wt_t *pObj, UINT32 type, synth_float_t value);
void WT_Prepare(wt_t *pObj);
void WT_Start(wt_t *pObj);
void WT_ProcessDataV(wt_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, synth_float_t *pOut, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _WAVETABLE_H_