mirror of
https://github.com/xemu-project/xemu.git
synced 2025-02-20 04:11:28 +00:00
audio: cleanups, bugfixes (memory leaks).
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJZCtViAAoJEEy22O7T6HE40bIP/j6kwZjDyduyGQvrc8lnVkkO OmApS0v0cImxHaNLTgXNYBsEfkkDaVWnIl2bcVw9JkMY7Q2r0axXFM18XjzMPvPB NOFddYiOv0RnmCBnsGxdv+DXAMhg32SbrC8bKFxiFVDMhpZFDyvyjX7Ou+AnTRtV kB/a+emLJcrZNU+eo8DOV4FjBk/BcP4IjcA5hgihPMQHf21cG9xrzZPisbd91SRk 7vQU8uc0uuUJrGx1T7eRnKexMeLZ5citrhMpC3OLw+ESlvJthuntARbYFJMPl/s9 DqdCfHDNKdjlIi7NO3kq0xAprxKi1lE9lgybNHGr1miOfEqAsl+0y262sQ5fHG1e 0dXHxXXJYtwgCMIu9XydcZQLRCtxq+vglsG2dhBqYxlpH/6sxNbSfyMzxGzVgdxV ULHLdA+XYXUS2qS/GaKAVLiqmR018yHxGXEkd+h0xbUnY311Y6BdDAhFRrc/OGL/ IzzGg8cRFpyWemPfiy21vqaMoF/nvD+7ayaOOjMJAHDYct596Ed1y0KMlq7ulEpi 7yh8qWIV7D4FfKkGutxcWAoLfJ2+1mNrBFzVY4kK2OIR1XVLNA2cBfes9mRwCQjZ N5eXQQ6cgw8C5+aq5N1dZSCikaikjhylqRWhBukC4F1vw52q3ZpZqCxmgfthASyn +55StVoMMQtmmrkFYAVt =oBxJ -----END PGP SIGNATURE----- Merge remote-tracking branch 'kraxel/tags/pull-audio-20170504-1' into staging audio: cleanups, bugfixes (memory leaks). # gpg: Signature made Thu 04 May 2017 08:16:50 AM BST # gpg: using RSA key 0x4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * kraxel/tags/pull-audio-20170504-1: (30 commits) audio: Use ARRAY_SIZE from qemu/osdep.h audio: un-export OPLResetChip audio: Remove unused typedefs audio: UpdateHandler is not used anymore audio: IRQHandler is not used anymore audio: OPLSetUpdateHandler is not used anywhere audio: OPLSetIRQHandler is not used anywhere audio: GUSsample is int16_t audio: GUSword is uint16_t audio: GUSword is uint16_t audio: remove GUSchar audio: GUSbyte is uint8_t audio: Remove unused fields audio: Remove type field audio: Remove Unused OPL_TYPE_* audio: Unfold OPLSAMPLE audio: Remove INT32 audio: remove INT16 audio: Remove INT8 audio: remove UINT32 ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
bc56fd3a23
@ -2028,6 +2028,8 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
|
||||
sw = sw1;
|
||||
}
|
||||
QLIST_REMOVE (cap, entries);
|
||||
g_free (cap->hw.mix_buf);
|
||||
g_free (cap->buf);
|
||||
g_free (cap);
|
||||
}
|
||||
return;
|
||||
|
@ -88,6 +88,7 @@ static void wav_capture_destroy (void *opaque)
|
||||
WAVState *wav = opaque;
|
||||
|
||||
AUD_del_capture (wav->cap, wav);
|
||||
g_free (wav);
|
||||
}
|
||||
|
||||
static void wav_capture_info (void *opaque)
|
||||
|
@ -14,5 +14,3 @@ common-obj-$(CONFIG_PL041) += pl041.o lm4549.o
|
||||
common-obj-$(CONFIG_CS4231) += cs4231.o
|
||||
common-obj-$(CONFIG_MARVELL_88W8618) += marvell_88w8618.o
|
||||
common-obj-$(CONFIG_MILKYMIST) += milkymist-ac97.o
|
||||
|
||||
$(obj)/adlib.o $(obj)/fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
|
||||
|
@ -33,11 +33,7 @@
|
||||
|
||||
#define ADLIB_KILL_TIMERS 1
|
||||
|
||||
#ifdef HAS_YMF262
|
||||
#define ADLIB_DESC "Yamaha YMF262 (OPL3)"
|
||||
#else
|
||||
#define ADLIB_DESC "Yamaha YM3812 (OPL2)"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "qemu/timer.h"
|
||||
@ -50,14 +46,8 @@
|
||||
#define ldebug(...)
|
||||
#endif
|
||||
|
||||
#ifdef HAS_YMF262
|
||||
#include "ymf262.h"
|
||||
void YMF262UpdateOneQEMU (int which, INT16 *dst, int length);
|
||||
#define SHIFT 2
|
||||
#else
|
||||
#include "fmopl.h"
|
||||
#define SHIFT 1
|
||||
#endif
|
||||
|
||||
#define TYPE_ADLIB "adlib"
|
||||
#define ADLIB(obj) OBJECT_CHECK(AdlibState, (obj), TYPE_ADLIB)
|
||||
@ -80,9 +70,7 @@ typedef struct {
|
||||
SWVoiceOut *voice;
|
||||
int left, pos, samples;
|
||||
QEMUAudioTimeStamp ats;
|
||||
#ifndef HAS_YMF262
|
||||
FM_OPL *opl;
|
||||
#endif
|
||||
PortioList port_list;
|
||||
} AdlibState;
|
||||
|
||||
@ -90,11 +78,7 @@ static AdlibState *glob_adlib;
|
||||
|
||||
static void adlib_stop_opl_timer (AdlibState *s, size_t n)
|
||||
{
|
||||
#ifdef HAS_YMF262
|
||||
YMF262TimerOver (0, n);
|
||||
#else
|
||||
OPLTimerOver (s->opl, n);
|
||||
#endif
|
||||
s->ticking[n] = 0;
|
||||
}
|
||||
|
||||
@ -131,11 +115,7 @@ static void adlib_write(void *opaque, uint32_t nport, uint32_t val)
|
||||
|
||||
adlib_kill_timers (s);
|
||||
|
||||
#ifdef HAS_YMF262
|
||||
YMF262Write (0, a, val);
|
||||
#else
|
||||
OPLWrite (s->opl, a, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t adlib_read(void *opaque, uint32_t nport)
|
||||
@ -145,12 +125,8 @@ static uint32_t adlib_read(void *opaque, uint32_t nport)
|
||||
int a = nport & 3;
|
||||
|
||||
adlib_kill_timers (s);
|
||||
|
||||
#ifdef HAS_YMF262
|
||||
data = YMF262Read (0, a);
|
||||
#else
|
||||
data = OPLRead (s->opl, a);
|
||||
#endif
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -240,11 +216,7 @@ static void adlib_callback (void *opaque, int free)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAS_YMF262
|
||||
YMF262UpdateOneQEMU (0, s->mixbuf + s->pos * 2, samples);
|
||||
#else
|
||||
YM3812UpdateOne (s->opl, s->mixbuf + s->pos, samples);
|
||||
#endif
|
||||
|
||||
while (samples) {
|
||||
written = write_audio (s, samples);
|
||||
@ -263,14 +235,10 @@ static void adlib_callback (void *opaque, int free)
|
||||
|
||||
static void Adlib_fini (AdlibState *s)
|
||||
{
|
||||
#ifdef HAS_YMF262
|
||||
YMF262Shutdown ();
|
||||
#else
|
||||
if (s->opl) {
|
||||
OPLDestroy (s->opl);
|
||||
s->opl = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_free(s->mixbuf);
|
||||
|
||||
@ -297,17 +265,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
|
||||
}
|
||||
glob_adlib = s;
|
||||
|
||||
#ifdef HAS_YMF262
|
||||
if (YMF262Init (1, 14318180, s->freq)) {
|
||||
error_setg (errp, "YMF262Init %d failed", s->freq);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
YMF262SetTimerHandler (0, timer_handler, 0);
|
||||
s->enabled = 1;
|
||||
}
|
||||
#else
|
||||
s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, s->freq);
|
||||
s->opl = OPLCreate (3579545, s->freq);
|
||||
if (!s->opl) {
|
||||
error_setg (errp, "OPLCreate %d failed", s->freq);
|
||||
return;
|
||||
@ -316,7 +274,6 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
|
||||
OPLSetTimerHandler (s->opl, timer_handler, 0);
|
||||
s->enabled = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
as.freq = s->freq;
|
||||
as.nchannels = SHIFT;
|
||||
|
277
hw/audio/fmopl.c
277
hw/audio/fmopl.c
@ -30,21 +30,15 @@
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define HAS_YM3812 1
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <math.h>
|
||||
//#include "driver.h" /* use M.A.M.E. */
|
||||
#include "fmopl.h"
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
/* -------------------- for debug --------------------- */
|
||||
/* #define OPL_OUTPUT_LOG */
|
||||
#ifdef OPL_OUTPUT_LOG
|
||||
@ -124,7 +118,7 @@ static const int slot_array[32]=
|
||||
/* key scale level */
|
||||
/* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
|
||||
#define DV (EG_STEP/2)
|
||||
static const UINT32 KSL_TABLE[8*16]=
|
||||
static const uint32_t KSL_TABLE[8*16]=
|
||||
{
|
||||
/* OCT 0 */
|
||||
0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
|
||||
@ -172,7 +166,7 @@ static const UINT32 KSL_TABLE[8*16]=
|
||||
/* sustain lebel table (3db per step) */
|
||||
/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
|
||||
#define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
|
||||
static const INT32 SL_TABLE[16]={
|
||||
static const int32_t SL_TABLE[16]={
|
||||
SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
|
||||
SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
|
||||
};
|
||||
@ -182,22 +176,22 @@ static const INT32 SL_TABLE[16]={
|
||||
/* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
|
||||
/* TL_TABLE[ 0 to TL_MAX ] : plus section */
|
||||
/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
|
||||
static INT32 *TL_TABLE;
|
||||
static int32_t *TL_TABLE;
|
||||
|
||||
/* pointers to TL_TABLE with sinwave output offset */
|
||||
static INT32 **SIN_TABLE;
|
||||
static int32_t **SIN_TABLE;
|
||||
|
||||
/* LFO table */
|
||||
static INT32 *AMS_TABLE;
|
||||
static INT32 *VIB_TABLE;
|
||||
static int32_t *AMS_TABLE;
|
||||
static int32_t *VIB_TABLE;
|
||||
|
||||
/* envelope output curve table */
|
||||
/* attack + decay + OFF */
|
||||
static INT32 ENV_CURVE[2*EG_ENT+1];
|
||||
static int32_t ENV_CURVE[2*EG_ENT+1];
|
||||
|
||||
/* multiple table */
|
||||
#define ML 2
|
||||
static const UINT32 MUL_TABLE[16]= {
|
||||
static const uint32_t MUL_TABLE[16]= {
|
||||
/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
|
||||
0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
|
||||
8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
|
||||
@ -205,7 +199,7 @@ static const UINT32 MUL_TABLE[16]= {
|
||||
#undef ML
|
||||
|
||||
/* dummy attack / decay rate ( when rate == 0 ) */
|
||||
static INT32 RATE_0[16]=
|
||||
static int32_t RATE_0[16]=
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
/* -------------------- static state --------------------- */
|
||||
@ -221,14 +215,14 @@ static OPL_CH *S_CH;
|
||||
static OPL_CH *E_CH;
|
||||
static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
|
||||
|
||||
static INT32 outd[1];
|
||||
static INT32 ams;
|
||||
static INT32 vib;
|
||||
static INT32 *ams_table;
|
||||
static INT32 *vib_table;
|
||||
static INT32 amsIncr;
|
||||
static INT32 vibIncr;
|
||||
static INT32 feedback2; /* connect for SLOT 2 */
|
||||
static int32_t outd[1];
|
||||
static int32_t ams;
|
||||
static int32_t vib;
|
||||
static int32_t *ams_table;
|
||||
static int32_t *vib_table;
|
||||
static int32_t amsIncr;
|
||||
static int32_t vibIncr;
|
||||
static int32_t feedback2; /* connect for SLOT 2 */
|
||||
|
||||
/* log output level */
|
||||
#define LOG_ERR 3 /* ERROR */
|
||||
@ -262,8 +256,6 @@ static inline void OPL_STATUS_SET(FM_OPL *OPL,int flag)
|
||||
if(OPL->status & OPL->statusmask)
|
||||
{ /* IRQ on */
|
||||
OPL->status |= 0x80;
|
||||
/* callback user interrupt handler (IRQ is OFF to ON) */
|
||||
if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -278,8 +270,6 @@ static inline void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
|
||||
if (!(OPL->status & OPL->statusmask) )
|
||||
{
|
||||
OPL->status &= 0x7f;
|
||||
/* callback user interrupt handler (IRQ is ON to OFF) */
|
||||
if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -321,7 +311,7 @@ static inline void OPL_KEYOFF(OPL_SLOT *SLOT)
|
||||
|
||||
/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
|
||||
/* return : envelope output */
|
||||
static inline UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
|
||||
static inline uint32_t OPL_CALC_SLOT( OPL_SLOT *SLOT )
|
||||
{
|
||||
/* calcrate envelope generator */
|
||||
if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
|
||||
@ -361,7 +351,7 @@ static inline UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
|
||||
/* set algorithm connection */
|
||||
static void set_algorithm( OPL_CH *CH)
|
||||
{
|
||||
INT32 *carrier = &outd[0];
|
||||
int32_t *carrier = &outd[0];
|
||||
CH->connect1 = CH->CON ? carrier : &feedback2;
|
||||
CH->connect2 = carrier;
|
||||
}
|
||||
@ -453,7 +443,7 @@ static inline void set_sl_rr(FM_OPL *OPL,int slot,int v)
|
||||
/* ---------- calcrate one of channel ---------- */
|
||||
static inline void OPL_CALC_CH( OPL_CH *CH )
|
||||
{
|
||||
UINT32 env_out;
|
||||
uint32_t env_out;
|
||||
OPL_SLOT *SLOT;
|
||||
|
||||
feedback2 = 0;
|
||||
@ -498,9 +488,9 @@ static inline void OPL_CALC_CH( OPL_CH *CH )
|
||||
#define WHITE_NOISE_db 6.0
|
||||
static inline void OPL_CALC_RH( OPL_CH *CH )
|
||||
{
|
||||
UINT32 env_tam,env_sd,env_top,env_hh;
|
||||
uint32_t env_tam,env_sd,env_top,env_hh;
|
||||
int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP);
|
||||
INT32 tone8;
|
||||
int32_t tone8;
|
||||
|
||||
OPL_SLOT *SLOT;
|
||||
int env_out;
|
||||
@ -618,20 +608,20 @@ static int OPLOpenTable( void )
|
||||
double pom;
|
||||
|
||||
/* allocate dynamic tables */
|
||||
if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL)
|
||||
if( (TL_TABLE = malloc(TL_MAX*2*sizeof(int32_t))) == NULL)
|
||||
return 0;
|
||||
if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)
|
||||
if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(int32_t *))) == NULL)
|
||||
{
|
||||
free(TL_TABLE);
|
||||
return 0;
|
||||
}
|
||||
if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)
|
||||
if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(int32_t))) == NULL)
|
||||
{
|
||||
free(TL_TABLE);
|
||||
free(SIN_TABLE);
|
||||
return 0;
|
||||
}
|
||||
if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)
|
||||
if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(int32_t))) == NULL)
|
||||
{
|
||||
free(TL_TABLE);
|
||||
free(SIN_TABLE);
|
||||
@ -763,18 +753,15 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
|
||||
{
|
||||
case 0x01:
|
||||
/* wave selector enable */
|
||||
if(OPL->type&OPL_TYPE_WAVESEL)
|
||||
OPL->wavesel = v&0x20;
|
||||
if(!OPL->wavesel)
|
||||
{
|
||||
OPL->wavesel = v&0x20;
|
||||
if(!OPL->wavesel)
|
||||
/* preset compatible mode */
|
||||
int c;
|
||||
for(c=0;c<OPL->max_ch;c++)
|
||||
{
|
||||
/* preset compatible mode */
|
||||
int c;
|
||||
for(c=0;c<OPL->max_ch;c++)
|
||||
{
|
||||
OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
|
||||
OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
|
||||
}
|
||||
OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
|
||||
OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -791,8 +778,8 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
|
||||
}
|
||||
else
|
||||
{ /* set IRQ mask ,timer enable*/
|
||||
UINT8 st1 = v&1;
|
||||
UINT8 st2 = (v>>1)&1;
|
||||
uint8_t st1 = v&1;
|
||||
uint8_t st2 = (v>>1)&1;
|
||||
/* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
|
||||
OPL_STATUS_RESET(OPL,v&0x78);
|
||||
OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);
|
||||
@ -812,57 +799,6 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
|
||||
}
|
||||
}
|
||||
return;
|
||||
#if BUILD_Y8950
|
||||
case 0x06: /* Key Board OUT */
|
||||
if(OPL->type&OPL_TYPE_KEYBOARD)
|
||||
{
|
||||
if(OPL->keyboardhandler_w)
|
||||
OPL->keyboardhandler_w(OPL->keyboard_param,v);
|
||||
else
|
||||
LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n"));
|
||||
}
|
||||
return;
|
||||
case 0x07: /* DELTA-T control : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
|
||||
if(OPL->type&OPL_TYPE_ADPCM)
|
||||
YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
|
||||
return;
|
||||
case 0x08: /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
|
||||
OPL->mode = v;
|
||||
v&=0x1f; /* for DELTA-T unit */
|
||||
case 0x09: /* START ADD */
|
||||
case 0x0a:
|
||||
case 0x0b: /* STOP ADD */
|
||||
case 0x0c:
|
||||
case 0x0d: /* PRESCALE */
|
||||
case 0x0e:
|
||||
case 0x0f: /* ADPCM data */
|
||||
case 0x10: /* DELTA-N */
|
||||
case 0x11: /* DELTA-N */
|
||||
case 0x12: /* EG-CTRL */
|
||||
if(OPL->type&OPL_TYPE_ADPCM)
|
||||
YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
|
||||
return;
|
||||
#if 0
|
||||
case 0x15: /* DAC data */
|
||||
case 0x16:
|
||||
case 0x17: /* SHIFT */
|
||||
return;
|
||||
case 0x18: /* I/O CTRL (Direction) */
|
||||
if(OPL->type&OPL_TYPE_IO)
|
||||
OPL->portDirection = v&0x0f;
|
||||
return;
|
||||
case 0x19: /* I/O DATA */
|
||||
if(OPL->type&OPL_TYPE_IO)
|
||||
{
|
||||
OPL->portLatch = v;
|
||||
if(OPL->porthandler_w)
|
||||
OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
|
||||
}
|
||||
return;
|
||||
case 0x1a: /* PCM data */
|
||||
return;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 0x20: /* am,vib,ksr,eg type,mul */
|
||||
@ -891,7 +827,7 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
|
||||
case 0xbd:
|
||||
/* amsep,vibdep,r,bd,sd,tom,tc,hh */
|
||||
{
|
||||
UINT8 rkey = OPL->rhythm^v;
|
||||
uint8_t rkey = OPL->rhythm^v;
|
||||
OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
|
||||
OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
|
||||
OPL->rhythm = v&0x3f;
|
||||
@ -1032,20 +968,19 @@ static void OPL_UnLockTable(void)
|
||||
OPLCloseTable();
|
||||
}
|
||||
|
||||
#if (BUILD_YM3812 || BUILD_YM3526)
|
||||
/*******************************************************************************/
|
||||
/* YM3812 local section */
|
||||
/*******************************************************************************/
|
||||
|
||||
/* ---------- update one of chip ----------- */
|
||||
void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
|
||||
void YM3812UpdateOne(FM_OPL *OPL, int16_t *buffer, int length)
|
||||
{
|
||||
int i;
|
||||
int data;
|
||||
OPLSAMPLE *buf = buffer;
|
||||
UINT32 amsCnt = OPL->amsCnt;
|
||||
UINT32 vibCnt = OPL->vibCnt;
|
||||
UINT8 rhythm = OPL->rhythm&0x20;
|
||||
int16_t *buf = buffer;
|
||||
uint32_t amsCnt = OPL->amsCnt;
|
||||
uint32_t vibCnt = OPL->vibCnt;
|
||||
uint8_t rhythm = OPL->rhythm&0x20;
|
||||
OPL_CH *CH,*R_CH;
|
||||
|
||||
if( (void *)OPL != cur_chip ){
|
||||
@ -1095,72 +1030,9 @@ void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* (BUILD_YM3812 || BUILD_YM3526) */
|
||||
|
||||
#if BUILD_Y8950
|
||||
|
||||
void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
|
||||
{
|
||||
int i;
|
||||
int data;
|
||||
OPLSAMPLE *buf = buffer;
|
||||
UINT32 amsCnt = OPL->amsCnt;
|
||||
UINT32 vibCnt = OPL->vibCnt;
|
||||
UINT8 rhythm = OPL->rhythm&0x20;
|
||||
OPL_CH *CH,*R_CH;
|
||||
YM_DELTAT *DELTAT = OPL->deltat;
|
||||
|
||||
/* setup DELTA-T unit */
|
||||
YM_DELTAT_DECODE_PRESET(DELTAT);
|
||||
|
||||
if( (void *)OPL != cur_chip ){
|
||||
cur_chip = (void *)OPL;
|
||||
/* channel pointers */
|
||||
S_CH = OPL->P_CH;
|
||||
E_CH = &S_CH[9];
|
||||
/* rhythm slot */
|
||||
SLOT7_1 = &S_CH[7].SLOT[SLOT1];
|
||||
SLOT7_2 = &S_CH[7].SLOT[SLOT2];
|
||||
SLOT8_1 = &S_CH[8].SLOT[SLOT1];
|
||||
SLOT8_2 = &S_CH[8].SLOT[SLOT2];
|
||||
/* LFO state */
|
||||
amsIncr = OPL->amsIncr;
|
||||
vibIncr = OPL->vibIncr;
|
||||
ams_table = OPL->ams_table;
|
||||
vib_table = OPL->vib_table;
|
||||
}
|
||||
R_CH = rhythm ? &S_CH[6] : E_CH;
|
||||
for( i=0; i < length ; i++ )
|
||||
{
|
||||
/* channel A channel B channel C */
|
||||
/* LFO */
|
||||
ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
|
||||
vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
|
||||
outd[0] = 0;
|
||||
/* deltaT ADPCM */
|
||||
if( DELTAT->portstate )
|
||||
YM_DELTAT_ADPCM_CALC(DELTAT);
|
||||
/* FM part */
|
||||
for(CH=S_CH ; CH < R_CH ; CH++)
|
||||
OPL_CALC_CH(CH);
|
||||
/* Rythn part */
|
||||
if(rhythm)
|
||||
OPL_CALC_RH(S_CH);
|
||||
/* limit check */
|
||||
data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
|
||||
/* store to sound buffer */
|
||||
buf[i] = data >> OPL_OUTSB;
|
||||
}
|
||||
OPL->amsCnt = amsCnt;
|
||||
OPL->vibCnt = vibCnt;
|
||||
/* deltaT START flag */
|
||||
if( !DELTAT->portstate )
|
||||
OPL->status &= 0xfe;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ---------- reset one of chip ---------- */
|
||||
void OPLResetChip(FM_OPL *OPL)
|
||||
static void OPLResetChip(FM_OPL *OPL)
|
||||
{
|
||||
int c,s;
|
||||
int i;
|
||||
@ -1189,23 +1061,11 @@ void OPLResetChip(FM_OPL *OPL)
|
||||
CH->SLOT[s].evs = 0;
|
||||
}
|
||||
}
|
||||
#if BUILD_Y8950
|
||||
if(OPL->type&OPL_TYPE_ADPCM)
|
||||
{
|
||||
YM_DELTAT *DELTAT = OPL->deltat;
|
||||
|
||||
DELTAT->freqbase = OPL->freqbase;
|
||||
DELTAT->output_pointer = outd;
|
||||
DELTAT->portshift = 5;
|
||||
DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;
|
||||
YM_DELTAT_ADPCM_Reset(DELTAT,0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ---------- Create one of vietual YM3812 ---------- */
|
||||
/* 'rate' is sampling rate and 'bufsiz' is the size of the */
|
||||
FM_OPL *OPLCreate(int type, int clock, int rate)
|
||||
FM_OPL *OPLCreate(int clock, int rate)
|
||||
{
|
||||
char *ptr;
|
||||
FM_OPL *OPL;
|
||||
@ -1216,9 +1076,6 @@ FM_OPL *OPLCreate(int type, int clock, int rate)
|
||||
/* allocate OPL state space */
|
||||
state_size = sizeof(FM_OPL);
|
||||
state_size += sizeof(OPL_CH)*max_ch;
|
||||
#if BUILD_Y8950
|
||||
if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
|
||||
#endif
|
||||
/* allocate memory block */
|
||||
ptr = malloc(state_size);
|
||||
if(ptr==NULL) return NULL;
|
||||
@ -1226,11 +1083,7 @@ FM_OPL *OPLCreate(int type, int clock, int rate)
|
||||
memset(ptr,0,state_size);
|
||||
OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
|
||||
OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
|
||||
#if BUILD_Y8950
|
||||
if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);
|
||||
#endif
|
||||
/* set channel state pointer */
|
||||
OPL->type = type;
|
||||
OPL->clock = clock;
|
||||
OPL->rate = rate;
|
||||
OPL->max_ch = max_ch;
|
||||
@ -1280,31 +1133,7 @@ void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOff
|
||||
OPL->TimerHandler = TimerHandler;
|
||||
OPL->TimerParam = channelOffset;
|
||||
}
|
||||
void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
|
||||
{
|
||||
OPL->IRQHandler = IRQHandler;
|
||||
OPL->IRQParam = param;
|
||||
}
|
||||
void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param)
|
||||
{
|
||||
OPL->UpdateHandler = UpdateHandler;
|
||||
OPL->UpdateParam = param;
|
||||
}
|
||||
#if BUILD_Y8950
|
||||
void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param)
|
||||
{
|
||||
OPL->porthandler_w = PortHandler_w;
|
||||
OPL->porthandler_r = PortHandler_r;
|
||||
OPL->port_param = param;
|
||||
}
|
||||
|
||||
void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param)
|
||||
{
|
||||
OPL->keyboardhandler_w = KeyboardHandler_w;
|
||||
OPL->keyboardhandler_r = KeyboardHandler_r;
|
||||
OPL->keyboard_param = param;
|
||||
}
|
||||
#endif
|
||||
/* ---------- YM3812 I/O interface ---------- */
|
||||
int OPLWrite(FM_OPL *OPL,int a,int v)
|
||||
{
|
||||
@ -1314,7 +1143,6 @@ int OPLWrite(FM_OPL *OPL,int a,int v)
|
||||
}
|
||||
else
|
||||
{ /* data port */
|
||||
if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
|
||||
#ifdef OPL_OUTPUT_LOG
|
||||
if(opl_dbg_fp)
|
||||
{
|
||||
@ -1338,28 +1166,12 @@ unsigned char OPLRead(FM_OPL *OPL,int a)
|
||||
switch(OPL->address)
|
||||
{
|
||||
case 0x05: /* KeyBoard IN */
|
||||
if(OPL->type&OPL_TYPE_KEYBOARD)
|
||||
{
|
||||
if(OPL->keyboardhandler_r)
|
||||
return OPL->keyboardhandler_r(OPL->keyboard_param);
|
||||
else {
|
||||
LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n"));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#if 0
|
||||
case 0x0f: /* ADPCM-DATA */
|
||||
return 0;
|
||||
#endif
|
||||
case 0x19: /* I/O DATA */
|
||||
if(OPL->type&OPL_TYPE_IO)
|
||||
{
|
||||
if(OPL->porthandler_r)
|
||||
return OPL->porthandler_r(OPL->port_param);
|
||||
else {
|
||||
LOG(LOG_WAR,("OPL:read unmapped I/O port\n"));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case 0x1a: /* PCM-DATA */
|
||||
return 0;
|
||||
@ -1380,7 +1192,6 @@ int OPLTimerOver(FM_OPL *OPL,int c)
|
||||
if( OPL->mode & 0x80 )
|
||||
{ /* CSM mode total level latch and auto key on */
|
||||
int ch;
|
||||
if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
|
||||
for(ch=0;ch<9;ch++)
|
||||
CSMKeyControll( &OPL->P_CH[ch] );
|
||||
}
|
||||
|
175
hw/audio/fmopl.h
175
hw/audio/fmopl.h
@ -1,174 +1,103 @@
|
||||
#ifndef FMOPL_H
|
||||
#define FMOPL_H
|
||||
|
||||
/* --- select emulation chips --- */
|
||||
#define BUILD_YM3812 (HAS_YM3812)
|
||||
//#define BUILD_YM3526 (HAS_YM3526)
|
||||
//#define BUILD_Y8950 (HAS_Y8950)
|
||||
|
||||
/* --- system optimize --- */
|
||||
/* select bit size of output : 8 or 16 */
|
||||
#define OPL_OUTPUT_BIT 16
|
||||
|
||||
/* compiler dependence */
|
||||
#ifndef OSD_CPU_H
|
||||
#define OSD_CPU_H
|
||||
typedef unsigned char UINT8; /* unsigned 8bit */
|
||||
typedef unsigned short UINT16; /* unsigned 16bit */
|
||||
typedef unsigned int UINT32; /* unsigned 32bit */
|
||||
typedef signed char INT8; /* signed 8bit */
|
||||
typedef signed short INT16; /* signed 16bit */
|
||||
typedef signed int INT32; /* signed 32bit */
|
||||
#endif
|
||||
|
||||
#if (OPL_OUTPUT_BIT==16)
|
||||
typedef INT16 OPLSAMPLE;
|
||||
#endif
|
||||
#if (OPL_OUTPUT_BIT==8)
|
||||
typedef unsigned char OPLSAMPLE;
|
||||
#endif
|
||||
|
||||
|
||||
#if BUILD_Y8950
|
||||
#include "ymdeltat.h"
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
|
||||
typedef void (*OPL_IRQHANDLER)(int param,int irq);
|
||||
typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
|
||||
typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
|
||||
typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
|
||||
|
||||
/* !!!!! here is private section , do not access there member direct !!!!! */
|
||||
|
||||
#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
|
||||
#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */
|
||||
#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */
|
||||
#define OPL_TYPE_IO 0x08 /* I/O port */
|
||||
|
||||
/* Saving is necessary for member of the 'R' mark for suspend/resume */
|
||||
/* ---------- OPL one of slot ---------- */
|
||||
typedef struct fm_opl_slot {
|
||||
INT32 TL; /* total level :TL << 8 */
|
||||
INT32 TLL; /* adjusted now TL */
|
||||
UINT8 KSR; /* key scale rate :(shift down bit) */
|
||||
INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */
|
||||
INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */
|
||||
INT32 SL; /* sustin level :SL_TALBE[SL] */
|
||||
INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */
|
||||
UINT8 ksl; /* keyscale level :(shift down bits) */
|
||||
UINT8 ksr; /* key scale rate :kcode>>KSR */
|
||||
UINT32 mul; /* multiple :ML_TABLE[ML] */
|
||||
UINT32 Cnt; /* frequency count : */
|
||||
UINT32 Incr; /* frequency step : */
|
||||
int32_t TL; /* total level :TL << 8 */
|
||||
int32_t TLL; /* adjusted now TL */
|
||||
uint8_t KSR; /* key scale rate :(shift down bit) */
|
||||
int32_t *AR; /* attack rate :&AR_TABLE[AR<<2] */
|
||||
int32_t *DR; /* decay rate :&DR_TALBE[DR<<2] */
|
||||
int32_t SL; /* sustin level :SL_TALBE[SL] */
|
||||
int32_t *RR; /* release rate :&DR_TABLE[RR<<2] */
|
||||
uint8_t ksl; /* keyscale level :(shift down bits) */
|
||||
uint8_t ksr; /* key scale rate :kcode>>KSR */
|
||||
uint32_t mul; /* multiple :ML_TABLE[ML] */
|
||||
uint32_t Cnt; /* frequency count : */
|
||||
uint32_t Incr; /* frequency step : */
|
||||
/* envelope generator state */
|
||||
UINT8 eg_typ; /* envelope type flag */
|
||||
UINT8 evm; /* envelope phase */
|
||||
INT32 evc; /* envelope counter */
|
||||
INT32 eve; /* envelope counter end point */
|
||||
INT32 evs; /* envelope counter step */
|
||||
INT32 evsa; /* envelope step for AR :AR[ksr] */
|
||||
INT32 evsd; /* envelope step for DR :DR[ksr] */
|
||||
INT32 evsr; /* envelope step for RR :RR[ksr] */
|
||||
uint8_t eg_typ; /* envelope type flag */
|
||||
uint8_t evm; /* envelope phase */
|
||||
int32_t evc; /* envelope counter */
|
||||
int32_t eve; /* envelope counter end point */
|
||||
int32_t evs; /* envelope counter step */
|
||||
int32_t evsa; /* envelope step for AR :AR[ksr] */
|
||||
int32_t evsd; /* envelope step for DR :DR[ksr] */
|
||||
int32_t evsr; /* envelope step for RR :RR[ksr] */
|
||||
/* LFO */
|
||||
UINT8 ams; /* ams flag */
|
||||
UINT8 vib; /* vibrate flag */
|
||||
uint8_t ams; /* ams flag */
|
||||
uint8_t vib; /* vibrate flag */
|
||||
/* wave selector */
|
||||
INT32 **wavetable;
|
||||
int32_t **wavetable;
|
||||
}OPL_SLOT;
|
||||
|
||||
/* ---------- OPL one of channel ---------- */
|
||||
typedef struct fm_opl_channel {
|
||||
OPL_SLOT SLOT[2];
|
||||
UINT8 CON; /* connection type */
|
||||
UINT8 FB; /* feed back :(shift down bit) */
|
||||
INT32 *connect1; /* slot1 output pointer */
|
||||
INT32 *connect2; /* slot2 output pointer */
|
||||
INT32 op1_out[2]; /* slot1 output for selfeedback */
|
||||
uint8_t CON; /* connection type */
|
||||
uint8_t FB; /* feed back :(shift down bit) */
|
||||
int32_t *connect1; /* slot1 output pointer */
|
||||
int32_t *connect2; /* slot2 output pointer */
|
||||
int32_t op1_out[2]; /* slot1 output for selfeedback */
|
||||
/* phase generator state */
|
||||
UINT32 block_fnum; /* block+fnum : */
|
||||
UINT8 kcode; /* key code : KeyScaleCode */
|
||||
UINT32 fc; /* Freq. Increment base */
|
||||
UINT32 ksl_base; /* KeyScaleLevel Base step */
|
||||
UINT8 keyon; /* key on/off flag */
|
||||
uint32_t block_fnum; /* block+fnum : */
|
||||
uint8_t kcode; /* key code : KeyScaleCode */
|
||||
uint32_t fc; /* Freq. Increment base */
|
||||
uint32_t ksl_base; /* KeyScaleLevel Base step */
|
||||
uint8_t keyon; /* key on/off flag */
|
||||
} OPL_CH;
|
||||
|
||||
/* OPL state */
|
||||
typedef struct fm_opl_f {
|
||||
UINT8 type; /* chip type */
|
||||
int clock; /* master clock (Hz) */
|
||||
int rate; /* sampling rate (Hz) */
|
||||
double freqbase; /* frequency base */
|
||||
double TimerBase; /* Timer base time (==sampling time) */
|
||||
UINT8 address; /* address register */
|
||||
UINT8 status; /* status flag */
|
||||
UINT8 statusmask; /* status mask */
|
||||
UINT32 mode; /* Reg.08 : CSM , notesel,etc. */
|
||||
uint8_t address; /* address register */
|
||||
uint8_t status; /* status flag */
|
||||
uint8_t statusmask; /* status mask */
|
||||
uint32_t mode; /* Reg.08 : CSM , notesel,etc. */
|
||||
/* Timer */
|
||||
int T[2]; /* timer counter */
|
||||
UINT8 st[2]; /* timer enable */
|
||||
uint8_t st[2]; /* timer enable */
|
||||
/* FM channel slots */
|
||||
OPL_CH *P_CH; /* pointer of CH */
|
||||
int max_ch; /* maximum channel */
|
||||
/* Rhythm sention */
|
||||
UINT8 rhythm; /* Rhythm mode , key flag */
|
||||
#if BUILD_Y8950
|
||||
/* Delta-T ADPCM unit (Y8950) */
|
||||
YM_DELTAT *deltat; /* DELTA-T ADPCM */
|
||||
#endif
|
||||
/* Keyboard / I/O interface unit (Y8950) */
|
||||
UINT8 portDirection;
|
||||
UINT8 portLatch;
|
||||
OPL_PORTHANDLER_R porthandler_r;
|
||||
OPL_PORTHANDLER_W porthandler_w;
|
||||
int port_param;
|
||||
OPL_PORTHANDLER_R keyboardhandler_r;
|
||||
OPL_PORTHANDLER_W keyboardhandler_w;
|
||||
int keyboard_param;
|
||||
uint8_t rhythm; /* Rhythm mode , key flag */
|
||||
/* time tables */
|
||||
INT32 AR_TABLE[75]; /* atttack rate tables */
|
||||
INT32 DR_TABLE[75]; /* decay rate tables */
|
||||
UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */
|
||||
int32_t AR_TABLE[75]; /* atttack rate tables */
|
||||
int32_t DR_TABLE[75]; /* decay rate tables */
|
||||
uint32_t FN_TABLE[1024]; /* fnumber -> increment counter */
|
||||
/* LFO */
|
||||
INT32 *ams_table;
|
||||
INT32 *vib_table;
|
||||
INT32 amsCnt;
|
||||
INT32 amsIncr;
|
||||
INT32 vibCnt;
|
||||
INT32 vibIncr;
|
||||
int32_t *ams_table;
|
||||
int32_t *vib_table;
|
||||
int32_t amsCnt;
|
||||
int32_t amsIncr;
|
||||
int32_t vibCnt;
|
||||
int32_t vibIncr;
|
||||
/* wave selector enable flag */
|
||||
UINT8 wavesel;
|
||||
uint8_t wavesel;
|
||||
/* external event callback handler */
|
||||
OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
|
||||
int TimerParam; /* TIMER parameter */
|
||||
OPL_IRQHANDLER IRQHandler; /* IRQ handler */
|
||||
int IRQParam; /* IRQ parameter */
|
||||
OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */
|
||||
int UpdateParam; /* stream update parameter */
|
||||
} FM_OPL;
|
||||
|
||||
/* ---------- Generic interface section ---------- */
|
||||
#define OPL_TYPE_YM3526 (0)
|
||||
#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
|
||||
#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
|
||||
|
||||
FM_OPL *OPLCreate(int type, int clock, int rate);
|
||||
FM_OPL *OPLCreate(int clock, int rate);
|
||||
void OPLDestroy(FM_OPL *OPL);
|
||||
void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset);
|
||||
void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param);
|
||||
void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param);
|
||||
/* Y8950 port handlers */
|
||||
void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param);
|
||||
void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param);
|
||||
|
||||
void OPLResetChip(FM_OPL *OPL);
|
||||
int OPLWrite(FM_OPL *OPL,int a,int v);
|
||||
unsigned char OPLRead(FM_OPL *OPL,int a);
|
||||
int OPLTimerOver(FM_OPL *OPL,int c);
|
||||
|
||||
/* YM3626/YM3812 local section */
|
||||
void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
|
||||
|
||||
void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
|
||||
|
||||
void YM3812UpdateOne(FM_OPL *OPL, int16_t *buffer, int length);
|
||||
#endif
|
||||
|
@ -53,7 +53,7 @@ typedef struct GUSState {
|
||||
uint32_t freq;
|
||||
uint32_t port;
|
||||
int pos, left, shift, irqs;
|
||||
GUSsample *mixbuf;
|
||||
int16_t *mixbuf;
|
||||
uint8_t himem[1024 * 1024 + 32 + 4096];
|
||||
int samples;
|
||||
SWVoiceOut *voice;
|
||||
|
@ -25,26 +25,10 @@
|
||||
#ifndef GUSEMU_H
|
||||
#define GUSEMU_H
|
||||
|
||||
/* data types (need to be adjusted if neither a VC6 nor a C99 compatible compiler is used) */
|
||||
|
||||
#if defined _WIN32 && defined _MSC_VER /* doesn't support other win32 compilers yet, do it yourself... */
|
||||
typedef unsigned char GUSbyte;
|
||||
typedef unsigned short GUSword;
|
||||
typedef unsigned int GUSdword;
|
||||
typedef signed char GUSchar;
|
||||
typedef signed short GUSsample;
|
||||
#else
|
||||
typedef int8_t GUSchar;
|
||||
typedef uint8_t GUSbyte;
|
||||
typedef uint16_t GUSword;
|
||||
typedef uint32_t GUSdword;
|
||||
typedef int16_t GUSsample;
|
||||
#endif
|
||||
|
||||
typedef struct _GUSEmuState
|
||||
{
|
||||
GUSbyte *himemaddr; /* 1024*1024 bytes used for storing uploaded samples (+32 additional bytes for read padding) */
|
||||
GUSbyte *gusdatapos; /* (gusdataend-gusdata) bytes used for storing emulated GF1/mixer register states (32*32+4 bytes in initial GUSemu32 version) */
|
||||
uint8_t *himemaddr; /* 1024*1024 bytes used for storing uploaded samples (+32 additional bytes for read padding) */
|
||||
uint8_t *gusdatapos; /* (gusdataend-gusdata) bytes used for storing emulated GF1/mixer register states (32*32+4 bytes in initial GUSemu32 version) */
|
||||
uint32_t gusirq;
|
||||
uint32_t gusdma;
|
||||
unsigned int timer1fraction;
|
||||
@ -92,7 +76,7 @@ void gus_dma_transferdata(GUSEmuState *state, char *dma_addr, unsigned int count
|
||||
/* If the interrupts are asynchronous, it may be needed to use a separate thread mixing into a temporary */
|
||||
/* audio buffer in order to avoid quality loss caused by large numsamples and elapsed_time values. */
|
||||
|
||||
void gus_mixvoices(GUSEmuState *state, unsigned int playback_freq, unsigned int numsamples, GUSsample *bufferpos);
|
||||
void gus_mixvoices(GUSEmuState *state, unsigned int playback_freq, unsigned int numsamples, int16_t *bufferpos);
|
||||
/* recommended range: 10 < numsamples < 100 */
|
||||
/* lower values may result in increased rounding error, higher values often cause audible timing delays */
|
||||
|
||||
|
@ -31,15 +31,15 @@
|
||||
#include "gusemu.h"
|
||||
|
||||
#define GUSregb(position) (* (gusptr+(position)))
|
||||
#define GUSregw(position) (*(GUSword *) (gusptr+(position)))
|
||||
#define GUSregd(position) (*(GUSdword *)(gusptr+(position)))
|
||||
#define GUSregw(position) (*(uint16_t *) (gusptr+(position)))
|
||||
#define GUSregd(position) (*(uint16_t *)(gusptr+(position)))
|
||||
|
||||
/* size given in bytes */
|
||||
unsigned int gus_read(GUSEmuState * state, int port, int size)
|
||||
{
|
||||
int value_read = 0;
|
||||
|
||||
GUSbyte *gusptr;
|
||||
uint8_t *gusptr;
|
||||
gusptr = state->gusdatapos;
|
||||
GUSregd(portaccesses)++;
|
||||
|
||||
@ -125,7 +125,7 @@ unsigned int gus_read(GUSEmuState * state, int port, int size)
|
||||
if (!GUSregb(IRQStatReg2x6))
|
||||
GUS_irqclear(state, state->gusirq);
|
||||
}
|
||||
return (GUSbyte) value_read;
|
||||
return (uint8_t) value_read;
|
||||
/* DramDMAmemPosReg */
|
||||
/* case 0x42: value_read=GUSregw(GUS42DMAStart); break;*/
|
||||
/* 43h+44h write only */
|
||||
@ -173,12 +173,12 @@ unsigned int gus_read(GUSEmuState * state, int port, int size)
|
||||
value_read = value_read >> 8;
|
||||
value_read &= 0xff;
|
||||
}
|
||||
return (GUSword) value_read;
|
||||
return (uint16_t) value_read;
|
||||
/* case 0x306: */ /* Mixer/Version info */
|
||||
/* return 0xff; */ /* Pre 3.6 boards, ICS mixer NOT present */
|
||||
case 0x307: /* DRAMaccess */
|
||||
{
|
||||
GUSbyte *adr;
|
||||
uint8_t *adr;
|
||||
adr = state->himemaddr + (GUSregd(GUSDRAMPOS24bit) & 0xfffff);
|
||||
return *adr;
|
||||
}
|
||||
@ -189,14 +189,14 @@ unsigned int gus_read(GUSEmuState * state, int port, int size)
|
||||
|
||||
void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
{
|
||||
GUSbyte *gusptr;
|
||||
uint8_t *gusptr;
|
||||
gusptr = state->gusdatapos;
|
||||
GUSregd(portaccesses)++;
|
||||
|
||||
switch (port & 0xff0f)
|
||||
{
|
||||
case 0x200: /* MixerCtrlReg */
|
||||
GUSregb(MixerCtrlReg2x0) = (GUSbyte) data;
|
||||
GUSregb(MixerCtrlReg2x0) = (uint8_t) data;
|
||||
break;
|
||||
case 0x206: /* IRQstatReg / SB2x6IRQ */
|
||||
if (GUSregb(GUS45TimerCtrl) & 0x20) /* SB IRQ enabled? -> set 2x6IRQ bit */
|
||||
@ -208,7 +208,7 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
break;
|
||||
case 0x308: /* AdLib 388h */
|
||||
case 0x208: /* AdLibCommandReg */
|
||||
GUSregb(AdLibCommand2xA) = (GUSbyte) data;
|
||||
GUSregb(AdLibCommand2xA) = (uint8_t) data;
|
||||
break;
|
||||
case 0x309: /* AdLib 389h */
|
||||
case 0x209: /* AdLibDataReg */
|
||||
@ -217,11 +217,11 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
if (data & 0x80)
|
||||
GUSregb(TimerStatus2x8) &= 0x1f; /* AdLib IRQ reset? -> clear maskable adl. timer int regs */
|
||||
else
|
||||
GUSregb(TimerDataReg2x9) = (GUSbyte) data;
|
||||
GUSregb(TimerDataReg2x9) = (uint8_t) data;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUSregb(AdLibData2x9) = (GUSbyte) data;
|
||||
GUSregb(AdLibData2x9) = (uint8_t) data;
|
||||
if (GUSregb(GUS45TimerCtrl) & 0x02)
|
||||
{
|
||||
GUSregb(TimerStatus2x8) |= 0x01;
|
||||
@ -231,16 +231,16 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
}
|
||||
break;
|
||||
case 0x20A:
|
||||
GUSregb(AdLibStatus2x8) = (GUSbyte) data;
|
||||
GUSregb(AdLibStatus2x8) = (uint8_t) data;
|
||||
break; /* AdLibStatus2x8 */
|
||||
case 0x20B: /* GUS hidden registers */
|
||||
switch (GUSregb(RegCtrl_2xF) & 0x7)
|
||||
{
|
||||
case 0:
|
||||
if (GUSregb(MixerCtrlReg2x0) & 0x40)
|
||||
GUSregb(IRQ_2xB) = (GUSbyte) data; /* control register select bit */
|
||||
GUSregb(IRQ_2xB) = (uint8_t) data; /* control register select bit */
|
||||
else
|
||||
GUSregb(DMA_2xB) = (GUSbyte) data;
|
||||
GUSregb(DMA_2xB) = (uint8_t) data;
|
||||
break;
|
||||
/* case 1-4: general purpose emulation regs */
|
||||
case 5: /* clear stat reg 2xF */
|
||||
@ -249,7 +249,7 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
GUS_irqclear(state, state->gusirq);
|
||||
break;
|
||||
case 6: /* Jumper reg (Joystick/MIDI enable) */
|
||||
GUSregb(Jumper_2xB) = (GUSbyte) data;
|
||||
GUSregb(Jumper_2xB) = (uint8_t) data;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
@ -262,20 +262,20 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
GUS_irqrequest(state, state->gusirq, 1);
|
||||
}
|
||||
case 0x20D: /* SB2xCd no IRQ */
|
||||
GUSregb(SB2xCd) = (GUSbyte) data;
|
||||
GUSregb(SB2xCd) = (uint8_t) data;
|
||||
break;
|
||||
case 0x20E: /* SB2xE */
|
||||
GUSregb(SB2xE) = (GUSbyte) data;
|
||||
GUSregb(SB2xE) = (uint8_t) data;
|
||||
break;
|
||||
case 0x20F:
|
||||
GUSregb(RegCtrl_2xF) = (GUSbyte) data;
|
||||
GUSregb(RegCtrl_2xF) = (uint8_t) data;
|
||||
break; /* CtrlReg2xF */
|
||||
case 0x302: /* VoiceSelReg */
|
||||
GUSregb(VoiceSelReg3x2) = (GUSbyte) data;
|
||||
GUSregb(VoiceSelReg3x2) = (uint8_t) data;
|
||||
break;
|
||||
case 0x303: /* FunkSelReg */
|
||||
GUSregb(FunkSelReg3x3) = (GUSbyte) data;
|
||||
if ((GUSbyte) data == 0x8f) /* set irqstatreg, get voicereg and clear IRQ */
|
||||
GUSregb(FunkSelReg3x3) = (uint8_t) data;
|
||||
if ((uint8_t) data == 0x8f) /* set irqstatreg, get voicereg and clear IRQ */
|
||||
{
|
||||
int voice;
|
||||
if (GUSregd(voicewavetableirq)) /* WavetableIRQ */
|
||||
@ -318,15 +318,15 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
case 0x304:
|
||||
case 0x305:
|
||||
{
|
||||
GUSword writedata = (GUSword) data;
|
||||
GUSword readmask = 0x0000;
|
||||
uint16_t writedata = (uint16_t) data;
|
||||
uint16_t readmask = 0x0000;
|
||||
if (size == 1)
|
||||
{
|
||||
readmask = 0xff00;
|
||||
writedata &= 0xff;
|
||||
if ((port & 0xff0f) == 0x305)
|
||||
{
|
||||
writedata = (GUSword) (writedata << 8);
|
||||
writedata = (uint16_t) (writedata << 8);
|
||||
readmask = 0x00ff;
|
||||
}
|
||||
}
|
||||
@ -353,17 +353,17 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
break; /* reset flag active? */
|
||||
offset = 2 * (GUSregb(FunkSelReg3x3) & 0x0f);
|
||||
offset += (GUSregb(VoiceSelReg3x2) & 0x1f) << 5; /* = Voice*32 + Funktion*2 */
|
||||
GUSregw(offset) = (GUSword) ((GUSregw(offset) & readmask) | writedata);
|
||||
GUSregw(offset) = (uint16_t) ((GUSregw(offset) & readmask) | writedata);
|
||||
}
|
||||
break;
|
||||
/* voice unspecific functions */
|
||||
case 0x0e: /* NumVoices */
|
||||
GUSregb(NumVoices) = (GUSbyte) data;
|
||||
GUSregb(NumVoices) = (uint8_t) data;
|
||||
break;
|
||||
/* case 0x0f: */ /* read only */
|
||||
/* common functions */
|
||||
case 0x41: /* DramDMAContrReg */
|
||||
GUSregb(GUS41DMACtrl) = (GUSbyte) data;
|
||||
GUSregb(GUS41DMACtrl) = (uint8_t) data;
|
||||
if (data & 0x01)
|
||||
GUS_dmarequest(state);
|
||||
break;
|
||||
@ -380,7 +380,7 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
(GUSregd(GUSDRAMPOS24bit) & 0xffff) | ((data & 0x0f) << 16);
|
||||
break;
|
||||
case 0x45: /* TCtrlReg */
|
||||
GUSregb(GUS45TimerCtrl) = (GUSbyte) data;
|
||||
GUSregb(GUS45TimerCtrl) = (uint8_t) data;
|
||||
if (!(data & 0x20))
|
||||
GUSregb(TimerStatus2x8) &= 0xe7; /* sb IRQ dis? -> clear 2x8/2xC sb IRQ flags */
|
||||
if (!(data & 0x02))
|
||||
@ -434,18 +434,18 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
GUS_irqclear(state, state->gusirq);
|
||||
break;
|
||||
case 0x46: /* Counter1 */
|
||||
GUSregb(GUS46Counter1) = (GUSbyte) data;
|
||||
GUSregb(GUS46Counter1) = (uint8_t) data;
|
||||
break;
|
||||
case 0x47: /* Counter2 */
|
||||
GUSregb(GUS47Counter2) = (GUSbyte) data;
|
||||
GUSregb(GUS47Counter2) = (uint8_t) data;
|
||||
break;
|
||||
/* case 0x48: */ /* sampling freq reg not emulated (same as interwave) */
|
||||
case 0x49: /* SampCtrlReg */
|
||||
GUSregb(GUS49SampCtrl) = (GUSbyte) data;
|
||||
GUSregb(GUS49SampCtrl) = (uint8_t) data;
|
||||
break;
|
||||
/* case 0x4b: */ /* joystick trim not emulated */
|
||||
case 0x4c: /* GUSreset */
|
||||
GUSregb(GUS4cReset) = (GUSbyte) data;
|
||||
GUSregb(GUS4cReset) = (uint8_t) data;
|
||||
if (!(GUSregb(GUS4cReset) & 1)) /* reset... */
|
||||
{
|
||||
GUSregd(voicewavetableirq) = 0;
|
||||
@ -471,9 +471,9 @@ void gus_write(GUSEmuState * state, int port, int size, unsigned int data)
|
||||
break;
|
||||
case 0x307: /* DRAMaccess */
|
||||
{
|
||||
GUSbyte *adr;
|
||||
uint8_t *adr;
|
||||
adr = state->himemaddr + (GUSregd(GUSDRAMPOS24bit) & 0xfffff);
|
||||
*adr = (GUSbyte) data;
|
||||
*adr = (uint8_t) data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -510,7 +510,7 @@ void gus_dma_transferdata(GUSEmuState * state, char *dma_addr, unsigned int coun
|
||||
char *srcaddr;
|
||||
char *destaddr;
|
||||
char msbmask = 0;
|
||||
GUSbyte *gusptr;
|
||||
uint8_t *gusptr;
|
||||
gusptr = state->gusdatapos;
|
||||
|
||||
srcaddr = dma_addr; /* system memory address */
|
||||
@ -521,8 +521,8 @@ void gus_dma_transferdata(GUSEmuState * state, char *dma_addr, unsigned int coun
|
||||
destaddr = (char *) state->himemaddr + offset; /* wavetable RAM address */
|
||||
}
|
||||
|
||||
GUSregw(GUS42DMAStart) += (GUSword) (count >> 4); /* ToDo: add 16bit GUS page limit? */
|
||||
GUSregb(GUS50DMAHigh) = (GUSbyte) ((count + GUSregb(GUS50DMAHigh)) & 0xf); /* ToDo: add 16bit GUS page limit? */
|
||||
GUSregw(GUS42DMAStart) += (uint16_t) (count >> 4); /* ToDo: add 16bit GUS page limit? */
|
||||
GUSregb(GUS50DMAHigh) = (uint8_t) ((count + GUSregb(GUS50DMAHigh)) & 0xf); /* ToDo: add 16bit GUS page limit? */
|
||||
|
||||
if (GUSregb(GUS41DMACtrl) & 0x02) /* direction, 0 := sysram->gusram */
|
||||
{
|
||||
|
@ -27,26 +27,26 @@
|
||||
#include "gustate.h"
|
||||
|
||||
#define GUSregb(position) (* (gusptr+(position)))
|
||||
#define GUSregw(position) (*(GUSword *) (gusptr+(position)))
|
||||
#define GUSregd(position) (*(GUSdword *)(gusptr+(position)))
|
||||
#define GUSregw(position) (*(uint16_t *) (gusptr+(position)))
|
||||
#define GUSregd(position) (*(uint16_t *)(gusptr+(position)))
|
||||
|
||||
#define GUSvoice(position) (*(GUSword *)(voiceptr+(position)))
|
||||
#define GUSvoice(position) (*(uint16_t *)(voiceptr+(position)))
|
||||
|
||||
/* samples are always 16bit stereo (4 bytes each, first right then left interleaved) */
|
||||
void gus_mixvoices(GUSEmuState * state, unsigned int playback_freq, unsigned int numsamples,
|
||||
GUSsample *bufferpos)
|
||||
int16_t *bufferpos)
|
||||
{
|
||||
/* note that byte registers are stored in the upper half of each voice register! */
|
||||
GUSbyte *gusptr;
|
||||
uint8_t *gusptr;
|
||||
int Voice;
|
||||
GUSword *voiceptr;
|
||||
uint16_t *voiceptr;
|
||||
|
||||
unsigned int count;
|
||||
for (count = 0; count < numsamples * 2; count++)
|
||||
*(bufferpos + count) = 0; /* clear */
|
||||
|
||||
gusptr = state->gusdatapos;
|
||||
voiceptr = (GUSword *) gusptr;
|
||||
voiceptr = (uint16_t *) gusptr;
|
||||
if (!(GUSregb(GUS4cReset) & 0x01)) /* reset flag active? */
|
||||
return;
|
||||
|
||||
@ -85,16 +85,16 @@ void gus_mixvoices(GUSEmuState * state, unsigned int playback_freq, unsigned int
|
||||
if (GUSvoice(wVSRControl) & 0x400) /* 16bit */
|
||||
{
|
||||
int offset = ((CurrPos >> 9) & 0xc0000) + (((CurrPos >> 9) & 0x1ffff) << 1);
|
||||
GUSchar *adr;
|
||||
adr = (GUSchar *) state->himemaddr + offset;
|
||||
int8_t *adr;
|
||||
adr = (int8_t *) state->himemaddr + offset;
|
||||
sample1 = (*adr & 0xff) + (*(adr + 1) * 256);
|
||||
sample2 = (*(adr + 2) & 0xff) + (*(adr + 2 + 1) * 256);
|
||||
}
|
||||
else /* 8bit */
|
||||
{
|
||||
int offset = (CurrPos >> 9) & 0xfffff;
|
||||
GUSchar *adr;
|
||||
adr = (GUSchar *) state->himemaddr + offset;
|
||||
int8_t *adr;
|
||||
adr = (int8_t *) state->himemaddr + offset;
|
||||
sample1 = (*adr) * 256;
|
||||
sample2 = (*(adr + 1)) * 256;
|
||||
}
|
||||
@ -171,8 +171,8 @@ void gus_mixvoices(GUSEmuState * state, unsigned int playback_freq, unsigned int
|
||||
}
|
||||
|
||||
/* mix samples into buffer */
|
||||
*(bufferpos + 2 * sample) += (GUSsample) ((sample1 * PanningPos) >> 4); /* right */
|
||||
*(bufferpos + 2 * sample + 1) += (GUSsample) ((sample1 * (15 - PanningPos)) >> 4); /* left */
|
||||
*(bufferpos + 2 * sample) += (int16_t) ((sample1 * PanningPos) >> 4); /* right */
|
||||
*(bufferpos + 2 * sample + 1) += (int16_t) ((sample1 * (15 - PanningPos)) >> 4); /* left */
|
||||
}
|
||||
/* write back voice and volume */
|
||||
GUSvoice(wVSRCurrVol) = Volume32 / 32;
|
||||
@ -187,7 +187,7 @@ void gus_irqgen(GUSEmuState * state, unsigned int elapsed_time)
|
||||
/* time given in microseconds */
|
||||
{
|
||||
int requestedIRQs = 0;
|
||||
GUSbyte *gusptr;
|
||||
uint8_t *gusptr;
|
||||
gusptr = state->gusdatapos;
|
||||
if (GUSregb(TimerDataReg2x9) & 1) /* start timer 1 (80us decrement rate) */
|
||||
{
|
||||
|
@ -520,7 +520,7 @@ static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hda_audio_exit(HDACodecDevice *hda)
|
||||
static void hda_audio_exit(HDACodecDevice *hda)
|
||||
{
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
HDAAudioStream *st;
|
||||
@ -539,7 +539,6 @@ static int hda_audio_exit(HDACodecDevice *hda)
|
||||
}
|
||||
}
|
||||
AUD_remove_card(&a->card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hda_audio_post_load(void *opaque, int version)
|
||||
|
@ -70,7 +70,7 @@ static void hda_codec_dev_realize(DeviceState *qdev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static int hda_codec_dev_exit(DeviceState *qdev)
|
||||
static void hda_codec_dev_unrealize(DeviceState *qdev, Error **errp)
|
||||
{
|
||||
HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev);
|
||||
HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
|
||||
@ -78,7 +78,6 @@ static int hda_codec_dev_exit(DeviceState *qdev)
|
||||
if (cdc->exit) {
|
||||
cdc->exit(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
|
||||
@ -1318,7 +1317,7 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *k = DEVICE_CLASS(klass);
|
||||
k->realize = hda_codec_dev_realize;
|
||||
k->exit = hda_codec_dev_exit;
|
||||
k->unrealize = hda_codec_dev_unrealize;
|
||||
set_bit(DEVICE_CATEGORY_SOUND, k->categories);
|
||||
k->bus_type = TYPE_HDA_BUS;
|
||||
k->props = hda_props;
|
||||
|
@ -38,7 +38,7 @@ typedef struct HDACodecDeviceClass
|
||||
DeviceClass parent_class;
|
||||
|
||||
int (*init)(HDACodecDevice *dev);
|
||||
int (*exit)(HDACodecDevice *dev);
|
||||
void (*exit)(HDACodecDevice *dev);
|
||||
void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data);
|
||||
void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running, bool output);
|
||||
} HDACodecDeviceClass;
|
||||
|
Loading…
x
Reference in New Issue
Block a user