⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vlm5030.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
	vlm5030.c

	VLM5030 emulator

	Written by Tatsuyuki Satoh
	core decode program is used from MAME's TMS5220 emurator.

	memory cycle(sampling rate ?) = 122.9u(440clock)
	interpolator(LC8109 = 2.5ms)  = 20 * samples(125us)
	frame time  (20ms)            =  8 * interpolator

	version 0.33

----------- command format (Analytical result) ----------

1)end of speech (8bit/frame)
:00000011:

2)silent        (8bit/frame)
:????LL01:

LL : Silent frames
     00=2 frame
     01=4 frame
     10=6 frame
     11=8 frame

3)play frame    (48bit/frame)
: 1st    :   2nd  :   3rd  :   4th  :  5th   :   6th  :
:??PPPPP0:?????EEE:????????:????????:????????:????????:

EEE   : energy ( volume )
PPPPP : pitch
?     : unnown

*/
#include "driver.h"
#include "vlm5030.h"

#define MIN_SLICE 10

#define IP_SIZE 20		/* samples per interpolator */
#define FR_SIZE 8		/* interpolator per frame   */

static int sample_pos;
static int buffer_len;
static int emulation_rate;
static struct VLM5030interface *intf;

static unsigned char *outbuffer;
static int channel;

static unsigned char *VLM5030_rom;
static int VLM5030_address;
static int pin_BSY;
static int pin_ST;
static int pin_RST;
static int latch_data = 0;
static int sampling_mode;

static int table_h;

#define PH_RESET 0
#define PH_IDLE  1
#define PH_SETUP 2
#define PH_WAIT  3
#define PH_RUN   4
#define PH_STOP  5
static int phase;

/* these contain data describing the current and previous voice frames */
static unsigned short old_energy = 0;
static unsigned short old_pitch = 0;
static int old_k[10] = {0,0,0,0,0,0,0,0,0,0};

static unsigned short new_energy = 0;
static unsigned short new_pitch = 0;
static int new_k[10] = {0,0,0,0,0,0,0,0,0,0};

/* these are all used to contain the current state of the sound generation */
static unsigned short current_energy = 0;
static unsigned short current_pitch = 0;
static int current_k[10] = {0,0,0,0,0,0,0,0,0,0};

static unsigned short target_energy = 0;
static unsigned short target_pitch = 0;
static int target_k[10] = {0,0,0,0,0,0,0,0,0,0};

static int interp_count = 0;       /* number of interp periods (0-7) */
static int sample_count = 0;       /* sample number within interp (0-19) */
static int pitch_count = 0;

static int u[11] = {0,0,0,0,0,0,0,0,0,0,0};
static int x[10] = {0,0,0,0,0,0,0,0,0,0};

static int randbit = 0;

/* ROM Tables */

/* !!!!!!!!!! ROM table is not correct.        !!!!!!!!!! */
/* !!!!!!!!!!  These are ROM tables of TMS5220 !!!!!!!!!! */

/* This is the energy lookup table (4-bits -> 10-bits) */

static const unsigned short energytable[0x10]={
0x0000,0x00C0,0x0140,0x01C0,0x0280,0x0380,0x0500,0x0740,
0x0A00,0x0E40,0x1440,0x1C80,0x2840,0x38C0,0x5040,0x7FC0};

/* This is the pitch lookup table (6-bits -> 8-bits) */

static const unsigned short pitchtable [0x40]={
0x0000,0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,
0x1700,0x1800,0x1900,0x1A00,0x1B00,0x1C00,0x1D00,0x1E00,
0x1F00,0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,
0x2700,0x2800,0x2900,0x2A00,0x2B00,0x2D00,0x2F00,0x3100,
0x3300,0x3500,0x3600,0x3900,0x3B00,0x3D00,0x3F00,0x4200,
0x4500,0x4700,0x4900,0x4D00,0x4F00,0x5100,0x5500,0x5700,
0x5C00,0x5F00,0x6300,0x6600,0x6A00,0x6E00,0x7300,0x7700,
0x7B00,0x8000,0x8500,0x8A00,0x8F00,0x9500,0x9A00,0xA000};

/* These are the reflection coefficient lookup tables */

/* K1 is (5-bits -> 9 bits+sign, 2's comp. fractional (-1 < x < 1) */

