p igmon
/
uGen4x
PCM Digital Synthesizer
Synthsizer.cpp
- Committer:
- p_igmon
- Date:
- 2016-09-02
- Revision:
- 0:ad6637c36dc7
File content as of revision 0:ad6637c36dc7:
/********************************************************************** ***********************************************************************/ #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(); }