This program generates sound by using FM tone generator YMF825 via SPI.
fmvoice.c@0:c54d59d6fb78, 2018-01-05 (annotated)
- Committer:
- hasebems
- Date:
- Fri Jan 05 22:58:49 2018 +0000
- Revision:
- 0:c54d59d6fb78
???????????????
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hasebems | 0:c54d59d6fb78 | 1 | // fmvoice.c |
hasebems | 0:c54d59d6fb78 | 2 | #include "fmtype.h" |
hasebems | 0:c54d59d6fb78 | 3 | #include "fmvoice.h" |
hasebems | 0:c54d59d6fb78 | 4 | #include "fmtone.h" |
hasebems | 0:c54d59d6fb78 | 5 | #include "fmnote.h" |
hasebems | 0:c54d59d6fb78 | 6 | #include "fmsd1.h" |
hasebems | 0:c54d59d6fb78 | 7 | #include "fmpart.h" |
hasebems | 0:c54d59d6fb78 | 8 | |
hasebems | 0:c54d59d6fb78 | 9 | // setter |
hasebems | 0:c54d59d6fb78 | 10 | void Fmvoice_setVoiceNum( Fmvoice* _this, unsigned char vn ){ _this->_vnum = vn; } |
hasebems | 0:c54d59d6fb78 | 11 | void Fmvoice_setNextVc( Fmvoice* _this, Fmvoice* vc ){ _this->_nextVc = vc; } |
hasebems | 0:c54d59d6fb78 | 12 | |
hasebems | 0:c54d59d6fb78 | 13 | // getter |
hasebems | 0:c54d59d6fb78 | 14 | unsigned char Fmvoice_vnum( Fmvoice* _this ){ return _this->_vnum; } |
hasebems | 0:c54d59d6fb78 | 15 | bool Fmvoice_isKeyon( Fmvoice* _this ){ return _this->_keyon;} |
hasebems | 0:c54d59d6fb78 | 16 | Fmvoice* Fmvoice_nextVc( Fmvoice* _this ){ return _this->_nextVc; } |
hasebems | 0:c54d59d6fb78 | 17 | |
hasebems | 0:c54d59d6fb78 | 18 | void Fmvoice_init( Fmvoice* _this ) |
hasebems | 0:c54d59d6fb78 | 19 | { |
hasebems | 0:c54d59d6fb78 | 20 | _this->_keyon = (false); |
hasebems | 0:c54d59d6fb78 | 21 | _this->_nextVc = FMNULL; |
hasebems | 0:c54d59d6fb78 | 22 | } |
hasebems | 0:c54d59d6fb78 | 23 | void Fmvoice_keyon( Fmvoice* _this, void* nt, void* pt, void* tn, unsigned char note, unsigned char vel ) |
hasebems | 0:c54d59d6fb78 | 24 | { |
hasebems | 0:c54d59d6fb78 | 25 | Part* ptp = (Part*)pt; |
hasebems | 0:c54d59d6fb78 | 26 | |
hasebems | 0:c54d59d6fb78 | 27 | _this->_parent = nt; |
hasebems | 0:c54d59d6fb78 | 28 | _this->_keyon = true; |
hasebems | 0:c54d59d6fb78 | 29 | _this->_nextVc = FMNULL; |
hasebems | 0:c54d59d6fb78 | 30 | |
hasebems | 0:c54d59d6fb78 | 31 | // set voice number |
hasebems | 0:c54d59d6fb78 | 32 | writeSingle( 11, _this->_vnum ); |
hasebems | 0:c54d59d6fb78 | 33 | |
hasebems | 0:c54d59d6fb78 | 34 | // Damp |
hasebems | 0:c54d59d6fb78 | 35 | writeSingle( REG_TOP_ADRS+REG_CTRL, 0x30 ); |
hasebems | 0:c54d59d6fb78 | 36 | |
hasebems | 0:c54d59d6fb78 | 37 | // FNUM,BLOCK |
hasebems | 0:c54d59d6fb78 | 38 | Fmvoice_setBasicPit( _this, note ); |
hasebems | 0:c54d59d6fb78 | 39 | |
hasebems | 0:c54d59d6fb78 | 40 | // Vol |
hasebems | 0:c54d59d6fb78 | 41 | writeSingle( REG_TOP_ADRS+REG_VOL, vel&0xfc ); |
hasebems | 0:c54d59d6fb78 | 42 | |
hasebems | 0:c54d59d6fb78 | 43 | // ChVol |
hasebems | 0:c54d59d6fb78 | 44 | writeSingle( REG_TOP_ADRS+REG_CH_VOL, 0x71 ); |
hasebems | 0:c54d59d6fb78 | 45 | |
hasebems | 0:c54d59d6fb78 | 46 | // XVB |
hasebems | 0:c54d59d6fb78 | 47 | Fmvoice_chgVibDpt(_this, Part_cc1(ptp)); |
hasebems | 0:c54d59d6fb78 | 48 | |
hasebems | 0:c54d59d6fb78 | 49 | // INT, FRAC |
hasebems | 0:c54d59d6fb78 | 50 | Fmvoice_chgPit(_this, Part_pb(ptp)); |
hasebems | 0:c54d59d6fb78 | 51 | |
hasebems | 0:c54d59d6fb78 | 52 | // KeyOn, ToneNum |
hasebems | 0:c54d59d6fb78 | 53 | writeSingle( REG_TOP_ADRS+REG_CTRL, 0x40 + Part_toneNumber(ptp) ); |
hasebems | 0:c54d59d6fb78 | 54 | } |
hasebems | 0:c54d59d6fb78 | 55 | void Fmvoice_keyoff( Fmvoice* _this ) |
hasebems | 0:c54d59d6fb78 | 56 | { |
hasebems | 0:c54d59d6fb78 | 57 | _this->_keyon = false; |
hasebems | 0:c54d59d6fb78 | 58 | writeSingle( 11, _this->_vnum ); |
hasebems | 0:c54d59d6fb78 | 59 | writeSingle( REG_TOP_ADRS+REG_CTRL, 0 ); |
hasebems | 0:c54d59d6fb78 | 60 | } |
hasebems | 0:c54d59d6fb78 | 61 | void Fmvoice_release( Fmvoice* _this ) |
hasebems | 0:c54d59d6fb78 | 62 | { |
hasebems | 0:c54d59d6fb78 | 63 | _this->_keyon = false; |
hasebems | 0:c54d59d6fb78 | 64 | if ( _this->_parent != FMNULL ){ |
hasebems | 0:c54d59d6fb78 | 65 | Note* nt = (Note*)_this->_parent; |
hasebems | 0:c54d59d6fb78 | 66 | Note_releaseVc(nt,_this); |
hasebems | 0:c54d59d6fb78 | 67 | } |
hasebems | 0:c54d59d6fb78 | 68 | _this->_nextVc = FMNULL; |
hasebems | 0:c54d59d6fb78 | 69 | |
hasebems | 0:c54d59d6fb78 | 70 | writeSingle( 11, _this->_vnum ); |
hasebems | 0:c54d59d6fb78 | 71 | writeSingle( REG_TOP_ADRS+REG_CTRL, 0x30 ); |
hasebems | 0:c54d59d6fb78 | 72 | } |
hasebems | 0:c54d59d6fb78 | 73 | void Fmvoice_chgPit( Fmvoice* _this, unsigned short pb ) |
hasebems | 0:c54d59d6fb78 | 74 | { |
hasebems | 0:c54d59d6fb78 | 75 | static const unsigned short tPitTbl[256] = { |
hasebems | 0:c54d59d6fb78 | 76 | 256,257,259,260,262,263,264,266,267,269,270,272,273,275,276,278, |
hasebems | 0:c54d59d6fb78 | 77 | 279,281,282,284,285,287,288,290,292,293,295,296,298,300,301,303, |
hasebems | 0:c54d59d6fb78 | 78 | 304,306,308,309,311,313,314,316,318,320,321,323,325,327,328,330, |
hasebems | 0:c54d59d6fb78 | 79 | 332,334,336,337,339,341,343,345,347,349,350,352,354,356,358,360, |
hasebems | 0:c54d59d6fb78 | 80 | 362,364,366,368,370,372,374,376,378,380,382,384,386,388,391,393, |
hasebems | 0:c54d59d6fb78 | 81 | 395,397,399,401,403,406,408,410,412,415,417,419,421,424,426,428, |
hasebems | 0:c54d59d6fb78 | 82 | 431,433,435,438,440,442,445,447,450,452,454,457,459,462,464,467, |
hasebems | 0:c54d59d6fb78 | 83 | 470,472,475,477,480,482,485,488,490,493,496,498,501,504,506,509, |
hasebems | 0:c54d59d6fb78 | 84 | 512,515,518,520,523,526,529,532,535,538,540,543,546,549,552,555, |
hasebems | 0:c54d59d6fb78 | 85 | 558,561,564,567,571,574,577,580,583,586,589,593,596,599,602,606, |
hasebems | 0:c54d59d6fb78 | 86 | 609,612,616,619,622,626,629,632,636,639,643,646,650,653,657,660, |
hasebems | 0:c54d59d6fb78 | 87 | 664,668,671,675,679,682,686,690,693,697,701,705,709,712,716,720, |
hasebems | 0:c54d59d6fb78 | 88 | 724,728,732,736,740,744,748,752,756,760,764,769,773,777,781,785, |
hasebems | 0:c54d59d6fb78 | 89 | 790,794,798,803,807,811,816,820,825,829,834,838,843,847,852,856, |
hasebems | 0:c54d59d6fb78 | 90 | 861,866,870,875,880,885,890,894,899,904,909,914,919,924,929,934, |
hasebems | 0:c54d59d6fb78 | 91 | 939,944,949,954,960,965,970,975,981,986,991,997,1002,1007,1013,1023 }; |
hasebems | 0:c54d59d6fb78 | 92 | |
hasebems | 0:c54d59d6fb78 | 93 | unsigned char reg[2]; |
hasebems | 0:c54d59d6fb78 | 94 | unsigned char pit = pb/64; |
hasebems | 0:c54d59d6fb78 | 95 | reg[1] = (unsigned char)((tPitTbl[pit]<<1) & 0x007e); |
hasebems | 0:c54d59d6fb78 | 96 | reg[0] = (unsigned char)(((tPitTbl[pit]<<2) & 0x1f00)>>8); |
hasebems | 0:c54d59d6fb78 | 97 | |
hasebems | 0:c54d59d6fb78 | 98 | writeSingle( 11, _this->_vnum ); |
hasebems | 0:c54d59d6fb78 | 99 | writeSingle( REG_TOP_ADRS+REG_INT, reg[0] ); |
hasebems | 0:c54d59d6fb78 | 100 | writeSingle( REG_TOP_ADRS+REG_FRC, reg[1] ); |
hasebems | 0:c54d59d6fb78 | 101 | } |
hasebems | 0:c54d59d6fb78 | 102 | void Fmvoice_chgVibDpt( Fmvoice* _this, unsigned char vibDpt ) |
hasebems | 0:c54d59d6fb78 | 103 | { |
hasebems | 0:c54d59d6fb78 | 104 | vibDpt = vibDpt >>4; |
hasebems | 0:c54d59d6fb78 | 105 | if ( vibDpt == 0 ){ vibDpt = 1;} |
hasebems | 0:c54d59d6fb78 | 106 | writeSingle( 11, _this->_vnum ); |
hasebems | 0:c54d59d6fb78 | 107 | writeSingle( REG_TOP_ADRS+REG_XVB, vibDpt ); |
hasebems | 0:c54d59d6fb78 | 108 | } |
hasebems | 0:c54d59d6fb78 | 109 | void Fmvoice_setBasicPit( Fmvoice* _this, unsigned char note ) |
hasebems | 0:c54d59d6fb78 | 110 | { |
hasebems | 0:c54d59d6fb78 | 111 | static const unsigned short tFreq[240] = { |
hasebems | 0:c54d59d6fb78 | 112 | 347,348,349,350,351,352,353,354,355,356, 357,358,359,360,361,362,363,365,366,367, |
hasebems | 0:c54d59d6fb78 | 113 | 368,369,370,371,372,373,374,375,376,377, 378,380,381,382,383,384,385,386,387,388, |
hasebems | 0:c54d59d6fb78 | 114 | 390,391,392,393,394,395,396,397,399,400, 401,402,403,404,406,407,408,409,410,412, |
hasebems | 0:c54d59d6fb78 | 115 | 413,414,415,416,417,419,420,421,422,424, 425,426,427,428,430,431,432,433,435,436, |
hasebems | 0:c54d59d6fb78 | 116 | 437,439,440,441,442,444,445,446,447,449, 450,451,453,454,455,457,458,459,461,462, |
hasebems | 0:c54d59d6fb78 | 117 | 463,465,466,467,469,470,471,473,474,475, 477,478,480,481,482,484,485,487,488,489, |
hasebems | 0:c54d59d6fb78 | 118 | 491,492,494,495,496,498,499,501,502,504, 505,507,508,510,511,513,514,515,517,518, |
hasebems | 0:c54d59d6fb78 | 119 | 520,521,523,524,526,528,529,531,532,534, 535,537,538,540,541,543,545,546,548,549, |
hasebems | 0:c54d59d6fb78 | 120 | 551,552,554,556,557,559,561,562,564,565, 567,569,570,572,574,575,577,579,580,582, |
hasebems | 0:c54d59d6fb78 | 121 | 584,585,587,589,590,592,594,596,597,599, 601,602,604,606,608,609,611,613,615,617, |
hasebems | 0:c54d59d6fb78 | 122 | 618,620,622,624,626,627,629,631,633,635, 636,638,640,642,644,646,648,649,651,653, |
hasebems | 0:c54d59d6fb78 | 123 | 655,657,659,661,663,665,667,668,670,672, 674,676,678,680,682,684,686,688,690,692}; |
hasebems | 0:c54d59d6fb78 | 124 | |
hasebems | 0:c54d59d6fb78 | 125 | signed short realNote = note; |
hasebems | 0:c54d59d6fb78 | 126 | while ( realNote > 128 ){ realNote -= 12;} |
hasebems | 0:c54d59d6fb78 | 127 | while ( realNote < 0 ){ realNote += 12;} |
hasebems | 0:c54d59d6fb78 | 128 | |
hasebems | 0:c54d59d6fb78 | 129 | int tblIndex = (realNote % 12) * 20; |
hasebems | 0:c54d59d6fb78 | 130 | |
hasebems | 0:c54d59d6fb78 | 131 | unsigned char reg[2]; |
hasebems | 0:c54d59d6fb78 | 132 | unsigned short fr = tFreq[tblIndex]; |
hasebems | 0:c54d59d6fb78 | 133 | unsigned char oct = realNote/12 - 1; |
hasebems | 0:c54d59d6fb78 | 134 | reg[0] = (unsigned char)(((fr & 0x0380)>>4) | oct); |
hasebems | 0:c54d59d6fb78 | 135 | reg[1] = (unsigned char)(fr & 0x007f); |
hasebems | 0:c54d59d6fb78 | 136 | |
hasebems | 0:c54d59d6fb78 | 137 | writeSingle( 11, _this->_vnum ); |
hasebems | 0:c54d59d6fb78 | 138 | writeSingle( REG_TOP_ADRS+REG_BLK, reg[0] ); |
hasebems | 0:c54d59d6fb78 | 139 | writeSingle( REG_TOP_ADRS+REG_FNUM, reg[1] ); |
hasebems | 0:c54d59d6fb78 | 140 | } |