Files
JaySynth/Source/synth/blit.c
T
jens 843c6e300c - initial import
git-svn-id: http://moon:8086/svn/software/trunk/projects/JaySynth@37 b431acfa-c32f-4a4a-93f1-934dc6c82436
2014-10-25 07:27:55 +00:00

434 lines
9.8 KiB
C

// --------------------------------------------------------------
// --------------------------------------------------------------
#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;
}
}