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