static const short k1table    [0x20]={
(short)0x82C0,(short)0x8380,(short)0x83C0,(short)0x8440,(short)0x84C0,(short)0x8540,(short)0x8600,(short)0x8780,
(short)0x8880,(short)0x8980,(short)0x8AC0,(short)0x8C00,(short)0x8D40,(short)0x8F00,(short)0x90C0,(short)0x92C0,
(short)0x9900,(short)0xA140,(short)0xAB80,(short)0xB840,(short)0xC740,(short)0xD8C0,(short)0xEBC0,0x0000,
0x1440,0x2740,0x38C0,0x47C0,0x5480,0x5EC0,0x6700,0x6D40};

/* K2 is (5-bits -> 9 bits+sign, 2's comp. fractional (-1 < x < 1) */

static const short k2table    [0x20]={
(short)0xAE00,(short)0xB480,(short)0xBB80,(short)0xC340,(short)0xCB80,(short)0xD440,(short)0xDDC0,(short)0xE780,
(short)0xF180,(short)0xFBC0,0x0600,0x1040,0x1A40,0x2400,0x2D40,0x3600,
0x3E40,0x45C0,0x4CC0,0x5300,0x5880,0x5DC0,0x6240,0x6640,
0x69C0,0x6CC0,0x6F80,0x71C0,0x73C0,0x7580,0x7700,0x7E80};

/* K3 is (4-bits -> 9 bits+sign, 2's comp. fractional (-1 < x < 1) */

static const short k3table    [0x10]={
(short)0x9200,(short)0x9F00,(short)0xAD00,(short)0xBA00,(short)0xC800,(short)0xD500,(short)0xE300,(short)0xF000,
(short)0xFE00,0x0B00,0x1900,0x2600,0x3400,0x4100,0x4F00,0x5C00};

/* K4 is (4-bits -> 9 bits+sign, 2's comp. fractional (-1 < x < 1) */

static const short k4table    [0x10]={
(short)0xAE00,(short)0xBC00,(short)0xCA00,(short)0xD800,(short)0xE600,(short)0xF400,0x0100,0x0F00,
0x1D00,0x2B00,0x3900,0x4700,0x5500,0x6300,0x7100,0x7E00};

/* K5 is (4-bits -> 9 bits+sign, 2's comp. fractional (-1 < x < 1) */

static const short k5table    [0x10]={
(short)0xAE00,(short)0xBA00,(short)0xC500,(short)0xD100,(short)0xDD00,(short)0xE800,(short)0xF400,(short)0xFF00,
0x0B00,0x1700,0x2200,0x2E00,0x3900,0x4500,0x5100,0x5C00};

/* K6 is (4-bits -> 9 bits+sign, 2's comp. fractional (-1 < x < 1) */

static const short k6table    [0x10]={
(short)0xC000,(short)0xCB00,(short)0xD600,(short)0xE100,(short)0xEC00,(short)0xF700,0x0300,0x0E00,
0x1900,0x2400,0x2F00,0x3A00,0x4500,0x5000,0x5B00,0x6600};

/* K7 is (4-bits -> 9 bits+sign, 2's comp. fractional (-1 < x < 1) */

static const short k7table    [0x10]={
(short)0xB300,(short)0xBF00,(short)0xCB00,(short)0xD700,(short)0xE300,(short)0xEF00,(short)0xFB00,0x0700,
0x1300,0x1F00,0x2B00,0x3700,0x4300,0x4F00,0x5A00,0x6600};

/* K8 is (3-bits -> 9 bits+sign, 2's comp. fractional (-1 < x < 1) */

static const short k8table    [0x08]={
(short)0xC000,(short)0xD800,(short)0xF000,0x0700,0x1F00,0x3700,0x4F00,0x6600};

/* K9 is (3-bits -> 9 bits+sign, 2's comp. fractional (-1 < x < 1) */

static const short k9table    [0x08]={
(short)0xC000,(short)0xD400,(short)0xE800,(short)0xFC00,0x1000,0x2500,0x3900,0x4D00};

/* K10 is (3-bits -> 9 bits+sign, 2's comp. fractional (-1 < x < 1) */

static const short k10table   [0x08]={
(short)0xCD00,(short)0xDF00,(short)0xF100,0x0400,0x1600,0x2000,0x3B00,0x4D00};

