Masahiko Hasebe / microbit_ymf825

Dependencies:   microbit

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fmvoice.c Source File

fmvoice.c

00001 //  fmvoice.c
00002 #include    "fmtype.h"
00003 #include    "fmvoice.h"
00004 #include    "fmtone.h"
00005 #include    "fmnote.h"
00006 #include    "fmsd1.h"
00007 #include    "fmpart.h"
00008 
00009 //  setter
00010 void Fmvoice_setVoiceNum( Fmvoice* _this, unsigned char vn ){ _this->_vnum = vn; }
00011 void Fmvoice_setNextVc( Fmvoice* _this, Fmvoice* vc ){ _this->_nextVc = vc; }
00012 
00013 //  getter
00014 unsigned char Fmvoice_vnum( Fmvoice* _this ){ return _this->_vnum; }
00015 bool Fmvoice_isKeyon( Fmvoice* _this ){ return _this->_keyon;}
00016 Fmvoice* Fmvoice_nextVc( Fmvoice* _this ){ return _this->_nextVc; }
00017 
00018 void Fmvoice_init( Fmvoice* _this )
00019 {
00020     _this->_keyon = (false);
00021     _this->_nextVc = FMNULL;
00022 }
00023 void Fmvoice_keyon( Fmvoice* _this, void* nt, void* pt, void* tn, unsigned char note, unsigned char vel )
00024 {
00025     Part* ptp = (Part*)pt;
00026 
00027     _this->_parent = nt;
00028     _this->_keyon = true;
00029     _this->_nextVc = FMNULL;
00030 
00031     //  set voice number
00032     writeSingle( 11, _this->_vnum );
00033 
00034     //  Damp
00035     writeSingle( REG_TOP_ADRS+REG_CTRL, 0x30 );
00036 
00037     //  FNUM,BLOCK
00038     Fmvoice_setBasicPit( _this, note );
00039 
00040     //  Vol
00041     writeSingle( REG_TOP_ADRS+REG_VOL, vel&0xfc );
00042 
00043     //  ChVol
00044     writeSingle( REG_TOP_ADRS+REG_CH_VOL, 0x71 );
00045 
00046     //  XVB
00047     Fmvoice_chgVibDpt(_this, Part_cc1(ptp));
00048 
00049     //  INT, FRAC
00050     Fmvoice_chgPit(_this, Part_pb(ptp));
00051 
00052     //  KeyOn, ToneNum
00053     writeSingle( REG_TOP_ADRS+REG_CTRL, 0x40 + Part_toneNumber(ptp) );
00054 }
00055 void Fmvoice_keyoff( Fmvoice* _this )
00056 {
00057     _this->_keyon = false;
00058     writeSingle( 11, _this->_vnum );
00059     writeSingle( REG_TOP_ADRS+REG_CTRL, 0 );
00060 }
00061 void Fmvoice_release( Fmvoice* _this )
00062 {
00063     _this->_keyon = false;
00064     if ( _this->_parent != FMNULL ){
00065         Note* nt = (Note*)_this->_parent;
00066         Note_releaseVc(nt,_this);
00067     }
00068     _this->_nextVc = FMNULL;
00069 
00070     writeSingle( 11, _this->_vnum );
00071     writeSingle( REG_TOP_ADRS+REG_CTRL, 0x30 );
00072 }
00073 void Fmvoice_chgPit( Fmvoice* _this, unsigned short pb )
00074 {
00075     static const unsigned short tPitTbl[256] = {
00076     256,257,259,260,262,263,264,266,267,269,270,272,273,275,276,278,
00077     279,281,282,284,285,287,288,290,292,293,295,296,298,300,301,303,
00078     304,306,308,309,311,313,314,316,318,320,321,323,325,327,328,330,
00079     332,334,336,337,339,341,343,345,347,349,350,352,354,356,358,360,
00080     362,364,366,368,370,372,374,376,378,380,382,384,386,388,391,393,
00081     395,397,399,401,403,406,408,410,412,415,417,419,421,424,426,428,
00082     431,433,435,438,440,442,445,447,450,452,454,457,459,462,464,467,
00083     470,472,475,477,480,482,485,488,490,493,496,498,501,504,506,509,
00084     512,515,518,520,523,526,529,532,535,538,540,543,546,549,552,555,
00085     558,561,564,567,571,574,577,580,583,586,589,593,596,599,602,606,
00086     609,612,616,619,622,626,629,632,636,639,643,646,650,653,657,660,
00087     664,668,671,675,679,682,686,690,693,697,701,705,709,712,716,720,
00088     724,728,732,736,740,744,748,752,756,760,764,769,773,777,781,785,
00089     790,794,798,803,807,811,816,820,825,829,834,838,843,847,852,856,
00090     861,866,870,875,880,885,890,894,899,904,909,914,919,924,929,934,
00091     939,944,949,954,960,965,970,975,981,986,991,997,1002,1007,1013,1023 };
00092 
00093     unsigned char reg[2];
00094     unsigned char pit = pb/64;
00095     reg[1] = (unsigned char)((tPitTbl[pit]<<1) & 0x007e);
00096     reg[0] = (unsigned char)(((tPitTbl[pit]<<2) & 0x1f00)>>8);
00097 
00098     writeSingle( 11, _this->_vnum );
00099     writeSingle( REG_TOP_ADRS+REG_INT, reg[0] );
00100     writeSingle( REG_TOP_ADRS+REG_FRC, reg[1] );
00101 }
00102 void Fmvoice_chgVibDpt( Fmvoice* _this, unsigned char vibDpt )
00103 {
00104     vibDpt = vibDpt >>4;
00105     if ( vibDpt == 0 ){ vibDpt = 1;}
00106     writeSingle( 11, _this->_vnum );
00107     writeSingle( REG_TOP_ADRS+REG_XVB, vibDpt );
00108 }
00109 void Fmvoice_setBasicPit( Fmvoice* _this, unsigned char note )
00110 {
00111     static const unsigned short tFreq[240] = {
00112     347,348,349,350,351,352,353,354,355,356,    357,358,359,360,361,362,363,365,366,367,
00113     368,369,370,371,372,373,374,375,376,377,    378,380,381,382,383,384,385,386,387,388,
00114     390,391,392,393,394,395,396,397,399,400,    401,402,403,404,406,407,408,409,410,412,
00115     413,414,415,416,417,419,420,421,422,424,    425,426,427,428,430,431,432,433,435,436,
00116     437,439,440,441,442,444,445,446,447,449,    450,451,453,454,455,457,458,459,461,462,
00117     463,465,466,467,469,470,471,473,474,475,    477,478,480,481,482,484,485,487,488,489,
00118     491,492,494,495,496,498,499,501,502,504,    505,507,508,510,511,513,514,515,517,518,
00119     520,521,523,524,526,528,529,531,532,534,    535,537,538,540,541,543,545,546,548,549,
00120     551,552,554,556,557,559,561,562,564,565,    567,569,570,572,574,575,577,579,580,582,
00121     584,585,587,589,590,592,594,596,597,599,    601,602,604,606,608,609,611,613,615,617,
00122     618,620,622,624,626,627,629,631,633,635,    636,638,640,642,644,646,648,649,651,653,
00123     655,657,659,661,663,665,667,668,670,672,    674,676,678,680,682,684,686,688,690,692};
00124 
00125     signed short realNote = note;
00126     while ( realNote > 128 ){ realNote -= 12;}
00127     while ( realNote < 0 ){ realNote += 12;}
00128 
00129     int tblIndex = (realNote % 12) * 20;
00130 
00131     unsigned char reg[2];
00132     unsigned short fr = tFreq[tblIndex];
00133     unsigned char oct = realNote/12 - 1;
00134     reg[0] = (unsigned char)(((fr & 0x0380)>>4) | oct);
00135     reg[1] = (unsigned char)(fr & 0x007f);
00136 
00137     writeSingle( 11, _this->_vnum );
00138     writeSingle( REG_TOP_ADRS+REG_BLK, reg[0] );
00139     writeSingle( REG_TOP_ADRS+REG_FNUM, reg[1] );
00140 }