275 lines
4.8 KiB
C
275 lines
4.8 KiB
C
#ifndef __NES_APU_H
|
||
#define __NES_APU_H
|
||
//////////////////////////////////////////////////////////////////////////////////
|
||
//本程序移植自网友ye781205的NES模拟器工程
|
||
//ALIENTEK STM32F407开发板
|
||
//NES APU 驱动代码
|
||
//正点原子@ALIENTEK
|
||
//技术论坛:www.openedv.com
|
||
//创建日期:2014/7/1
|
||
//版本:V1.0
|
||
//////////////////////////////////////////////////////////////////////////////////
|
||
|
||
#define APU_SAMPLE_RATE 22050 //APU音频输出为22.050Khz
|
||
#define APU_PCMBUF_SIZE APU_SAMPLE_RATE/60 //44100/60=735 22050/60=367
|
||
|
||
|
||
#undef NULL
|
||
#define NULL 0
|
||
#ifndef TRUE
|
||
#define TRUE 1
|
||
#endif
|
||
#ifndef FALSE
|
||
#define FALSE 0
|
||
#endif
|
||
|
||
/* define this for realtime generated noise */
|
||
#define REALTIME_NOISE
|
||
|
||
#define APU_WRA0 0x4000
|
||
#define APU_WRA1 0x4001
|
||
#define APU_WRA2 0x4002
|
||
#define APU_WRA3 0x4003
|
||
#define APU_WRB0 0x4004
|
||
#define APU_WRB1 0x4005
|
||
#define APU_WRB2 0x4006
|
||
#define APU_WRB3 0x4007
|
||
#define APU_WRC0 0x4008
|
||
#define APU_WRC2 0x400A
|
||
#define APU_WRC3 0x400B
|
||
#define APU_WRD0 0x400C
|
||
#define APU_WRD2 0x400E
|
||
#define APU_WRD3 0x400F
|
||
#define APU_WRE0 0x4010
|
||
#define APU_WRE1 0x4011
|
||
#define APU_WRE2 0x4012
|
||
#define APU_WRE3 0x4013
|
||
|
||
#define APU_SMASK 0x4015
|
||
|
||
/* length of generated noise */
|
||
#define APU_NOISE_32K 0x7FFF
|
||
#define APU_NOISE_93 93
|
||
|
||
#define APU_BASEFREQ 1789772.7272727272727272
|
||
|
||
/* to/from 16.16 fixed point */
|
||
#define APU_TO_FIXED(x) ((x) << 16)
|
||
#define APU_FROM_FIXED(x) ((x) >> 16)
|
||
|
||
|
||
/* channel structures */
|
||
/* As much data as possible is precalculated,
|
||
** to keep the sample processing as lean as possible
|
||
*/
|
||
|
||
typedef struct rectangle_s
|
||
{
|
||
u8 regs[4];
|
||
|
||
u8 enabled;
|
||
|
||
int phaseacc;
|
||
int freq;
|
||
int output_vol;
|
||
u8 fixed_envelope;
|
||
u8 holdnote;
|
||
u8 volume;
|
||
|
||
int sweep_phase;
|
||
int sweep_delay;
|
||
u8 sweep_on;
|
||
u8 sweep_shifts;
|
||
u8 sweep_length;
|
||
u8 sweep_inc;
|
||
|
||
/* this may not be necessary in the future */
|
||
int freq_limit;
|
||
|
||
/* rectangle 0 uses a complement addition for sweep
|
||
** increases, while rectangle 1 uses subtraction
|
||
*/
|
||
u8 sweep_complement;
|
||
|
||
int env_phase;
|
||
int env_delay;
|
||
u8 env_vol;
|
||
|
||
int vbl_length;
|
||
u8 adder;
|
||
int duty_flip;
|
||
} rectangle_t;
|
||
|
||
typedef struct triangle_s
|
||
{
|
||
u8 regs[3];
|
||
|
||
u8 enabled;
|
||
|
||
int freq;
|
||
int phaseacc;
|
||
int output_vol;
|
||
|
||
u8 adder;
|
||
|
||
u8 holdnote;
|
||
u8 counter_started;
|
||
/* quasi-hack */
|
||
int write_latency;
|
||
|
||
int vbl_length;
|
||
int linear_length;
|
||
} triangle_t;
|
||
typedef struct noise_s
|
||
{
|
||
u8 regs[3];
|
||
|
||
u8 enabled;
|
||
|
||
int freq;
|
||
int phaseacc;
|
||
int output_vol;
|
||
|
||
int env_phase;
|
||
int env_delay;
|
||
u8 env_vol;
|
||
u8 fixed_envelope;
|
||
u8 holdnote;
|
||
|
||
u8 volume;
|
||
|
||
int vbl_length;
|
||
|
||
#ifdef REALTIME_NOISE
|
||
u8 xor_tap;
|
||
#else
|
||
u8 short_sample;
|
||
int cur_pos;
|
||
#endif /* REALTIME_NOISE */
|
||
} noise_t;
|
||
|
||
typedef struct dmc_s
|
||
{
|
||
u8 regs[4];
|
||
|
||
/* bodge for timestamp queue */
|
||
u8 enabled;
|
||
|
||
int freq;
|
||
int phaseacc;
|
||
int output_vol;
|
||
|
||
u32 address;
|
||
u32 cached_addr;
|
||
int dma_length;
|
||
int cached_dmalength;
|
||
u8 cur_byte;
|
||
|
||
u8 looping;
|
||
u8 irq_gen;
|
||
u8 irq_occurred;
|
||
} dmc_t;
|
||
|
||
enum //定义枚举变量
|
||
{
|
||
APU_FILTER_NONE,
|
||
APU_FILTER_LOWPASS,
|
||
APU_FILTER_WEIGHTED
|
||
};
|
||
|
||
typedef struct
|
||
{
|
||
//u32 min_range, max_range;
|
||
signed long int min_range, max_range;
|
||
u8 (*read_func)(u32 address);
|
||
} apu_memread;
|
||
|
||
typedef struct
|
||
{
|
||
//u32 min_range, max_range;
|
||
signed long int min_range, max_range;
|
||
void (*write_func)(u32 address, u8 value);
|
||
} apu_memwrite;
|
||
|
||
/* external sound chip stuff */
|
||
typedef struct apuext_s
|
||
{
|
||
void (*init)(void);
|
||
void (*shutdown)(void);
|
||
void (*reset)(void);
|
||
//DCR
|
||
void (*paramschanged)(void);
|
||
int (*process)(void);
|
||
apu_memread *mem_read;
|
||
apu_memwrite *mem_write;
|
||
} apuext_t;
|
||
|
||
/* APU queue structure */
|
||
#define APUQUEUE_SIZE 256 //4096
|
||
#define APUQUEUE_MASK (APUQUEUE_SIZE - 1)
|
||
|
||
/* apu ring buffer member */
|
||
typedef struct apudata_s
|
||
{
|
||
u32 timestamp, address;
|
||
u8 value;
|
||
} apudata_t;
|
||
|
||
|
||
typedef struct apu_s
|
||
{
|
||
rectangle_t rectangle[2];
|
||
triangle_t triangle;
|
||
noise_t noise;
|
||
dmc_t dmc;
|
||
u8 enable_reg;
|
||
|
||
apudata_t queue[APUQUEUE_SIZE];//APUQUEUE_SIZE
|
||
int q_head, q_tail;
|
||
u32 elapsed_cycles;
|
||
|
||
void *buffer; /* pointer to output buffer输出缓冲区指针 */
|
||
int num_samples;
|
||
|
||
u8 mix_enable[6];
|
||
int filter_type;
|
||
|
||
int cycle_rate;
|
||
|
||
int sample_rate;
|
||
int sample_bits;
|
||
int refresh_rate;
|
||
|
||
int decay_lut[16];
|
||
int vbl_lut[32];
|
||
int trilength_lut[128];
|
||
/* external sound chip 外部声音芯片*/
|
||
apuext_t *ext;
|
||
} apu_t;
|
||
|
||
extern apu_t *apu;
|
||
extern u16 *wave_buffers;
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif /* __cplusplus */
|
||
extern void apu_init(void);
|
||
extern void apu_setparams(int sample_rate, int refresh_rate, int frag_size,int sample_bits);
|
||
extern void apu_process(u16 *buffer, int num_samples);
|
||
extern void apu_reset(void);
|
||
|
||
extern u8 Apu_Read4015(u32 address);
|
||
extern void Apu_Write(u8 value,u32 address);
|
||
|
||
void apu_soundoutput(void);
|
||
void apu_write4017(u32 address, u8 value);
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
#endif
|
||
|
||
|
||
|
||
|
||
|