1 // Sunsoft FME-7 sound emulator
3 // Game_Music_Emu 0.6-pre
7 #include "blargg_common.h"
8 #include "blip_buffer.h"
10 enum { fme7_reg_count
= 14 };
12 // Mask and addresses of registers
13 enum { fme7_addr_mask
= 0xE000 };
14 enum { fme7_data_addr
= 0xE000 };
15 enum { fme7_latch_addr
= 0xC000 };
16 enum { fme7_osc_count
= 3 };
18 enum { amp_range
= 192 }; // can be any value; this gives best error/quality tradeoff
21 struct Blip_Buffer
* output
;
25 // static unsigned char const amp_table [16];
29 uint8_t regs
[fme7_reg_count
];
30 uint8_t phases
[3]; // 0 or 1
32 uint16_t delays
[3]; // a, b, c
34 struct osc_t oscs
[fme7_osc_count
];
35 blip_time_t last_time
;
37 struct Blip_Synth synth
;
40 // See Nes_Apu.h for reference
41 void Fme7_init( struct Nes_Fme7_Apu
* this );
42 void Fme7_reset( struct Nes_Fme7_Apu
* this );
44 static inline void Fme7_volume( struct Nes_Fme7_Apu
* this, int v
)
46 Synth_volume( &this->synth
, (v
/2 - (v
*3)/25) / amp_range
); // to do: fine-tune
49 static inline void Fme7_osc_output( struct Nes_Fme7_Apu
* this, int i
, struct Blip_Buffer
* buf
)
51 assert( (unsigned) i
< fme7_osc_count
);
52 this->oscs
[i
].output
= buf
;
55 static inline void Fme7_output( struct Nes_Fme7_Apu
* this, struct Blip_Buffer
* buf
)
58 for ( i
= 0; i
< fme7_osc_count
; i
++ )
59 Fme7_osc_output( this, i
, buf
);
62 // (addr & addr_mask) == latch_addr
63 static inline void Fme7_write_latch( struct Nes_Fme7_Apu
* this, int data
) { this->latch
= data
; }
65 // (addr & addr_mask) == data_addr
66 void Fme7_run_until( struct Nes_Fme7_Apu
* this, blip_time_t end_time
);
67 static inline void Fme7_write_data( struct Nes_Fme7_Apu
* this, blip_time_t time
, int data
)
69 if ( (unsigned) this->latch
>= fme7_reg_count
)
72 debug_printf( "FME7 write to %02X (past end of sound registers)\n", (int) latch
);
77 Fme7_run_until( this, time
);
78 this->regs
[this->latch
] = data
;
81 static inline void Fme7_end_frame( struct Nes_Fme7_Apu
* this, blip_time_t time
)
83 if ( time
> this->last_time
)
84 Fme7_run_until( this, time
);
86 assert( this->last_time
>= time
);
87 this->last_time
-= time
;