Files
JaySynth/Source/synth/wavetable.c
T
jens 978c752e8b - use jsy_min/jsy_max
- fixed includes
- removed redundant MW table
- added Missing JK_MidiClock
2023-04-21 14:25:04 +02:00

382 lines
11 KiB
C

#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"
//#define WAVE_EXPORT_FILE
extern const wt_descr_t _g_wt_descr[WT_NUM_WAVETABLES];
#if 0
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}
};
#endif
void WT_ModInit(wt_common_t *pCom)
{
UINT32 i, j, k, offset, last_pos, distance;
INT16 sample, wave[WT_WAVE_SIZE];
wt_descr_t const *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];
FILE *pFileAll = NULL;
#ifdef WAVE_EXPORT_FILE
pFileAll = fopen("C:\\Users\\jens\\JaySynth\\wave_sweep.pcm", "wb");
#endif
// 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;
}
#ifdef WAVE_EXPORT_FILE
{
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
if (pFileAll)
{
int i;
for (i=0; i < 20; i++)
{
fwrite(wave, 2, WT_WAVE_SIZE, pFileAll);
}
}
}
if (pFileAll)
fclose(pFileAll);
// 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)*jsy_max(0, jsy_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][jsy_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)*jsy_max(0, jsy_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][jsy_min((WT_WAVETABLE_SIZE-1), pObj->wt_start+1)][ni_next] - pObj->pCom->ppWavetables[wt_table][jsy_min((WT_WAVETABLE_SIZE-1), pObj->wt_start+1)][ni])*nf + pObj->pCom->ppWavetables[wt_table][jsy_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;
}
}
}