This program generates sound by using FM tone generator YMF825 via SPI.
Diff: fmpart.c
- Revision:
- 0:c54d59d6fb78
diff -r 000000000000 -r c54d59d6fb78 fmpart.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fmpart.c Fri Jan 05 22:58:49 2018 +0000 @@ -0,0 +1,164 @@ +// fmpart.c +#include "fmtype.h" +#include "fmpart.h" +#include "fmsd1.h" +#include "fmasgn.h" +#include "fmtone.h" + +// Prototype +static Note* getNote(Part* _this); + +// getter +unsigned char Part_cc1(Part* _this){ return _this->_cc1; } +unsigned char Part_cc7(Part* _this){ return _this->_cc7; } +unsigned short Part_pb(Part* _this){ return _this->_pbvalue; } +unsigned char Part_toneNumber(Part* _this){ return _this->_toneNumber; } + +void Part_init( Part* _this ) +{ + int i; + + Asgn_init(); + Tone_init(); + + _this->_topNt = 0; + _this->_endNt = 0; + _this->_cc1 = 0; + _this->_cc7 = 100; + _this->_cc64 = 0; + _this->_pbvalue = 0x2000; + _this->_toneNumber = 0; + + for ( i=0; i<MAX_NOTE_OBJECT; i++ ){ + Note_init(&_this->_note[i]); + Note_setPart(&_this->_note[i], (void*)_this); + } +} +void Part_note( Part* _this, unsigned char note, unsigned char velocity ) +{ + if ( velocity != 0 ){ + // keyon + Note* newNt = getNote(_this); + if ( Note_keyon(newNt,&_this->_tone,note,velocity) == true ){ + if ( _this->_endNt != FMNULL ){ + Note_setNextPtr( _this->_endNt,newNt ); + Note_setPrevPtr( newNt,_this->_endNt ); + } + _this->_endNt = newNt; + if ( _this->_topNt ==FMNULL ){ + _this->_topNt = newNt; + } + } + } + else { + // keyoff + Note* nt = _this->_topNt; + while( nt != 0 ){ + if (( Note_note(nt) == note ) && + ( Note_isKeyOn(nt) == true ) && + ( Note_isHeld(nt) == false )){ + if ( _this->_cc64 < 64 ){ + Note_keyoff(nt); + } + else { + Note_setHold(nt,true); + } + break; + } + nt = Note_nextPtr(nt); + } + } +} +void Part_releaseNote( Part* _this, Note* nt ) +{ + Note* prevPtr = Note_prevPtr(nt); + if ( _this->_endNt == nt ){ + _this->_endNt = prevPtr; + } + if ( prevPtr != FMNULL ){ + Note_setNextPtr(prevPtr, Note_nextPtr(nt)); + } + + Note* nextPtr = Note_nextPtr(nt); + if ( _this->_topNt == nt ){ + _this->_topNt = nextPtr; + } + if ( nextPtr != FMNULL ){ + Note_setPrevPtr(nextPtr, Note_prevPtr(nt)); + } +} +void Part_cc( Part* _this, unsigned char ccnum, unsigned char value ) +{ + Note* nt = _this->_topNt; + + // Limit + if (value > 127) { value = 127; } + + switch (ccnum) { + case 1: { + _this->_cc1 = value; + while ( nt != FMNULL ) { + Note_chgVibDpt(nt); + nt = Note_nextPtr(nt); + } + break; + } + case 7: { + _this->_cc7 = value; + writeSingle( REG_MASTER_VOL, (value<<1)&0xfc ); + break; + } + case 64: { + _this->_cc64 = value; + if ( value < 64 ){ + while ( nt != FMNULL ) { + if ( Note_isHeld(nt) == true ){ + Note_keyoff(nt); + } + nt = Note_nextPtr(nt); + } + } + break; + } + default: break; + } +} +void Part_pc( Part* _this, unsigned char num ) +{ + Note* nt = _this->_topNt; + Note* nextNt; + + // Damp + while ( nt != FMNULL ) { + nextNt = Note_nextPtr(nt); + Note_damp(nt); + nt = nextNt; + } + + _this->_toneNumber = num; +} +void Part_pbend( Part* _this, unsigned char lsb, unsigned char msb ) +{ + Note* nt = _this->_topNt; + _this->_pbvalue = (msb<<7)|(lsb&0x7f); + while ( nt != FMNULL ) { + Note_chgPit(nt); + nt = Note_nextPtr(nt); + } +} +static Note* getNote( Part* _this ) +{ + int i; + Note* newNt = 0; + for ( i=0; i<MAX_NOTE_OBJECT; i++ ){ + newNt = &(_this->_note[i]); + if ( Note_isInUse(newNt) == false ){ + return newNt; + } + } + // if nothing + newNt = _this->_topNt; + Note_damp(newNt); + return newNt; +} +