p igmon
/
uGen4x
PCM Digital Synthesizer
Diff: Synthsizer.cpp
- Revision:
- 0:ad6637c36dc7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Synthsizer.cpp Fri Sep 02 13:24:16 2016 +0000 @@ -0,0 +1,575 @@ +/********************************************************************** + + +***********************************************************************/ + +#include "synthesizer.h" + +#ifdef DCF +__asm S16 dcf64(S32 *param ,S32 *signal){ + + PUSH {R4-R7} + LDR r2,[r0 , #0]; param a0 + LDR r3,[r1 , #0]; signal 0 + SMULL r4,r5,r2,r3 + + LDR r6,[r0 , #4]; a1 + LDR r7,[r1 , #4]; x1 + SMLAL r4,r5,r6,r7; Top r5 Bottom r4 + LDR r2,[r0 , #8]; b0 + LDR r3,[r1 , #8]; x2 + SMLAL r4,r5,r2,r3 + LDR r6,[r0 , #12]; b1 + LDR r7,[r1 , #12]; y1 + SMLAL r4,r5,r6,r7 + LDR r2,[r0 , #16]; b2 + LDR r3,[r1 , #16]; y2 + SMLAL r4,r5,r2,r3 + + MOV r0,r1; r0 = r1 signal + ADDS r4 ,r4, r4 ; add the least significant words + ADCS r5 ,r5, r5 ; add the most significant words with carry + ADDS r4, r4, r4 ; add the least significant words + ADCS r5, r5, r5 ; add the most significant words with carry + + LDR r6,[r1, #12]; dcf_y1 + LDR r3,[r0, #4]; dcf_x1 + STR r6,[r1, #16]; dcf_y2 = dcf_y1 + STR r3,[r0, #8]; dcf_x2 = dcf_x1 + LDR r4,[r1, #0]; sample + STR r5,[r0, #12]; dcf_y1 = result + STR r4,[r1 ,#4]; dcf_x1 = sample + + ASR r0,r5,#16; r0 = r5 >>16 + POP {R4-R7} + BX LR +; ENDP + + ALIGN +; END +} +#endif + +__asm S16 satAdd16(S16 val1 ,S16 val2){ + QADD16 r0,r0,r1 + + BX LR +; ENDP + + ALIGN +; END +} + +__asm S32 satAdd32(S32 val1 ,S32 val2){ + QADD r0,r0,r1 + + BX LR + ENDP + + ALIGN + END +} + +int gen_encount; + +extern DigitalOut generating; +#define GENERATE_ON generating=1; +#define GENERATE_OFF generating=0; + +S16 limit; + +/* DMA WAVE BUFFER */ +extern S16 DMA_Buffer[]; +extern __IO BUFFER_StateTypeDef BufferOffset; + +extern U8 midi_base_ch ; +volatile U8 midi_note_ch ; +volatile U8 midi_prog_ch ; + +volatile U8 samplecount = 0; +extern S8 MasterTune;// -128 - +127 +volatile int portament; +S16 MasterVolume = 127<<8;// max 127<<8 +volatile S16 mvoldiv = 0; + +extern STR_VOICE voice[]; + +//static _UWORD df_table[] ={24883,26363,27930,29591,31351,33215,35190,37282,39499,41848,44336,46973};// 44.1k 440Hz@A4 1404029 +static U16 df_table[] ={24996,26482,28057,29725,31493,33366,35350,37452,39679,42038,44538,47186};// 44.1k 442Hz@A4 + +static U16 k[16] ={65535,61439,57343,53247,49151,45055,40959,36863,32767,28671,24575,20479,16383,12287,8191,4095};// 121009 + +#ifdef REVERVE16BIT +S16 reverve_buf[22000]; +S16 *reverve_wtemp; +#else +S8 reverve_buf[44000]; +S8 *reverve_wtemp; +#endif + +extern volatile int TimerCount10mS ; +extern volatile int KeyValDiv; + +extern GENERATOR sgen[]; +extern GENERATOR dgen[]; +extern GENERATOR_TEMP dgen_temp[]; +extern GENERATOR *gen ;// = &sgen[(PresetVoiceNum - 1)*PRGGENMAX] set by Menu PresetVoice +extern GENERATOR *pgen;// = &dgen[0]; +extern GENERATOR_TEMP *pgen_temp;// = &dgen_temp[0]; +extern WaveDef Wave[]; + +extern U8 PresetVoiceNum; +extern U8 MidiChannel;; +extern S8 MasterTune;; +extern int rch_pol; + +void init_voice(void){ +#ifdef DCF + int i; + GENERATOR *gena; + GENERATOR_TEMP *gena_temp; + STR_VOICE *voicea; + gena = pgen; + gena_temp = pgen_temp; + voicea = &voice[0]; + for (i=0;i<VOICEMAX;i++){ + voicea->enable = 0; + voicea->signal[0] = voicea->signal[1] = voicea->signal[2] = voicea->signal[3] = voicea->signal[4] = voicea->signal[5] = 0; + voicea->gen = gena; + voicea->gen_temp = gena_temp; + gena += PRGGENMAX; + gena_temp += PRGGENMAX; + voicea++; + } +#endif +} + +void gen_attack(GENERATOR *gena,GENERATOR_TEMP *gena_temp){ + /* Generator Start */ + gena_temp->lfo1value = 0; + gena_temp->lfo1count = 0; + gena_temp->lfo2count = 0; + gena_temp->lfo1delaycount = gena->lfo1delaytime; + gena_temp->lfo2delaycount = gena->lfo2delaytime; + gena_temp->x = 0; + gena_temp->startadr = (U8 *)Wave[gena->wave_num - 1].startaddr; + gena_temp->p1 = (U8 *)Wave[gena->wave_num - 1].p1; + gena_temp->p2 = (U8 *)Wave[gena->wave_num - 1].p2; + gena_temp->cycle = (U8 *)Wave[gena->wave_num - 1].cycle; + gena_temp->samplecountp1p2 = (U8 *)((uint8_t *)gena_temp->p2 - (uint8_t *)gena_temp->p1); + gena_temp->voltemp = 0; + gena_temp->voltemp1 = (gena->volume<<16) / gena->attacktime; + gena_temp->voltemp2 = ((gena->volume * gena->sustainlevel) /100) <<16; + + gena_temp->status = GEN_NOTEON; + gena_temp->eg_status = EG_IDLE; +} + +void init_sgen(void){ + GENERATOR gena ={ + 1,// U8 sw;// 0,1 + 1,// U8 wave_num;// 1-128 + 0,// S8 notebias;// -128 - +127 + 31,// U8 pan;// 0-31 + 0,// S16 detune;// -512 - +511 + 32512,// U16 volume;// 0-127<<8 + 1,// U16 attacktime;// + 100,// U16 decaytime;// + 80,// U8 sustainlevel;// + 0,// U16 releasetime;// 0-21 + 0,// U16 lfo1depth; + 0,// U8 lfo1speed; + 0,// U8 lfo1type; + 0,// U16 lfo1delaytime;// 0-3000 + 0,// U16 lfo2depth; + 0,// U8 lfo2speed; + 0,// U8 lfo2type; + 0,// U16 lfo2delaytime;// 0-3000 + }; + +// for(int i=0;i<PRGGENMAX*128;i++){ + for(int i=0;i<PRGGENMAX*64;i++){ + memcpy (&sgen[i],&gena,sizeof(GENERATOR)); + } +} + + +void notenum2df(GENERATOR *gen ,GENERATOR_TEMP *gen_temp){ + U32 temp; + U8 octave ,notenum; + notenum = gen_temp->notenum + gen->notebias; + octave = notenum / 12; + /* Pitch Adjuster */ + + if (gen_temp->cycle == 0){ + temp = df_table[(notenum % 12)] * (U32)((U8 *)gen_temp->samplecountp1p2);// 2^16 * 2^(7-8) + }else{ + temp = df_table[(notenum % 12)] * (U32)((U8 *)gen_temp->cycle); + } +// temp += ((S32)(temp * MasterTune))>>12;// +32 縺ァ +1% ・・128 縺ァ +4% +// temp += ((S32)(temp * MasterTune))>>4;// +32 縺ァ +1% ・・128 縺ァ +4% + gen_temp->df = (temp << (1 + octave)); +// gen_temp->df += (S32)((S32)((gen_temp->df>>19) * MasterTune)>>8);// 140617 + gen_temp->df += (S32)((S32)((gen_temp->df>>8) * MasterTune)>>4);// 140618 +} + +void noteon(U8 notenum ,U8 velocity){ + U8 i; + U8 gencount ,sgencount; + STR_VOICE *voicea; + GENERATOR *sgen; + GENERATOR *gena; + GENERATOR_TEMP *gena_temp; + voicea = &voice[0]; + sgen = gen;// source + gena = pgen;// 螳滉ス薙・縺サ縺・〒 + gena_temp = pgen_temp;// 螳滉ス薙・縺サ縺・〒 + gencount = sgencount = 0; + + + if (portament){ + while(sgencount < PRGGENMAX){// 騾壼クク・・ + if(sgen->sw){ // 130302 + while(gencount < GENMAX){ + if(gena_temp->status == GEN_POROFF){ + gena_temp->status = GEN_PORON; + gena_temp->notenum = notenum; + notenum2df(gena,gena_temp); +// gena->velocity = velocity; + gena++; + gena_temp++; + gencount++; + break;// exit while + } + gena++; + gena_temp++; + gencount++; + } + } + sgen++; + sgencount++; + } // while loop + }else{ +#ifdef DCF + if(gen_encount > (GENMAX - 1))return;// 140707 Gen count limit + for (i=0;i<VOICEMAX;i++){ + if(voicea->enable == 0) break;// 遨コ縺・※縺・kvoice + voicea++; + } + if(i>(VOICEMAX - 1))return;// All Voice is Working +// voicea->enable = 0; + gena = voicea->gen; + gena_temp = voicea->gen_temp; + sgen = gen;// source + + for (i=0;i<PRGGENMAX;i++){ + if(sgen->sw){ + memcpy(gena ,sgen ,sizeof(GENERATOR));// sgen1 ->> gena1 + gena_temp->notenum = notenum; + gena_temp->velocity = velocity; + gen_attack(gena ,gena_temp); + notenum2df(gena ,gena_temp); + gen_encount++;// 140707 + voicea->enable |= 1<<i; + }else{ + gena_temp->status = GEN_IDLE; + gena->sw = 0; + gena_temp->voltemp = 0; + } + gena++; + gena_temp++; + sgen++; + } + + } +#else + if(gen_encount > (GENMAX - 1))return;// 140707 Gen count limit + while(sgencount < PRGGENMAX){// 騾壼クク・・ + if(sgen->sw){ // 130302 + while(gencount < GENMAX){ + if(gena_temp->status == GEN_IDLE){ + memcpy(gena ,sgen ,sizeof(GENERATOR));// sgen ->> gena + gena_temp->notenum = notenum; + gena_temp->velocity = velocity; + gen_attack(gena ,gena_temp); + notenum2df(gena ,gena_temp); + gena++; + gena_temp++; + gencount++; + gen_encount++;// 140707 + break;// exit while + } + gena++; + gena_temp++; + gencount++; + } + } + sgen++; + sgencount++; + } + } +#endif +} + +void noteoff(U8 notenum ,U8 velocity){ + U8 i; + GENERATOR *gena; + GENERATOR_TEMP *gena_temp; + gena = pgen;// 螳滉ス薙・縺サ縺・〒 + gena_temp = pgen_temp;// 螳滉ス薙・縺サ縺・〒 + for(i=0;i<GENMAX;i++){ + if(((gena_temp->status == GEN_NOTEON)||(gena_temp->status == GEN_PORON)) && (gena_temp->notenum == notenum)){ // 130302 + +/* 111025 Velocity active untill release time + gena->velocity = 0; +*/ + if (portament){ + gena_temp->status = GEN_POROFF; + }else{ + /* Generator Start Release */ + gena_temp->status = GEN_NOTEOFF; + gena_temp->eg_status = EG_RELEASE; + } + } + gena++; + gena_temp++; + } +} + +void pgmchg(U8 number){ + if (number >63) return; + PresetVoiceNum = number + 1; + presetvoice(); +} + + +/* + Interpolaton value + x - 逵溘・豕「蠖「縺ョ蠎ァ讓・ + y - 陬憺俣險育ョ励↓繧医▲縺ヲ蠕励ky(x) + + 謖・焚驛ィ・主ー乗焚驛ィ + 20 12 bit +*/ + + uint32_t temp32a; +/* DMA Wave繝舌ャ繝輔ぃ縺ォ豕「蠖「繧呈嶌縺崎セシ繧 */ +void wave_generate(void){ + U8 i; + U16 count; + S32 rch,lch; + S16 rchout,lchout; + S16 temps16; + S32 sample; + S16 interpovalue; + S32 interpovalue32; + GENERATOR *gena; + GENERATOR_TEMP *gena_temp; + STR_VOICE *voicea; + + volatile S16 *ptr; + U16 temp; + S32 y; + U32 expo_x; // 謖・焚驛ィ 20bit + U16 fract_x;// 蟆乗焚驛ィ 12bit + + volatile S16 *ptr0; + GENERATE_ON + if (--TimerCount10mS < 0) TimerCount10mS = 0; + + if (BufferOffset == DMA_FullComplete){ + ptr0 = (S16 *)&DMA_Buffer[DMA_BUFFERSIZE>>1];// From Half + }else{ + ptr0 = (S16 *)&DMA_Buffer[0];// From Top + } + BufferOffset = DMA_Idle; + + count = DMA_BUFFERSIZE/4;// DMA 繝舌ャ繝輔ぃ縺ョ繧オ繧、繧コ + while(count-- > 0){ + if(samplecount++ > 43){ + samplecount = 0; + envelope_work(); + } + voicea = &voice[0]; + sample = 0; + gena = pgen;// 螳滉ス薙・縺サ縺・〒 + gena_temp = pgen_temp;// 螳滉ス薙・縺サ縺・〒 + for(i=0;i<GENMAX;i++){ + if(gena_temp->eg_status != EG_IDLE){ + // if(gena_temp->status !=GEN_IDLE){ + +/* +#ifdef BEND + gena->x += (((U32)gena_temp->df>>16) + (S16)gena->detune + gena->lfo1value + gena->bendvalue); +#else +// gena_temp->x += (((U32)gena_temp->df>>16) + (S16)gena->detune + gena_temp->lfo1value); + gena_temp->x += (((U32)gena_temp->df>>16) + (S32)gena->detune + gena_temp->lfo1value); +#endif +*/ + gena_temp->x += gena_temp->xx; + + if (gena_temp->x <= (U32)gena_temp->p2<<12){ + goto generate1; + }else if(gena_temp->p1 == 0){// No Loop + goto nothing; + }else{ + gena_temp->x -= ((U32)gena_temp->samplecountp1p2 <<12);// Loop p1 - p2 + } + +generate1: expo_x = gena_temp->x>>12; +#ifdef INTERPO2 + temp = (gena_temp->x) & 0xfff; + ptr = (S16*)gena_temp->startadr +((U32)expo_x); + y = (*ptr * (4096 - temp)); + ptr++; + y += *ptr * temp; + interpovalue32 = (S32)((S16)(y>>12) * limit)>>3; +#else + fract_x = (gena_temp->x>>8) & 0x0f; + ptr = (S16*)gena_temp->startadr +((U32)expo_x); + + temp = k[fract_x]; + y = *ptr * temp; + ptr++; + y += (*ptr * (65535 - temp)); + interpovalue32 = (S16)(y>>16) * limit; + +#endif + +#ifdef DIST +// if (gena_temp->eg_status < EG_RELEASE){ + if (interpovalue32 > 120<<8){ + interpovalue32 = 120<<8; + }else if(interpovalue32 < (120<<8) * -1){ + interpovalue32 = (120<<8) * -1; + } +// } +#endif + +#ifdef 0 + if (gena_temp->eg_status < EG_RELEASE){ + if (interpovalue > limit<<8){ + interpovalue = limit<<8; + }else if(interpovalue < (limit<<8) * -1){ + interpovalue = (limit<<8) * -1; + } + } +#endif + +// sample += ((S16)interpovalue * ((gena_temp->voltempL)>>1));// 譛牙柑譯∵焚32繝薙ャ繝・ + sample = satAdd32(sample ,((S16)interpovalue32 * ((gena_temp->voltempL)>>1))); +nothing: + + } +#ifdef DCF + if ((i & (PRGGENMAX - 1))== (PRGGENMAX - 1)){ + voicea->signal[0] = (S32)(sample);// 譛牙柑譯∵焚32繝薙ャ繝・ + voicea++; + sample = 0; + } +#endif + gena++; + gena_temp++; + } +#ifdef DCF + voicea =&voice[0]; + lch = 0; + i = VOICEMAX; + while(i--){ +// lch += (S16)(dcf64(voicea->dcf_param ,&voicea->signal[0])); + lch = satAdd16(lch ,(S16)(dcf64(voicea->dcf_param ,&voicea->signal[0]))); +// lch += (S16)((S32)voicea->signal[0]>>16);// NoneLPF + voicea++; + } +#else + lch = sample >> 16; +#endif + +// temps16 = (((S32)lch) * (((S16)MasterVolume)<<1))>>16; + +#ifdef 0 + if (lch > limit<<8){ + lch = limit<<8; + }else if(lch < (limit<<8) * -1){ + lch = (limit<<8) * -1; + } +#endif + +#if 0 + /* Reverve */ +#ifdef REVERVE16BIT + if (count & 1){ + if(++reverve_wtemp == (reverve_buf + 22000)) reverve_wtemp = reverve_buf; + *reverve_wtemp = temps16; + rchout = lchout = 0; + for(i=0;i<90;i += 3){ + S16 *temp_ptr = reverve_wtemp - reverve_tap[i]; + if(temp_ptr < reverve_buf){ + lchout += ((S16)(*(temp_ptr + 22000)) * (U16)reverve_tap[i+1])>>18; + rchout += ((S16)(*(temp_ptr + 22000)) * (U16)reverve_tap[i+2])>>18; + }else{ + lchout += ((S16)(*temp_ptr) * (U16)reverve_tap[i+1])>>18; + rchout += ((S16)(*temp_ptr) * (U16)reverve_tap[i+2])>>18; + } + } + } +#else + /* Reverve */ + rchout = lchout = 0; + if(++reverve_wtemp == (reverve_buf + 44000)) reverve_wtemp = reverve_buf; + *reverve_wtemp = S8(temps16>>8); + for(i=0;i<90;i += 3){ + S8 *temp_ptr = reverve_wtemp - reverve_tap[i]; + if(temp_ptr < reverve_buf){ + lchout += ((S8)(*(temp_ptr + 44000)) * (U16)reverve_tap[i+1])>>10; + rchout += ((S8)(*(temp_ptr + 44000)) * (U16)reverve_tap[i+2])>>10; + }else{ + lchout += ((S8)(*temp_ptr) * (U16)reverve_tap[i+1])>>10; + rchout += ((S8)(*temp_ptr) * (U16)reverve_tap[i+2])>>10; + } + + } + +#endif +// *bufptr++ = ((rch + (rchout & 0xffff))<<16)|(((lch & 0xffff) + (lchout & 0xffff)) & 0xffff); + + *ptr0++ = temps16 + rchout; + *ptr0++ = temps16 + lchout; +#endif + + temps16 = (((S32)lch) * (((S16)MasterVolume)<<1))>>16; + *ptr0++ = temps16; + *ptr0++ = rch_pol * temps16; + + } + GENERATE_OFF +} + + +void uGen4_init(void) +{ + GENERATOR *gena; + GENERATOR_TEMP *gena_temp; + + mvoldiv = 0; + portament = 0;// 130213 + + gena = pgen; + gena_temp = pgen_temp; + for(int i=0;i<GENMAX;i++){ + gena_temp->status = GEN_IDLE; + gena->sw = 0; + gena_temp->voltemp = 0; + gena++; + gena_temp++; + } + + init_voice(); + + midi_note_ch = midi_base_ch; + midi_prog_ch = midi_base_ch; + +// init_midi(); + +} +