Masahiko Hasebe / microbit_ymf825

Dependencies:   microbit

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fmpart.c Source File

fmpart.c

00001 //  fmpart.c
00002 #include    "fmtype.h"
00003 #include    "fmpart.h"
00004 #include    "fmsd1.h"
00005 #include    "fmasgn.h"
00006 #include    "fmtone.h"
00007 
00008 //  Prototype
00009 static Note* getNote(Part* _this);
00010 
00011 //  getter
00012 unsigned char Part_cc1(Part* _this){ return _this->_cc1; }
00013 unsigned char Part_cc7(Part* _this){ return _this->_cc7; }
00014 unsigned short Part_pb(Part* _this){ return _this->_pbvalue; }
00015 unsigned char Part_toneNumber(Part* _this){ return _this->_toneNumber; }
00016 
00017 void Part_init( Part* _this )
00018 {
00019     int i;
00020 
00021     Asgn_init();
00022     Tone_init();
00023 
00024     _this->_topNt = 0;
00025     _this->_endNt = 0;
00026     _this->_cc1 = 0;
00027     _this->_cc7 = 100;
00028     _this->_cc64 = 0;
00029     _this->_pbvalue = 0x2000;
00030     _this->_toneNumber = 0;
00031 
00032     for ( i=0; i<MAX_NOTE_OBJECT; i++ ){
00033         Note_init(&_this->_note[i]);
00034         Note_setPart(&_this->_note[i], (void*)_this);
00035     }
00036 }
00037 void Part_note( Part* _this, unsigned char note, unsigned char velocity )
00038 {
00039     if ( velocity != 0 ){
00040         //  keyon
00041         Note* newNt = getNote(_this);
00042         if ( Note_keyon(newNt,&_this->_tone,note,velocity) == true ){
00043             if ( _this->_endNt != FMNULL ){
00044                 Note_setNextPtr( _this->_endNt,newNt );
00045                 Note_setPrevPtr( newNt,_this->_endNt );
00046             }
00047             _this->_endNt = newNt;
00048             if ( _this->_topNt ==FMNULL ){
00049                 _this->_topNt = newNt;
00050             }
00051         }
00052     }
00053     else {
00054         //  keyoff
00055         Note* nt = _this->_topNt;
00056         while( nt != 0 ){
00057             if (( Note_note(nt) == note ) &&
00058                 ( Note_isKeyOn(nt) == true ) &&
00059                 ( Note_isHeld(nt) == false )){
00060                 if ( _this->_cc64 < 64 ){
00061                     Note_keyoff(nt);
00062                 }
00063                 else {
00064                     Note_setHold(nt,true);
00065                 }
00066                 break;
00067             }
00068             nt = Note_nextPtr(nt);
00069         }
00070     }
00071 }
00072 void Part_releaseNote( Part* _this, Note* nt )
00073 {
00074     Note* prevPtr = Note_prevPtr(nt);
00075     if ( _this->_endNt == nt ){
00076         _this->_endNt = prevPtr;
00077     }
00078     if ( prevPtr != FMNULL ){
00079         Note_setNextPtr(prevPtr, Note_nextPtr(nt));
00080     }
00081 
00082     Note* nextPtr = Note_nextPtr(nt);
00083     if ( _this->_topNt == nt ){
00084         _this->_topNt = nextPtr;
00085     }
00086     if ( nextPtr != FMNULL ){
00087         Note_setPrevPtr(nextPtr, Note_prevPtr(nt));
00088     }
00089 }
00090 void Part_cc( Part* _this, unsigned char ccnum, unsigned char value )
00091 {
00092     Note* nt = _this->_topNt;
00093 
00094     //  Limit
00095     if (value > 127) { value = 127; }
00096 
00097     switch (ccnum) {
00098         case 1: {
00099             _this->_cc1 = value;
00100             while ( nt != FMNULL ) {
00101                 Note_chgVibDpt(nt);
00102                 nt = Note_nextPtr(nt);
00103             }
00104             break;
00105         }
00106         case 7: {
00107             _this->_cc7 = value;
00108             writeSingle( REG_MASTER_VOL, (value<<1)&0xfc );
00109             break;
00110         }
00111         case 64: {
00112             _this->_cc64 = value;
00113             if ( value < 64 ){
00114                 while ( nt != FMNULL ) {
00115                     if ( Note_isHeld(nt) == true ){
00116                         Note_keyoff(nt);
00117                     }
00118                     nt = Note_nextPtr(nt);
00119                 }
00120             }
00121             break;
00122         }
00123         default: break;
00124     }
00125 }
00126 void Part_pc( Part* _this, unsigned char num )
00127 {
00128     Note* nt = _this->_topNt;
00129     Note* nextNt;
00130 
00131     //  Damp
00132     while ( nt != FMNULL ) {
00133         nextNt = Note_nextPtr(nt);
00134         Note_damp(nt);
00135         nt = nextNt;
00136     }
00137 
00138     _this->_toneNumber = num;
00139 }
00140 void Part_pbend( Part* _this, unsigned char lsb, unsigned char msb )
00141 {
00142     Note* nt = _this->_topNt;
00143     _this->_pbvalue = (msb<<7)|(lsb&0x7f);
00144     while ( nt != FMNULL ) {
00145         Note_chgPit(nt);
00146         nt = Note_nextPtr(nt);
00147     }
00148 }
00149 static Note* getNote( Part* _this )
00150 {
00151     int i;
00152     Note* newNt = 0;
00153     for ( i=0; i<MAX_NOTE_OBJECT; i++ ){
00154         newNt = &(_this->_note[i]);
00155         if ( Note_isInUse(newNt) ==  false ){
00156             return newNt;
00157         }
00158     }
00159     //  if nothing
00160     newNt = _this->_topNt;
00161     Note_damp(newNt);
00162     return newNt;
00163 }
00164