#ifndef LIBOPNA_OPNAFM_H_INCLUDED #define LIBOPNA_OPNAFM_H_INCLUDED #include #include #include "leveldata/leveldata.h" #ifdef __cplusplus extern "C" { #endif #define LIBOPNA_FM_ENV_MAX 1023 enum { ENV_ATTACK, ENV_DECAY, ENV_SUSTAIN, ENV_RELEASE, ENV_OFF, }; struct opna_fm_slot { // 20bits, upper 10 bits will be the index to sine table uint32_t phase; // 10 bits uint16_t env; // 12 bits uint16_t env_hires; uint16_t env_count; uint8_t env_state; uint8_t rate_shifter; uint8_t rate_selector; uint8_t rate_mul; uint8_t tl; uint8_t sl; uint8_t ar; uint8_t dr; uint8_t sr; uint8_t rr; uint8_t mul; uint8_t det; uint8_t ks; uint8_t keycode; // set with opna_write bool keyon_ext; // synchronized with env update (once per 3 samples) bool keyon; // set when opna_fm_slotout called int16_t prevout; }; struct opna_fm_channel { struct opna_fm_slot slot[4]; // save 2 samples for slot 1 feedback uint16_t fbmem; // save sample for long (>2) chain of slots uint16_t alg_mem; uint8_t alg; uint8_t fb; uint16_t fnum; uint8_t blk; struct leveldata leveldata; }; struct opna_fm { struct opna_fm_channel channel[6]; // remember here what was written on higher byte, // actually write when lower byte written uint8_t blkfnum_h; // channel 3 blk, fnum struct { uint16_t fnum[3]; uint8_t blk[3]; uint8_t mode; } ch3; // do envelope once per 3 samples uint8_t env_div3; // pan bool lselect[6]; bool rselect[6]; // mask // when (1<