/* chirp table */

static char chirptable[41]={
0x00, 0x2a, (char)0xd4, 0x32,
(char)0xb2, 0x12, 0x25, 0x14,
0x02, (char)0xe1, (char)0xc5, 0x02,
0x5f, 0x5a, 0x05, 0x0f,
0x26, (char)0xfc, (char)0xa5, (char)0xa5,
(char)0xd6, (char)0xdd, (char)0xdc, (char)0xfc,
0x25, 0x2b, 0x22, 0x21,
0x0f, (char)0xff, (char)0xf8, (char)0xee,
(char)0xed, (char)0xef, (char)0xf7, (char)0xf6,
(char)0xfa, 0x00, 0x03, 0x02,
0x01
};

/* interpolation coefficients */
static char interp_coeff[8] = {
8, 8, 8, 4, 4, 2, 2, 1
};


/* check sample file */
static int check_samplefile(int num)
{
	if (Machine->samples == 0) return 0;
	if (Machine->samples->total <= num ) return 0;
	if (Machine->samples->sample[num] == 0) return 0;
	/* sample file is found */
	return 1;
}

static int get_bits(int sbit,int bits)
{
#if 1 /* LSB FIRST */
	int offset = VLM5030_address + (sbit>>3);
	int data;

	data = VLM5030_rom[offset] | (((int)VLM5030_rom[offset+1])<<8);
	data >>= sbit;
	data &= (0xff>>(8-bits));
#else
	int offset = VLM5030_address + (sbit>>3);
	int data;

	data = (((int)VLM5030_rom[offset])<<8) | VLM5030_rom[offset+1];
	data <<= (sbit&0x07);
	data &= 0xffff;
	data >>= (16 - bits);
#endif

	return data;
}

/* get next frame */
static int parse_frame (void)
{
	unsigned char cmd;

	/* remember previous frame */
	old_energy = new_energy;
	old_pitch = new_pitch;
	memcpy( old_k , new_k , sizeof(old_k) );
	/* command byte check */
	cmd = VLM5030_rom[VLM5030_address];
	if( cmd & 0x01 )
	{	/* extend frame */
		new_energy = new_pitch = 0;
		memset( new_k , 0 , sizeof(new_k));
		VLM5030_address++;
		if( cmd & 0x02 )
		{	/* end of speech */
			return 0;
		}
		else
		{	/* silent frame */
			int nums = ( (cmd>>2)+1 )*2;
			return nums * FR_SIZE;
		}
	}
	/* normal frame */
/*
0        8        16       24       32       40
:??PPPPP0:11111EEE:11112222:33334444:55556667:77889900:

PPPPP : pitch  ( maybe )
EEE   : volume (energy?)

K10 TOTAL 35bit(+2bit)

*/
	new_pitch  = pitchtable[get_bits( 1,5)<<1] / 256;
	new_energy = energytable[get_bits( 6,5)>>1] >> 6;

	/* 10 K's */
	new_k[0] = k1table[get_bits(11,5)];
	new_k[1] = k2table[get_bits(16,4)<<0];
	new_k[2] = k3table[get_bits(20,4)<<0];
	new_k[3] = k4table[get_bits(24,4)<<0];
	new_k[4] = k5table[get_bits(28,4)<<0];
	new_k[5] = k6table[get_bits(32,4)<<0];
	new_k[6] = k7table[get_bits(36,4)<<0];
	new_k[7] = k8table[get_bits(40,3)<<0];
	new_k[8] = k9table[get_bits(43,3)<<0];
	new_k[9] = k10table[get_bits(46,2)<<1];

	VLM5030_address+=6;
	return FR_SIZE;
}

/* decode and buffering data */
static void vlm5030_process(unsigned char *buffer, int size)
{
	int buf_count=0;
	int interp_effect;

	/* running */
	if( phase == PH_RUN )
	{
		/* playing speech */
		while (size > 0)
		{
			int current_val;

			/* check new interpolator or  new frame */
			if( sample_count == 0 )
			{
				sample_count = IP_SIZE;
				/* interpolator changes */
				if ( interp_count == 0 )
				{
					/* change to new frame */
					interp_count = parse_frame(); /* with change phase */
					if ( interp_count == 0 )
					{
						sample_count = 160; /* end -> stop time */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -