Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Fork of STM32FMSynth by
main.cpp
00001 #include "mbed.h" 00002 #include "sintable.h" 00003 00004 AnalogOut outMono(PA_4);//Not labeled in the docs for the f401, but seems to be for all 00005 //AnalogOut DAC1(PA_5); 00006 00007 AnalogIn inVol(PA_0); 00008 AnalogIn inModAmt(PA_1); 00009 //AnalogIn ADC2(PA_2);//these are the uart pins!! 00010 //AnalogIn ADC3(PA_3);//these are the uart pins!! 00011 //AnalogIn ADC4(PA_4);//we're using these for output 00012 //AnalogIn ADC5(PA_5);//we're using these for output 00013 AnalogIn inCarA(PA_6); 00014 AnalogIn inCarD(PA_7); 00015 //AnalogIn ADC8(PB_0);//lets leave the 2 we aren't using in a single port 00016 //AnalogIn ADC9(PB_1);//that way we know there's not ADCs on one of them 00017 AnalogIn inCarS(PC_0); 00018 AnalogIn inCarR(PC_1); 00019 AnalogIn inModA(PC_2); 00020 AnalogIn inModD(PC_3); 00021 AnalogIn inModS(PC_4); 00022 AnalogIn inModR(PC_5); 00023 00024 //BusIn keyBank(PC_10, PC_11, PC_12, PC_13, PD_2, PH_1); old 00025 BusIn keyBank(PH_1, PD_2, PC_13, PC_12, PC_11, PC_10); 00026 BusOut bankSelect(PB_0, PB_1, PB_2, PB_3, PB_4, PB_5, PB_6, PB_7, PB_8); 00027 BusIn numerator(PA_8, PA_9, PA_10, PA_11); 00028 BusIn denominator(PA_12, PA_13, PA_14, PA_15); 00029 00030 //Serial pc(USBTX, USBRX); 00031 00032 Ticker synthesisClock;// this object sets up an ISR to execute every given fraction of a second. 00033 00034 #define numKeys 49// our keyboard includes from two octaves above middle c to two octaves below it 00035 00036 //constants 00037 00038 //These are the pitches of the notes of our keyboard in hz * int16_max / sampling rate(20khz) 00039 const int carrierIncrements[] = {214, 227, 240, 254, 270, 286, 303, 321, 340, 00040 360, 381, 404, 428, 454, 481, 509, 540, 572, 606, 642, 680, 720, 763, 809, 00041 857, 908, 962, 1019, 1080, 1144, 1212, 1284, 1360, 1441, 1527, 1618, 1714, 00042 1816, 1924, 2039, 2160, 2288, 2424, 2568, 2721, 2883, 3055, 3236, 3429}; 00043 00044 //The maximum value of our envelopes is int16_max 00045 #define attackLimit 0xFFFF 00046 00047 //this gives us a value of pi to multiply things by 00048 #define U_PI 3.14159265358979 00049 00050 //non-constants 00051 //Most of these will be recalculated or reset on every input cycle of the main 00052 // loop, as appropriate 00053 00054 int FMmult = 1;//The modulator pitch is FMmult * the base carrier pitch for that note 00055 int Volume = 0xffff;//the maximum volume to start, our number format is fixed 16 bits of fractional 00056 // inside a 32bit integer usually only in that fractional allowing for 00057 // integer multiplications and shifts to recenter instead of floating 00058 // -point arithmetic 00059 int modVol = 0x2000;//the amount of modulation to apply, most useful relatively low 00060 int64_t keyboard = 0;//our key state is stored as bit flags in the lower 49 bits of this 00061 int64_t modattack = 0x1ffffffffffff;//similar to keyboard, if the corrsponding bit is 00062 // zero the envelope for that bit is in decay or sustain instead of attack 00063 int64_t carattack = 0x1ffffffffffff; 00064 int carrierPhases[numKeys];//store the phases of the notes in between samplings 00065 int modulatorPhases[numKeys]; 00066 int envelopeAmpsC[numKeys];//store the amplitudes of the envelopes in between samplings 00067 int envelopeAmpsM[numKeys]; 00068 00069 //the envelope parameters for synthesis are read from these registers 00070 int modA = 0xffff;//modulator attack rate 00071 int modD = 0xffff;//modulator decay rate 00072 int modS = 0;//modulator sustain level 00073 int modR = 0xffff;//modulator release rate 00074 int carA = 0xffff;//carrier attack rate 00075 int carD = 0xffff;//carrier decay rate 00076 int carS = 0;//carrier sustain level 00077 int carR = 0xffff;//carrier release level 00078 00079 ///@brief Converts a phase of period 2^16 into a sine value 00080 ///@phase The phase to calculate the sine of in phase/65536 * 2 pi radians 00081 ///@return the sine as a signed 16 bit fractonal part inside a 32 bit int 00082 int fastSin(const int phase){ 00083 //the middle 12 bits are used to index into a lookuptable of pre computed sines 00084 int index = (phase & 0x3ffc) >> 2; 00085 00086 //we used linear interpolation given out bottom 2 bits to turn a 2^12 Look Up Table into a 2^14 LUT 00087 int subindex = phase & 0x3; 00088 00089 //We use mirroring of a quarter wave of sine so we only have to store a quarter of the samples again 00090 int quadrant = (phase & 0xc000) >> 14; 00091 int sum = 0; 00092 switch (quadrant) {//perform the mirroring and add the memebers of the weighted average for interpolation 00093 case 0: 00094 sum += (4 - subindex) * sinTable[index]; 00095 sum += subindex * sinTable[index+1]; 00096 break; 00097 case 1: 00098 sum += (4 - subindex) * sinTable[1+4095-index]; 00099 sum += subindex * sinTable[4095-index]; 00100 break; 00101 case 2: 00102 sum -= (4 - subindex) * sinTable[index]; 00103 sum -= subindex * sinTable[index+1]; 00104 break; 00105 case 3: 00106 sum -= (4 - subindex) * sinTable[1+4095-index]; 00107 sum -= subindex * sinTable[4095-index]; 00108 break; 00109 } 00110 sum = sum >> 2;//divide the weighted sum of the neighborign samples by 4 00111 //to get a weighted average 00112 00113 return sum; 00114 } 00115 00116 ///@brief calculates one audio sample given the keyboard state and envelope paramaters and passes it to the DAC 00117 void synthesize(){ 00118 int wave = 0;// holds the sample being constructed. 00119 int subsignal;// the subsample for one note 00120 int64_t keymask;// holds a mask of the current note for easy access to keyboard and attack registers 00121 00122 //for all keys 00123 for(int64_t i = 0; i < numKeys; ++i){ 00124 keymask = 1ll << i;//set the key mask 00125 00126 if(!(keymask & keyboard)){//if the key is NOT pressed 00127 carattack |= keymask;//allow attack the next time it is 00128 modattack |= keymask; 00129 00130 //if envelope is still positive, decrement by decay rate 00131 if(envelopeAmpsC[i] > 0){ 00132 envelopeAmpsC[i] -= carR; 00133 } 00134 if(envelopeAmpsM[i] > 0){ 00135 envelopeAmpsM[i] -= modR; 00136 } 00137 00138 }else{//if the key IS pressed 00139 00140 if(envelopeAmpsC[i] <= 0){//if this key was silent before, 00141 carrierPhases[i] = 0;//reset the wave states 00142 modulatorPhases[i] = 0;//this should prevent frequency drift from stopped FM 00143 envelopeAmpsM[i] = 0; 00144 envelopeAmpsC[i] = 1;//only do it once 00145 } 00146 00147 //if carrier has not left attack phase 00148 if(keymask & carattack){ 00149 //add attack rate to envelope if not already maximised 00150 if(envelopeAmpsC[i] < attackLimit ){ 00151 envelopeAmpsC[i] += carA; 00152 }else{//otherwise clip to maximum and leave attack pahse 00153 envelopeAmpsC[i] = attackLimit; 00154 carattack &= ~keymask; 00155 } 00156 }else{//if in decay/sustain 00157 if(envelopeAmpsC[i] > carS){//subtract the decay rate if above sustain level 00158 envelopeAmpsC[i] -= carD; 00159 } 00160 } 00161 00162 //do all that again for the modulator envelope 00163 if(keymask & modattack){ 00164 if(envelopeAmpsM[i] < attackLimit){ 00165 envelopeAmpsM[i] += modA; 00166 }else{ 00167 envelopeAmpsM[i] = attackLimit; 00168 modattack &= ~keymask; 00169 } 00170 }else{ 00171 if(envelopeAmpsM[i] > modS){ 00172 envelopeAmpsM[i] -= modD; 00173 } 00174 } 00175 00176 } 00177 00178 //If this subsignal is not silent 00179 if(envelopeAmpsC[i] > 0){ 00180 //calculate the new phase of the modulator 00181 modulatorPhases[i] += (carrierIncrements[i] * FMmult)>> 16; 00182 00183 //get the sine for that phase and scale it by the envelope 00184 int modulation = (fastSin(modulatorPhases[i]) * envelopeAmpsM[i])>>16; 00185 00186 //scale it again by the modulation amount 00187 modulation = (modulation * modVol) >> 16; 00188 00189 //calculate the new phase of the carrier, modualting frequency by the modulation 00190 carrierPhases[i] += carrierIncrements[i] + modulation; 00191 00192 //get the sine for that carrier phase and scale by the envelope 00193 //additionally divide by 8 to allow 8 notes to play without saturating the DAC 00194 subsignal = (fastSin(carrierPhases[i]) * envelopeAmpsC[i])>>19; 00195 00196 //add the sample for this note into the overall sample 00197 wave += subsignal; 00198 } 00199 00200 } 00201 00202 //Scale the complete sample by the volume 00203 wave = wave * Volume >> 16; 00204 00205 //clip the sample to within the limits of the DAC if neccessary 00206 wave = (wave > 32767) ? 32767 : wave; 00207 wave = (wave < -32768) ? - 32768 : wave; 00208 00209 //Center the waveform within the range of the DAC 00210 wave += 32768; 00211 00212 //output the sample 00213 outMono.write_u16(wave); 00214 } 00215 00216 00217 int main() { 00218 int ratNumer; 00219 int ratDenom; 00220 int64_t keytemp; 00221 int tempCarA, tempCarD, tempCarR, tempModA, tempModD, tempModR; 00222 00223 for(int i = 0; i < numKeys; ++i){ //zero out values 00224 carrierPhases[i] = 0; 00225 modulatorPhases[i] = 0; 00226 envelopeAmpsC[i] = 0; 00227 envelopeAmpsM[i] = 0; 00228 } 00229 00230 keyBank.mode(PullNone); // we're using external pullup resistors, 00231 //and things weren't working this didn't fix it but better safe 00232 00233 synthesisClock.attach(synthesize, 0.00005); //this runs every 50 us or 20khz 00234 00235 while(true){ 00236 ratNumer = 0xf & ~ numerator; //read ratio numerator 00237 ratDenom = 0xf & ~ denominator; //read ratio denominator 00238 FMmult = (ratNumer << 16) / ratDenom; //FM multiplier = numerator / denominator 00239 00240 Volume = (int)inVol.read_u16(); //read volume 00241 00242 modVol = (int)inModAmt.read_u16(); //read modulation amount 00243 00244 //ensure we don't divide by zero on any of these 00245 00246 //read carrier attack 00247 tempCarA = inCarA.read_u16(); 00248 if(! tempCarA) 00249 carA = 0xffff; 00250 else 00251 carA = 0xffff / tempCarA; 00252 00253 //read carrier decay 00254 tempCarD = inCarD.read_u16(); 00255 if(! tempCarD) 00256 carD = 0xffff; 00257 else 00258 carD = 0xffff / tempCarD; 00259 00260 //read carrier sustain 00261 carS = (int)inCarS.read_u16(); 00262 00263 //read carrier release 00264 tempCarR = inCarR.read_u16(); 00265 if(! tempCarR) 00266 carR = 0xffff; 00267 else 00268 carR = 0xffff / tempCarR; 00269 00270 //read modulation attack 00271 tempModA = inModA.read_u16(); 00272 if(! tempModA) 00273 modA = 0xffff; 00274 else 00275 modA = 0xffff / tempModA; 00276 00277 //read modulation decay 00278 tempModD = inModD.read_u16(); 00279 if(! tempModD) 00280 modD = 0xffff; 00281 else 00282 modD = 0xffff / tempModD; 00283 00284 //read modulation sustain 00285 modS = (int)inModS.read_u16(); 00286 00287 //read modulation release 00288 tempModR = inModR.read_u16(); 00289 if(! tempModR) 00290 modR = 0xffff; 00291 else 00292 modR = 0xffff / tempModR; 00293 00294 keytemp = 0; //zero the keys before we start ORing on top of everything, 00295 //keytemp is a buffer that waits until every key is read, then it pushes 00296 //into the 'keyboard' variable 00297 00298 for(int i = 0; i < 9; ++i) {//for all 9 half-octaves of the keyboard 00299 bankSelect = (~(1 << i)) & bankSelect.mask();//supply power (as ground) to that bank 00300 wait_us(200); //delay to get to get full reading 00301 int shiftOffset = 6LL * i; //read the keys in the bank 00302 00303 //assign the bank to its corresponding position in the overall keyboard 00304 keytemp |= ((~(unsigned long long)keyBank) & (unsigned long long)keyBank.mask()) << (unsigned long long)shiftOffset; 00305 } 00306 keytemp >>= 5;//shift 5 over because bank 0 only has 1 key and it is the 6th key (...111111 111111 100000) 00307 00308 keyboard = keytemp;//push our read values once we are complete. 00309 //This only takes 1 cycle, especially since we are using 'keyboard' in the ISR 00310 00311 //wait_ms(10);//we've stopped bothering to wait here. it didn't make a difference 00312 } 00313 }
Generated on Sat Aug 6 2022 15:00:45 by
1.7.2
