Abel Zatarain / Mbed 2 deprecated FMSynthCSUSM

Dependencies:   mbed

main.cpp

Committer:
davolfman
Date:
2017-12-07
Revision:
12:3a1e7fde5040
Parent:
11:286386c0db40
Child:
13:29705e6bf718

File content as of revision 12:3a1e7fde5040:

#include "mbed.h"
#include "sintable.h"

AnalogOut outMono(PA_4);//Not labeled in the docs for the f401, but seems to be for all
//AnalogOut DAC1(PA_5);

AnalogIn inVol(PA_0);
AnalogIn inModAmt(PA_1);
//AnalogIn ADC2(PA_2);//these are the uart pins!!
//AnalogIn ADC3(PA_3);//these are the uart pins!!
//AnalogIn ADC4(PA_4);//we're using these for output
//AnalogIn ADC5(PA_5);//we're using these for output
AnalogIn inCarA(PA_6);
AnalogIn inCarD(PA_7);
//AnalogIn ADC8(PB_0);//lets leave the 2 we aren't using in a single port
//AnalogIn ADC9(PB_1);//that way we know there's not ADCs on one of them
AnalogIn inCarS(PC_0);
AnalogIn inCarR(PC_1);
AnalogIn inModA(PC_2);
AnalogIn inModD(PC_3);
AnalogIn inModS(PC_4);
AnalogIn inModR(PC_5);

//BusIn keyBank(PC_10, PC_11, PC_12, PC_13, PD_2, PH_1); old
BusIn keyBank(PH_1, PD_2, PC_13, PC_12, PC_11, PC_10);
BusOut bankSelect(PB_0, PB_1, PB_2, PB_3, PB_4, PB_5, PB_6, PB_7, PB_8);
BusIn numerator(PA_8, PA_9, PA_10, PA_11);
BusIn denominator(PA_12, PA_13, PA_14, PA_15);

Serial pc(USBTX, USBRX);

Ticker synthesisClock;

#define numKeys 49

//constants
const int carrierIncrements[] = {107, 113, 120, 127, 135, 143, 151, 160, 170, 
    180, 190, 202, 214, 227, 240, 254, 270, 286, 303, 321, 340, 360, 381, 404, 
    428, 454, 481, 509, 540, 572, 606, 642, 680, 720, 763, 809, 857, 908, 962, 
    1019, 1080, 1144, 1212, 1284, 1360, 1441, 1527, 1618, 1714};
const int attackLimit = (0x1 << 16) - 1;
#define U_PI 3.14159265358979
//non-constants
//Most of these will be recalculated or reset on every input cycle of the main
//  loop, as appropriate
int FMmult;
int Volume;
int modVol;
int64_t keyboard;
int64_t modattack;
int64_t carattack;
int carrierPhases[numKeys];
int modulatorPhases[numKeys];
int envelopeAmpsC[numKeys];
int envelopeAmpsM[numKeys];

int testTone = 0;

int modA;
int modD;
int modS;
int modR;
int carA;
int carD;
int carS;
int carR;

int fastSin(const int phase){
    int index = (phase & 0x3ffc) >> 2;
    int subindex = phase & 0x3;
    int quadrant = (phase & 0xc000) >> 14;
    int sum = 0;
    switch (quadrant) {
        case 0:
            sum += (4 - subindex) * sinTable[index];
            sum += subindex * sinTable[index+1];
            break;
        case 1:
            sum += (4 - subindex) * sinTable[1+4095-index];
            sum += subindex * sinTable[4095-index];
            break;
        case 2:
            sum -= (4 - subindex) * sinTable[index];
            sum -= subindex * sinTable[index+1];        
            break;
        case 3:
            sum -= (4 - subindex) * sinTable[1+4095-index];
            sum -= subindex * sinTable[4095-index];
            break;
    }
    sum = sum >> 2;
    
    return sum;
}

void synthesize(){
    int volumeSum = 0;//starting from silence
    int CenvAmp, MenvAmp;
    bool keypressed;
    int tempPhase, modVal, carVal;
    
    testTone = (testTone + carrierIncrements[25]) & 0xffff;
    
    for(int64_t i; i < numKeys; ++i){//for all keys
        int64_t keymask = 0x00000001 << i;
        keypressed = keyboard & keymask;
        CenvAmp = envelopeAmpsC[i];
        MenvAmp = envelopeAmpsM[i];
        
        if(!keypressed){
            carattack |= keymask;//re-enable attack
            modattack |= keymask;
            CenvAmp = (CenvAmp > 0) ? CenvAmp - carR : CenvAmp;
            MenvAmp = (MenvAmp > 0) ? MenvAmp - modR : CenvAmp;
        }else{
            if(carattack & keymask){//if in carrier attack
                CenvAmp = (CenvAmp < attackLimit) ? CenvAmp + carA : attackLimit;
            }else{
                CenvAmp = (CenvAmp > carS) ? CenvAmp - carD : carS;
            }
            
            if(modattack * keymask){//if in modulator attack
                MenvAmp = (MenvAmp < attackLimit) ? MenvAmp + modA : attackLimit;
            }else{
                MenvAmp = (MenvAmp > modS) ? MenvAmp - modD : modS;
            }
        }

        CenvAmp = (CenvAmp < 0) ? 0 : CenvAmp;
        MenvAmp = (MenvAmp < 0) ? 0 : MenvAmp;
        if(CenvAmp >= attackLimit){
            CenvAmp = attackLimit;
            carattack &= ~keymask; // disable attack on this key
        }
        if(MenvAmp >= attackLimit){
            MenvAmp = attackLimit;
            modattack &= ~keymask;
        }
        if(CenvAmp == 0)
            carrierPhases[i] = 0;
        if(MenvAmp == 0)
            modulatorPhases[i] = 0;
            
        envelopeAmpsC[i] = CenvAmp;
        envelopeAmpsM[i]= MenvAmp;
        
        modulatorPhases[i] = (modulatorPhases[i] + ((carrierIncrements[i] * FMmult) >> 16)) & 0xffff;
        modVal = fastSin(modulatorPhases[i]) * MenvAmp >> 16;
        modVal = modVal * modVol >> 16;
        
        //debug
        //modVal = 0;
        //CenvAmp = keypressed ? 1 : 0;
        
        tempPhase = carrierPhases[i] + carrierIncrements[i];
        tempPhase = (tempPhase + modVal) & 0xffff;
        carrierPhases[i] = tempPhase;
        
        carVal = fastSin(tempPhase) * CenvAmp >> 16;
        
        volumeSum += carVal;        
    }
    
    volumeSum = volumeSum / numKeys;
    volumeSum = (volumeSum * Volume) >> 16;
    //outMono.write_u16((volumeSum + Volume) > 1);
    volumeSum = fastSin(testTone) * 8;
    volumeSum = (volumeSum > 32767) ? 32767 : volumeSum;
    volumeSum = (volumeSum < -32768) ? -32768 : volumeSum;
    volumeSum = volumeSum + 32768;
    
    
    outMono.write_u16(volumeSum);
}


int main() {
    int ratNumer;
    int ratDenom;
    
    int64_t keytemp = 0;

    FMmult = 1;
    Volume = 0;
    modVol = 0;
    keyboard = 0ll;
    modattack = 0x1ffffffffffff;
    carattack = 0x1ffffffffffff;
    for(int i = 0; i < numKeys; ++i){
        carrierPhases[i] = 0;
        modulatorPhases[i] = 0;
        envelopeAmpsC[i] = 0;
        envelopeAmpsM[i] = 0;
    }
    modA = 0;
    modD = 0;
    modS = 0;
    modR = 0;
    carA = 0;
    carD = 0;
    carS = 0;
    carR = 0;
    
    keyBank.mode(PullNone);
    synthesisClock.attach(synthesize, 0.000025);
    
    while(true){
        ratNumer = 0xf & ~ numerator;
        ratDenom = 0xf & ~ denominator;
        FMmult = (ratNumer << 16) / ratDenom;
        
        //Volume = (int)inVol.read_u16();
        Volume = 0xffff;
        
        modVol = (int)inModAmt.read_u16();
        
        if(! inCarA.read_u16())
            carA = 0xffff;
        else
            carA = 0xffff / ((int)inCarA.read_u16());
        
        if(! inCarD.read_u16())
            carD = 0xffff;
        else
            carD = 0xffff / ((int)inCarD.read_u16());
        
        carS = (int)inCarS.read_u16();
        
        if(! inCarR.read_u16())
            carR = 0xffff;
        else
            carR = 0xffff / ((int)inCarR.read_u16());
        
        if(! inModA.read_u16())
            modA = 0xffff;
        else
            modA = 0xffff / ((int)inModA.read_u16());
        
        if(! inModD.read_u16())
            modD = 0xffff;
        else
            modD = 0xffff / ((int)inModD.read_u16());
        
        modS = (int)inModS.read_u16();
        
        if(! inModR.read_u16())
            modR = 0xffff;
        else
            modR = 0xffff / ((int)inModR.read_u16());
        
        //THIS IS CORRECT (1 means the key is connected)
        //                 B8    B7    B6    B5    B4    B3    B2    B1  B0
        //               |----||----||----||----||----||----||----||----||
        //0000000000000001111111111111111111111111111111111111111111111111
        //
        //THIS IS NOT CORRECT (1 means the key is connected)
        //            B8    B7    B6    B5    B4    B3    B2    B1    B0
        //          |----||----||----||----||----||----||----||----||----|
        //0000000000111111111111111111111111111111111111111111111111100000
        //Thus, we need to subtract 5 from our shift
        keytemp = 0; //zero the keys before we start ORing on top of everything
        for(int i = 0; i < 9; ++i) {
            bankSelect = (~(1LL << i)) & (unsigned long long)bankSelect.mask();
            wait_us(200);
            int shiftOffset = 6LL * i;

    
            keytemp |= ((~(unsigned long long)keyBank) & (unsigned long long)keyBank.mask()) << (unsigned long long)shiftOffset;
        }
        keytemp >>= 5;
        
        //keyboard = keytemp;
        //debug
        keyboard = 0x1000000ll;
        wait_ms(5);
    }
}