aboutsummaryrefslogtreecommitdiff
path: root/libopna/opnafm.h
diff options
context:
space:
mode:
Diffstat (limited to 'libopna/opnafm.h')
-rw-r--r--libopna/opnafm.h111
1 files changed, 111 insertions, 0 deletions
diff --git a/libopna/opnafm.h b/libopna/opnafm.h
new file mode 100644
index 0000000..acd673f
--- /dev/null
+++ b/libopna/opnafm.h
@@ -0,0 +1,111 @@
+#ifndef LIBOPNA_OPNAFM_H_INCLUDED
+#define LIBOPNA_OPNAFM_H_INCLUDED
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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;
+ 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;
+
+ bool keyon;
+};
+
+struct opna_fm_channel {
+ struct opna_fm_slot slot[4];
+
+ // save 2 samples for slot 1 feedback
+ uint16_t fbmem1;
+ uint16_t fbmem2;
+ // 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 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];
+};
+
+void opna_fm_reset(struct opna_fm *fm);
+void opna_fm_mix(struct opna_fm *fm, int16_t *buf, unsigned samples);
+void opna_fm_writereg(struct opna_fm *fm, unsigned reg, unsigned val);
+
+//
+void opna_fm_chan_reset(struct opna_fm_channel *chan);
+void opna_fm_chan_phase(struct opna_fm_channel *chan);
+void opna_fm_chan_env(struct opna_fm_channel *chan);
+void opna_fm_chan_set_blkfnum(struct opna_fm_channel *chan, unsigned blk, unsigned fnum);
+int16_t opna_fm_chanout(struct opna_fm_channel *chan);
+void opna_fm_slot_key(struct opna_fm_channel *chan, int slotnum, bool keyon);
+
+void opna_fm_chan_set_alg(struct opna_fm_channel *chan, unsigned alg);
+void opna_fm_chan_set_fb(struct opna_fm_channel *chan, unsigned fb);
+void opna_fm_slot_set_ar(struct opna_fm_slot *slot, unsigned ar);
+void opna_fm_slot_set_dr(struct opna_fm_slot *slot, unsigned dr);
+void opna_fm_slot_set_sr(struct opna_fm_slot *slot, unsigned sr);
+void opna_fm_slot_set_rr(struct opna_fm_slot *slot, unsigned rr);
+void opna_fm_slot_set_sl(struct opna_fm_slot *slot, unsigned sl);
+void opna_fm_slot_set_tl(struct opna_fm_slot *slot, unsigned tl);
+void opna_fm_slot_set_ks(struct opna_fm_slot *slot, unsigned ks);
+void opna_fm_slot_set_mul(struct opna_fm_slot *slot, unsigned mul);
+void opna_fm_slot_set_det(struct opna_fm_slot *slot, unsigned det);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBOPNA_OPNAFM_H_INCLUDED */