PCM Digital Synthesizer

Dependencies:   LCD mbed

/media/uploads/p_igmon/img_1731-w480.jpg

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();
+
+}
+