Commit 85571bc7415c3fa9390f5edc3720ec7975219a68

Authored by bellard
1 parent 8f46820d

audio merge (malc)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1125 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
1 1 include config.mak
2 2  
  3 +#After enabling Adlib and/or FMOD rebuild QEMU from scratch
  4 +#Uncomment following for adlib support
  5 +#USE_ADLIB=1
  6 +
  7 +#Uncomment following and specify proper paths/names for FMOD support
  8 +#USE_FMOD=1
  9 +#FMOD_INCLUDE=/net/include/fmod
  10 +#FMOD_LIBPATH=/net/lib
  11 +#FMOD_VERSION=3.74
  12 +
3 13 TARGET_PATH=$(SRC_PATH)/target-$(TARGET_ARCH)
4   -VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw
  14 +VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
5 15 DEFINES=-I. -I$(TARGET_PATH) -I$(SRC_PATH)
6 16 ifdef CONFIG_USER_ONLY
7 17 VPATH+=:$(SRC_PATH)/linux-user
... ... @@ -267,16 +277,31 @@ endif
267 277 VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
268 278 VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
269 279  
  280 +SOUND_HW = sb16.o
  281 +AUDIODRV = audio.o ossaudio.o sdlaudio.o wavaudio.o
  282 +
  283 +ifeq ($(USE_ADLIB),1)
  284 +SOUND_HW += fmopl.o adlib.o
  285 +audio.o: DEFINES := -DUSE_ADLIB $(DEFINES)
  286 +endif
  287 +
  288 +ifeq ($(USE_FMOD),1)
  289 +AUDIODRV += fmodaudio.o
  290 +audio.o fmodaudio.o: DEFINES := -DUSE_FMOD_AUDIO -I$(FMOD_INCLUDE) $(DEFINES)
  291 +LDFLAGS += -L$(FMOD_LIBPATH) -Wl,-rpath,$(FMOD_LIBPATH)
  292 +LIBS += -lfmod-$(FMOD_VERSION)
  293 +endif
  294 +
270 295 ifeq ($(TARGET_ARCH), i386)
271 296 # Hardware support
272   -VL_OBJS+= ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o
273   -VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
274   -VL_OBJS+= cirrus_vga.o
  297 +VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
  298 +VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
  299 +VL_OBJS+= cirrus_vga.o mixeng.o
275 300 endif
276 301 ifeq ($(TARGET_ARCH), ppc)
277   -VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o
  302 +VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
278 303 VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
279   -VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o
  304 +VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o mixeng.o
280 305 endif
281 306 ifeq ($(TARGET_ARCH), sparc)
282 307 VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o
... ... @@ -360,6 +385,8 @@ op.o: op.c op_template.h op_mem.h
360 385 op_helper.o: op_helper_mem.h
361 386 endif
362 387  
  388 +mixeng.o: mixeng.c mixeng.h mixeng_template.h
  389 +
363 390 %.o: %.c
364 391 $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
365 392  
... ...
audio/audio.c 0 → 100644
  1 +/*
  2 + * QEMU Audio subsystem
  3 + *
  4 + * Copyright (c) 2003-2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include <assert.h>
  25 +#include <limits.h>
  26 +#include "vl.h"
  27 +
  28 +#define AUDIO_CAP "audio"
  29 +#include "audio/audio.h"
  30 +
  31 +#define USE_SDL_AUDIO
  32 +#define USE_WAV_AUDIO
  33 +
  34 +#if defined __linux__ || (defined _BSD && !defined __APPLE__)
  35 +#define USE_OSS_AUDIO
  36 +#endif
  37 +
  38 +#ifdef USE_OSS_AUDIO
  39 +#include "audio/ossaudio.h"
  40 +#endif
  41 +
  42 +#ifdef USE_SDL_AUDIO
  43 +#include "audio/sdlaudio.h"
  44 +#endif
  45 +
  46 +#ifdef USE_WAV_AUDIO
  47 +#include "audio/wavaudio.h"
  48 +#endif
  49 +
  50 +#ifdef USE_FMOD_AUDIO
  51 +#include "audio/fmodaudio.h"
  52 +#endif
  53 +
  54 +#define QC_AUDIO_DRV "QEMU_AUDIO_DRV"
  55 +#define QC_VOICES "QEMU_VOICES"
  56 +#define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT"
  57 +#define QC_FIXED_FREQ "QEMU_FIXED_FREQ"
  58 +
  59 +extern void SB16_init (void);
  60 +
  61 +#ifdef USE_ADLIB
  62 +extern void Adlib_init (void);
  63 +#endif
  64 +
  65 +#ifdef USE_GUS
  66 +extern void GUS_init (void);
  67 +#endif
  68 +
  69 +static void (*hw_ctors[]) (void) = {
  70 + SB16_init,
  71 +#ifdef USE_ADLIB
  72 + Adlib_init,
  73 +#endif
  74 +#ifdef USE_GUS
  75 + GUS_init,
  76 +#endif
  77 + NULL
  78 +};
  79 +
  80 +static HWVoice *hw_voice;
  81 +
  82 +AudioState audio_state = {
  83 + 1, /* use fixed settings */
  84 + 44100, /* fixed frequency */
  85 + 2, /* fixed channels */
  86 + AUD_FMT_S16, /* fixed format */
  87 + 1, /* number of hw voices */
  88 + -1 /* voice size */
  89 +};
  90 +
  91 +/* http://www.df.lth.se/~john_e/gems/gem002d.html */
  92 +/* http://www.multi-platforms.com/Tips/PopCount.htm */
  93 +uint32_t popcount (uint32_t u)
  94 +{
  95 + u = ((u&0x55555555) + ((u>>1)&0x55555555));
  96 + u = ((u&0x33333333) + ((u>>2)&0x33333333));
  97 + u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
  98 + u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
  99 + u = ( u&0x0000ffff) + (u>>16);
  100 + return u;
  101 +}
  102 +
  103 +inline uint32_t lsbindex (uint32_t u)
  104 +{
  105 + return popcount ((u&-u)-1);
  106 +}
  107 +
  108 +int audio_get_conf_int (const char *key, int defval)
  109 +{
  110 + int val = defval;
  111 + char *strval;
  112 +
  113 + strval = getenv (key);
  114 + if (strval) {
  115 + val = atoi (strval);
  116 + }
  117 +
  118 + return val;
  119 +}
  120 +
  121 +const char *audio_get_conf_str (const char *key, const char *defval)
  122 +{
  123 + const char *val = getenv (key);
  124 + if (!val)
  125 + return defval;
  126 + else
  127 + return val;
  128 +}
  129 +
  130 +void audio_log (const char *fmt, ...)
  131 +{
  132 + va_list ap;
  133 + va_start (ap, fmt);
  134 + vfprintf (stderr, fmt, ap);
  135 + va_end (ap);
  136 +}
  137 +
  138 +/*
  139 + * Soft Voice
  140 + */
  141 +void pcm_sw_free_resources (SWVoice *sw)
  142 +{
  143 + if (sw->buf) qemu_free (sw->buf);
  144 + if (sw->rate) st_rate_stop (sw->rate);
  145 + sw->buf = NULL;
  146 + sw->rate = NULL;
  147 +}
  148 +
  149 +int pcm_sw_alloc_resources (SWVoice *sw)
  150 +{
  151 + sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));
  152 + if (!sw->buf)
  153 + return -1;
  154 +
  155 + sw->rate = st_rate_start (sw->freq, sw->hw->freq);
  156 + if (!sw->rate) {
  157 + qemu_free (sw->buf);
  158 + sw->buf = NULL;
  159 + return -1;
  160 + }
  161 + return 0;
  162 +}
  163 +
  164 +void pcm_sw_fini (SWVoice *sw)
  165 +{
  166 + pcm_sw_free_resources (sw);
  167 +}
  168 +
  169 +int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
  170 + int nchannels, audfmt_e fmt)
  171 +{
  172 + int bits = 8, sign = 0;
  173 +
  174 + switch (fmt) {
  175 + case AUD_FMT_S8:
  176 + sign = 1;
  177 + case AUD_FMT_U8:
  178 + break;
  179 +
  180 + case AUD_FMT_S16:
  181 + sign = 1;
  182 + case AUD_FMT_U16:
  183 + bits = 16;
  184 + break;
  185 + }
  186 +
  187 + sw->hw = hw;
  188 + sw->freq = freq;
  189 + sw->fmt = fmt;
  190 + sw->nchannels = nchannels;
  191 + sw->shift = (nchannels == 2) + (bits == 16);
  192 + sw->align = (1 << sw->shift) - 1;
  193 + sw->left = 0;
  194 + sw->pos = 0;
  195 + sw->wpos = 0;
  196 + sw->live = 0;
  197 + sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq;
  198 + sw->bytes_per_second = sw->freq << sw->shift;
  199 + sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16];
  200 +
  201 + pcm_sw_free_resources (sw);
  202 + return pcm_sw_alloc_resources (sw);
  203 +}
  204 +
  205 +/* Hard voice */
  206 +void pcm_hw_free_resources (HWVoice *hw)
  207 +{
  208 + if (hw->mix_buf)
  209 + qemu_free (hw->mix_buf);
  210 + hw->mix_buf = NULL;
  211 +}
  212 +
  213 +int pcm_hw_alloc_resources (HWVoice *hw)
  214 +{
  215 + hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
  216 + if (!hw->mix_buf)
  217 + return -1;
  218 + return 0;
  219 +}
  220 +
  221 +
  222 +void pcm_hw_fini (HWVoice *hw)
  223 +{
  224 + if (hw->active) {
  225 + ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt);
  226 + pcm_hw_free_resources (hw);
  227 + hw->pcm_ops->fini (hw);
  228 + memset (hw, 0, audio_state.drv->voice_size);
  229 + }
  230 +}
  231 +
  232 +void pcm_hw_gc (HWVoice *hw)
  233 +{
  234 + if (hw->nb_voices)
  235 + return;
  236 +
  237 + pcm_hw_fini (hw);
  238 +}
  239 +
  240 +int pcm_hw_get_live (HWVoice *hw)
  241 +{
  242 + int i, alive = 0, live = hw->samples;
  243 +
  244 + for (i = 0; i < hw->nb_voices; i++) {
  245 + if (hw->pvoice[i]->live) {
  246 + live = audio_MIN (hw->pvoice[i]->live, live);
  247 + alive += 1;
  248 + }
  249 + }
  250 +
  251 + if (alive)
  252 + return live;
  253 + else
  254 + return -1;
  255 +}
  256 +
  257 +int pcm_hw_get_live2 (HWVoice *hw, int *nb_active)
  258 +{
  259 + int i, alive = 0, live = hw->samples;
  260 +
  261 + *nb_active = 0;
  262 + for (i = 0; i < hw->nb_voices; i++) {
  263 + if (hw->pvoice[i]->live) {
  264 + if (hw->pvoice[i]->live < live) {
  265 + *nb_active = hw->pvoice[i]->active != 0;
  266 + live = hw->pvoice[i]->live;
  267 + }
  268 + alive += 1;
  269 + }
  270 + }
  271 +
  272 + if (alive)
  273 + return live;
  274 + else
  275 + return -1;
  276 +}
  277 +
  278 +void pcm_hw_dec_live (HWVoice *hw, int decr)
  279 +{
  280 + int i;
  281 +
  282 + for (i = 0; i < hw->nb_voices; i++) {
  283 + if (hw->pvoice[i]->live) {
  284 + hw->pvoice[i]->live -= decr;
  285 + }
  286 + }
  287 +}
  288 +
  289 +void pcm_hw_clear (HWVoice *hw, void *buf, int len)
  290 +{
  291 + if (!len)
  292 + return;
  293 +
  294 + switch (hw->fmt) {
  295 + case AUD_FMT_S16:
  296 + case AUD_FMT_S8:
  297 + memset (buf, len << hw->shift, 0x00);
  298 + break;
  299 +
  300 + case AUD_FMT_U8:
  301 + memset (buf, len << hw->shift, 0x80);
  302 + break;
  303 +
  304 + case AUD_FMT_U16:
  305 + {
  306 + unsigned int i;
  307 + uint16_t *p = buf;
  308 + int shift = hw->nchannels - 1;
  309 +
  310 + for (i = 0; i < len << shift; i++) {
  311 + p[i] = INT16_MAX;
  312 + }
  313 + }
  314 + break;
  315 + }
  316 +}
  317 +
  318 +int pcm_hw_write (SWVoice *sw, void *buf, int size)
  319 +{
  320 + int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
  321 + int ret = 0, pos = 0;
  322 + if (!sw)
  323 + return size;
  324 +
  325 + hwsamples = sw->hw->samples;
  326 + samples = size >> sw->shift;
  327 +
  328 + if (!sw->live) {
  329 + sw->wpos = sw->hw->rpos;
  330 + }
  331 + wpos = sw->wpos;
  332 + live = sw->live;
  333 + dead = hwsamples - live;
  334 + swlim = (dead * ((int64_t) INT_MAX)) / sw->ratio;
  335 + swlim = audio_MIN (swlim, samples);
  336 +
  337 + ldebug ("size=%d live=%d dead=%d swlim=%d wpos=%d\n",
  338 + size, live, dead, swlim, wpos);
  339 + if (swlim)
  340 + sw->conv (sw->buf, buf, swlim);
  341 +
  342 + while (swlim) {
  343 + dead = hwsamples - live;
  344 + left = hwsamples - wpos;
  345 + blck = audio_MIN (dead, left);
  346 + if (!blck) {
  347 + /* dolog ("swlim=%d\n", swlim); */
  348 + break;
  349 + }
  350 + isamp = swlim;
  351 + osamp = blck;
  352 + st_rate_flow (sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp, &osamp);
  353 + ret += isamp;
  354 + swlim -= isamp;
  355 + pos += isamp;
  356 + live += osamp;
  357 + wpos = (wpos + osamp) % hwsamples;
  358 + }
  359 +
  360 + sw->wpos = wpos;
  361 + sw->live = live;
  362 + return ret << sw->shift;
  363 +}
  364 +
  365 +int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
  366 +{
  367 + int sign = 0, bits = 8;
  368 +
  369 + pcm_hw_fini (hw);
  370 + ldebug ("pcm_hw_init: %d %d %d\n", freq, nchannels, fmt);
  371 + if (hw->pcm_ops->init (hw, freq, nchannels, fmt)) {
  372 + memset (hw, 0, audio_state.drv->voice_size);
  373 + return -1;
  374 + }
  375 +
  376 + switch (hw->fmt) {
  377 + case AUD_FMT_S8:
  378 + sign = 1;
  379 + case AUD_FMT_U8:
  380 + break;
  381 +
  382 + case AUD_FMT_S16:
  383 + sign = 1;
  384 + case AUD_FMT_U16:
  385 + bits = 16;
  386 + break;
  387 + }
  388 +
  389 + hw->nb_voices = 0;
  390 + hw->active = 1;
  391 + hw->shift = (hw->nchannels == 2) + (bits == 16);
  392 + hw->bytes_per_second = hw->freq << hw->shift;
  393 + hw->align = (1 << hw->shift) - 1;
  394 + hw->samples = hw->bufsize >> hw->shift;
  395 + hw->clip = mixeng_clip[hw->nchannels == 2][sign][bits == 16];
  396 + if (pcm_hw_alloc_resources (hw)) {
  397 + pcm_hw_fini (hw);
  398 + return -1;
  399 + }
  400 + return 0;
  401 +}
  402 +
  403 +static int dist (void *hw)
  404 +{
  405 + if (hw) {
  406 + return (((uint8_t *) hw - (uint8_t *) hw_voice)
  407 + / audio_state.voice_size) + 1;
  408 + }
  409 + else {
  410 + return 0;
  411 + }
  412 +}
  413 +
  414 +#define ADVANCE(hw) hw ? advance (hw, audio_state.voice_size) : hw_voice
  415 +
  416 +HWVoice *pcm_hw_find_any (HWVoice *hw)
  417 +{
  418 + int i = dist (hw);
  419 + for (; i < audio_state.nb_hw_voices; i++) {
  420 + hw = ADVANCE (hw);
  421 + return hw;
  422 + }
  423 + return NULL;
  424 +}
  425 +
  426 +HWVoice *pcm_hw_find_any_active (HWVoice *hw)
  427 +{
  428 + int i = dist (hw);
  429 + for (; i < audio_state.nb_hw_voices; i++) {
  430 + hw = ADVANCE (hw);
  431 + if (hw->active)
  432 + return hw;
  433 + }
  434 + return NULL;
  435 +}
  436 +
  437 +HWVoice *pcm_hw_find_any_active_enabled (HWVoice *hw)
  438 +{
  439 + int i = dist (hw);
  440 + for (; i < audio_state.nb_hw_voices; i++) {
  441 + hw = ADVANCE (hw);
  442 + if (hw->active && hw->enabled)
  443 + return hw;
  444 + }
  445 + return NULL;
  446 +}
  447 +
  448 +HWVoice *pcm_hw_find_any_passive (HWVoice *hw)
  449 +{
  450 + int i = dist (hw);
  451 + for (; i < audio_state.nb_hw_voices; i++) {
  452 + hw = ADVANCE (hw);
  453 + if (!hw->active)
  454 + return hw;
  455 + }
  456 + return NULL;
  457 +}
  458 +
  459 +HWVoice *pcm_hw_find_specific (HWVoice *hw, int freq,
  460 + int nchannels, audfmt_e fmt)
  461 +{
  462 + while ((hw = pcm_hw_find_any_active (hw))) {
  463 + if (hw->freq == freq &&
  464 + hw->nchannels == nchannels &&
  465 + hw->fmt == fmt)
  466 + return hw;
  467 + }
  468 + return NULL;
  469 +}
  470 +
  471 +HWVoice *pcm_hw_add (int freq, int nchannels, audfmt_e fmt)
  472 +{
  473 + HWVoice *hw;
  474 +
  475 + if (audio_state.fixed_format) {
  476 + freq = audio_state.fixed_freq;
  477 + nchannels = audio_state.fixed_channels;
  478 + fmt = audio_state.fixed_fmt;
  479 + }
  480 +
  481 + hw = pcm_hw_find_specific (NULL, freq, nchannels, fmt);
  482 +
  483 + if (hw)
  484 + return hw;
  485 +
  486 + hw = pcm_hw_find_any_passive (NULL);
  487 + if (hw) {
  488 + hw->pcm_ops = audio_state.drv->pcm_ops;
  489 + if (!hw->pcm_ops)
  490 + return NULL;
  491 +
  492 + if (pcm_hw_init (hw, freq, nchannels, fmt)) {
  493 + pcm_hw_gc (hw);
  494 + return NULL;
  495 + }
  496 + else
  497 + return hw;
  498 + }
  499 +
  500 + return pcm_hw_find_any (NULL);
  501 +}
  502 +
  503 +int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw)
  504 +{
  505 + SWVoice **pvoice = qemu_mallocz ((hw->nb_voices + 1) * sizeof (sw));
  506 + if (!pvoice)
  507 + return -1;
  508 +
  509 + memcpy (pvoice, hw->pvoice, hw->nb_voices * sizeof (sw));
  510 + qemu_free (hw->pvoice);
  511 + hw->pvoice = pvoice;
  512 + hw->pvoice[hw->nb_voices++] = sw;
  513 + return 0;
  514 +}
  515 +
  516 +int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw)
  517 +{
  518 + int i, j;
  519 + if (hw->nb_voices > 1) {
  520 + SWVoice **pvoice = qemu_mallocz ((hw->nb_voices - 1) * sizeof (sw));
  521 +
  522 + if (!pvoice) {
  523 + dolog ("Can not maintain consistent state (not enough memory)\n");
  524 + return -1;
  525 + }
  526 +
  527 + for (i = 0, j = 0; i < hw->nb_voices; i++) {
  528 + if (j >= hw->nb_voices - 1) {
  529 + dolog ("Can not maintain consistent state "
  530 + "(invariant violated)\n");
  531 + return -1;
  532 + }
  533 + if (hw->pvoice[i] != sw)
  534 + pvoice[j++] = hw->pvoice[i];
  535 + }
  536 + qemu_free (hw->pvoice);
  537 + hw->pvoice = pvoice;
  538 + hw->nb_voices -= 1;
  539 + }
  540 + else {
  541 + qemu_free (hw->pvoice);
  542 + hw->pvoice = NULL;
  543 + hw->nb_voices = 0;
  544 + }
  545 + return 0;
  546 +}
  547 +
  548 +SWVoice *pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt)
  549 +{
  550 + SWVoice *sw;
  551 + HWVoice *hw;
  552 +
  553 + sw = qemu_mallocz (sizeof (*sw));
  554 + if (!sw)
  555 + goto err1;
  556 +
  557 + hw = pcm_hw_add (freq, nchannels, fmt);
  558 + if (!hw)
  559 + goto err2;
  560 +
  561 + if (pcm_hw_add_sw (hw, sw))
  562 + goto err3;
  563 +
  564 + if (pcm_sw_init (sw, hw, freq, nchannels, fmt))
  565 + goto err4;
  566 +
  567 + return sw;
  568 +
  569 +err4:
  570 + pcm_hw_del_sw (hw, sw);
  571 +err3:
  572 + pcm_hw_gc (hw);
  573 +err2:
  574 + qemu_free (sw);
  575 +err1:
  576 + return NULL;
  577 +}
  578 +
  579 +SWVoice *AUD_open (SWVoice *sw, const char *name,
  580 + int freq, int nchannels, audfmt_e fmt)
  581 +{
  582 + if (!audio_state.drv) {
  583 + return NULL;
  584 + }
  585 +
  586 + if (sw && freq == sw->freq && sw->nchannels == nchannels && sw->fmt == fmt) {
  587 + return sw;
  588 + }
  589 +
  590 + if (sw) {
  591 + ldebug ("Different format %s %d %d %d\n",
  592 + name,
  593 + sw->freq == freq,
  594 + sw->nchannels == nchannels,
  595 + sw->fmt == fmt);
  596 + }
  597 +
  598 + if (nchannels != 1 && nchannels != 2) {
  599 + dolog ("Bogus channel count %d for voice %s\n", nchannels, name);
  600 + return NULL;
  601 + }
  602 +
  603 + if (!audio_state.fixed_format && sw) {
  604 + pcm_sw_fini (sw);
  605 + pcm_hw_del_sw (sw->hw, sw);
  606 + pcm_hw_gc (sw->hw);
  607 + if (sw->name) {
  608 + qemu_free (sw->name);
  609 + sw->name = NULL;
  610 + }
  611 + qemu_free (sw);
  612 + sw = NULL;
  613 + }
  614 +
  615 + if (sw) {
  616 + HWVoice *hw = sw->hw;
  617 + if (!hw) {
  618 + dolog ("Internal logic error voice %s has no hardware store\n",
  619 + name);
  620 + return sw;
  621 + }
  622 +
  623 + if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) {
  624 + pcm_sw_fini (sw);
  625 + pcm_hw_del_sw (hw, sw);
  626 + pcm_hw_gc (hw);
  627 + if (sw->name) {
  628 + qemu_free (sw->name);
  629 + sw->name = NULL;
  630 + }
  631 + qemu_free (sw);
  632 + return NULL;
  633 + }
  634 + }
  635 + else {
  636 + sw = pcm_create_voice_pair (freq, nchannels, fmt);
  637 + if (!sw) {
  638 + dolog ("Failed to create voice %s\n", name);
  639 + return NULL;
  640 + }
  641 + }
  642 +
  643 + if (sw->name) {
  644 + qemu_free (sw->name);
  645 + sw->name = NULL;
  646 + }
  647 + sw->name = qemu_strdup (name);
  648 + return sw;
  649 +}
  650 +
  651 +int AUD_write (SWVoice *sw, void *buf, int size)
  652 +{
  653 + int bytes;
  654 +
  655 + if (!sw->hw->enabled)
  656 + dolog ("Writing to disabled voice %s\n", sw->name);
  657 + bytes = sw->hw->pcm_ops->write (sw, buf, size);
  658 + return bytes;
  659 +}
  660 +
  661 +void AUD_run (void)
  662 +{
  663 + HWVoice *hw = NULL;
  664 +
  665 + while ((hw = pcm_hw_find_any_active_enabled (hw))) {
  666 + int i;
  667 + if (hw->pending_disable && pcm_hw_get_live (hw) <= 0) {
  668 + hw->enabled = 0;
  669 + hw->pcm_ops->ctl (hw, VOICE_DISABLE);
  670 + for (i = 0; i < hw->nb_voices; i++) {
  671 + hw->pvoice[i]->live = 0;
  672 + /* hw->pvoice[i]->old_ticks = 0; */
  673 + }
  674 + continue;
  675 + }
  676 +
  677 + hw->pcm_ops->run (hw);
  678 + assert (hw->rpos < hw->samples);
  679 + for (i = 0; i < hw->nb_voices; i++) {
  680 + SWVoice *sw = hw->pvoice[i];
  681 + if (!sw->active && !sw->live && sw->old_ticks) {
  682 + int64_t delta = qemu_get_clock (vm_clock) - sw->old_ticks;
  683 + if (delta > audio_state.ticks_threshold) {
  684 + ldebug ("resetting old_ticks for %s\n", sw->name);
  685 + sw->old_ticks = 0;
  686 + }
  687 + }
  688 + }
  689 + }
  690 +}
  691 +
  692 +int AUD_get_free (SWVoice *sw)
  693 +{
  694 + int free;
  695 +
  696 + if (!sw)
  697 + return 4096;
  698 +
  699 + free = ((sw->hw->samples - sw->live) << sw->hw->shift) * sw->ratio
  700 + / INT_MAX;
  701 +
  702 + free &= ~sw->hw->align;
  703 + if (!free) return 0;
  704 +
  705 + return free;
  706 +}
  707 +
  708 +int AUD_get_buffer_size (SWVoice *sw)
  709 +{
  710 + return sw->hw->bufsize;
  711 +}
  712 +
  713 +void AUD_adjust (SWVoice *sw, int bytes)
  714 +{
  715 + if (!sw)
  716 + return;
  717 + sw->old_ticks += (ticks_per_sec * (int64_t) bytes) / sw->bytes_per_second;
  718 +}
  719 +
  720 +void AUD_reset (SWVoice *sw)
  721 +{
  722 + sw->active = 0;
  723 + sw->old_ticks = 0;
  724 +}
  725 +
  726 +int AUD_calc_elapsed (SWVoice *sw)
  727 +{
  728 + int64_t now, delta, bytes;
  729 + int dead, swlim;
  730 +
  731 + if (!sw)
  732 + return 0;
  733 +
  734 + now = qemu_get_clock (vm_clock);
  735 + delta = now - sw->old_ticks;
  736 + bytes = (delta * sw->bytes_per_second) / ticks_per_sec;
  737 + if (delta < 0) {
  738 + dolog ("whoops delta(<0)=%lld\n", delta);
  739 + return 0;
  740 + }
  741 +
  742 + dead = sw->hw->samples - sw->live;
  743 + swlim = ((dead * (int64_t) INT_MAX) / sw->ratio);
  744 +
  745 + if (bytes > swlim) {
  746 + return swlim;
  747 + }
  748 + else {
  749 + return bytes;
  750 + }
  751 +}
  752 +
  753 +void AUD_enable (SWVoice *sw, int on)
  754 +{
  755 + int i;
  756 + HWVoice *hw;
  757 +
  758 + if (!sw)
  759 + return;
  760 +
  761 + hw = sw->hw;
  762 + if (on) {
  763 + if (!sw->live)
  764 + sw->wpos = sw->hw->rpos;
  765 + if (!sw->old_ticks) {
  766 + sw->old_ticks = qemu_get_clock (vm_clock);
  767 + }
  768 + }
  769 +
  770 + if (sw->active != on) {
  771 + if (on) {
  772 + hw->pending_disable = 0;
  773 + if (!hw->enabled) {
  774 + hw->enabled = 1;
  775 + for (i = 0; i < hw->nb_voices; i++) {
  776 + ldebug ("resetting voice\n");
  777 + sw = hw->pvoice[i];
  778 + sw->old_ticks = qemu_get_clock (vm_clock);
  779 + }
  780 + hw->pcm_ops->ctl (hw, VOICE_ENABLE);
  781 + }
  782 + }
  783 + else {
  784 + if (hw->enabled && !hw->pending_disable) {
  785 + int nb_active = 0;
  786 + for (i = 0; i < hw->nb_voices; i++) {
  787 + nb_active += hw->pvoice[i]->active != 0;
  788 + }
  789 +
  790 + if (nb_active == 1) {
  791 + hw->pending_disable = 1;
  792 + }
  793 + }
  794 + }
  795 + sw->active = on;
  796 + }
  797 +}
  798 +
  799 +static struct audio_output_driver *drvtab[] = {
  800 +#ifdef USE_OSS_AUDIO
  801 + &oss_output_driver,
  802 +#endif
  803 +#ifdef USE_FMOD_AUDIO
  804 + &fmod_output_driver,
  805 +#endif
  806 +#ifdef USE_SDL_AUDIO
  807 + &sdl_output_driver,
  808 +#endif
  809 +#ifdef USE_WAV_AUDIO
  810 + &wav_output_driver,
  811 +#endif
  812 +};
  813 +
  814 +static int voice_init (struct audio_output_driver *drv)
  815 +{
  816 + audio_state.opaque = drv->init ();
  817 + if (audio_state.opaque) {
  818 + if (audio_state.nb_hw_voices > drv->max_voices) {
  819 + dolog ("`%s' does not support %d multiple hardware channels\n"
  820 + "Resetting to %d\n",
  821 + drv->name, audio_state.nb_hw_voices, drv->max_voices);
  822 + audio_state.nb_hw_voices = drv->max_voices;
  823 + }
  824 + hw_voice = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size);
  825 + if (hw_voice) {
  826 + audio_state.drv = drv;
  827 + return 1;
  828 + }
  829 + else {
  830 + dolog ("Not enough memory for %d `%s' voices (each %d bytes)\n",
  831 + audio_state.nb_hw_voices, drv->name, drv->voice_size);
  832 + drv->fini (audio_state.opaque);
  833 + return 0;
  834 + }
  835 + }
  836 + else {
  837 + dolog ("Could not init `%s' audio\n", drv->name);
  838 + return 0;
  839 + }
  840 +}
  841 +
  842 +static void audio_vm_stop_handler (void *opaque, int reason)
  843 +{
  844 + HWVoice *hw = NULL;
  845 +
  846 + while ((hw = pcm_hw_find_any (hw))) {
  847 + if (!hw->pcm_ops)
  848 + continue;
  849 +
  850 + hw->pcm_ops->ctl (hw, reason ? VOICE_ENABLE : VOICE_DISABLE);
  851 + }
  852 +}
  853 +
  854 +static void audio_atexit (void)
  855 +{
  856 + HWVoice *hw = NULL;
  857 +
  858 + while ((hw = pcm_hw_find_any (hw))) {
  859 + if (!hw->pcm_ops)
  860 + continue;
  861 +
  862 + hw->pcm_ops->ctl (hw, VOICE_DISABLE);
  863 + hw->pcm_ops->fini (hw);
  864 + }
  865 + audio_state.drv->fini (audio_state.opaque);
  866 +}
  867 +
  868 +static void audio_save (QEMUFile *f, void *opaque)
  869 +{
  870 +}
  871 +
  872 +static int audio_load (QEMUFile *f, void *opaque, int version_id)
  873 +{
  874 + if (version_id != 1)
  875 + return -EINVAL;
  876 +
  877 + return 0;
  878 +}
  879 +
  880 +void AUD_init (void)
  881 +{
  882 + int i;
  883 + int done = 0;
  884 + const char *drvname;
  885 +
  886 + audio_state.fixed_format =
  887 + !!audio_get_conf_int (QC_FIXED_FORMAT, audio_state.fixed_format);
  888 + audio_state.fixed_freq =
  889 + audio_get_conf_int (QC_FIXED_FREQ, audio_state.fixed_freq);
  890 + audio_state.nb_hw_voices =
  891 + audio_get_conf_int (QC_VOICES, audio_state.nb_hw_voices);
  892 +
  893 + if (audio_state.nb_hw_voices <= 0) {
  894 + dolog ("Bogus number of voices %d, resetting to 1\n",
  895 + audio_state.nb_hw_voices);
  896 + }
  897 +
  898 + drvname = audio_get_conf_str (QC_AUDIO_DRV, NULL);
  899 + if (drvname) {
  900 + int found = 0;
  901 + for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
  902 + if (!strcmp (drvname, drvtab[i]->name)) {
  903 + done = voice_init (drvtab[i]);
  904 + found = 1;
  905 + break;
  906 + }
  907 + }
  908 + if (!found) {
  909 + dolog ("Unknown audio driver `%s'\n", drvname);
  910 + }
  911 + }
  912 +
  913 + qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL);
  914 + atexit (audio_atexit);
  915 +
  916 + if (!done) {
  917 + for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
  918 + if (drvtab[i]->can_be_default)
  919 + done = voice_init (drvtab[i]);
  920 + }
  921 + }
  922 +
  923 + audio_state.ticks_threshold = ticks_per_sec / 50;
  924 + audio_state.freq_threshold = 100;
  925 +
  926 + register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);
  927 + if (!done) {
  928 + dolog ("Can not initialize audio subsystem\n");
  929 + return;
  930 + }
  931 +
  932 + for (i = 0; hw_ctors[i]; i++) {
  933 + hw_ctors[i] ();
  934 + }
  935 +}
... ...
audio/audio.h 0 → 100644
  1 +/*
  2 + * QEMU Audio subsystem header
  3 + *
  4 + * Copyright (c) 2003-2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#ifndef QEMU_AUDIO_H
  25 +#define QEMU_AUDIO_H
  26 +
  27 +#include "mixeng.h"
  28 +
  29 +#define dolog(...) fprintf (stderr, AUDIO_CAP ": " __VA_ARGS__)
  30 +#ifdef DEBUG
  31 +#define ldebug(...) dolog (__VA_ARGS__)
  32 +#else
  33 +#define ldebug(...)
  34 +#endif
  35 +
  36 +typedef enum {
  37 + AUD_FMT_U8,
  38 + AUD_FMT_S8,
  39 + AUD_FMT_U16,
  40 + AUD_FMT_S16
  41 +} audfmt_e;
  42 +
  43 +typedef struct HWVoice HWVoice;
  44 +struct audio_output_driver;
  45 +
  46 +typedef struct AudioState {
  47 + int fixed_format;
  48 + int fixed_freq;
  49 + int fixed_channels;
  50 + int fixed_fmt;
  51 + int nb_hw_voices;
  52 + int voice_size;
  53 + int64_t ticks_threshold;
  54 + int freq_threshold;
  55 + void *opaque;
  56 + struct audio_output_driver *drv;
  57 +} AudioState;
  58 +
  59 +extern AudioState audio_state;
  60 +
  61 +typedef struct SWVoice {
  62 + int freq;
  63 + audfmt_e fmt;
  64 + int nchannels;
  65 +
  66 + int shift;
  67 + int align;
  68 +
  69 + t_sample *conv;
  70 +
  71 + int left;
  72 + int pos;
  73 + int bytes_per_second;
  74 + int64_t ratio;
  75 + st_sample_t *buf;
  76 + void *rate;
  77 +
  78 + int wpos;
  79 + int live;
  80 + int active;
  81 + int64_t old_ticks;
  82 + HWVoice *hw;
  83 + char *name;
  84 +} SWVoice;
  85 +
  86 +#define VOICE_ENABLE 1
  87 +#define VOICE_DISABLE 2
  88 +
  89 +struct pcm_ops {
  90 + int (*init) (HWVoice *hw, int freq, int nchannels, audfmt_e fmt);
  91 + void (*fini) (HWVoice *hw);
  92 + void (*run) (HWVoice *hw);
  93 + int (*write) (SWVoice *sw, void *buf, int size);
  94 + int (*ctl) (HWVoice *hw, int cmd, ...);
  95 +};
  96 +
  97 +struct audio_output_driver {
  98 + const char *name;
  99 + void *(*init) (void);
  100 + void (*fini) (void *);
  101 + struct pcm_ops *pcm_ops;
  102 + int can_be_default;
  103 + int max_voices;
  104 + int voice_size;
  105 +};
  106 +
  107 +struct HWVoice {
  108 + int active;
  109 + int enabled;
  110 + int pending_disable;
  111 + int valid;
  112 + int freq;
  113 +
  114 + f_sample *clip;
  115 + audfmt_e fmt;
  116 + int nchannels;
  117 +
  118 + int align;
  119 + int shift;
  120 +
  121 + int rpos;
  122 + int bufsize;
  123 +
  124 + int bytes_per_second;
  125 + st_sample_t *mix_buf;
  126 +
  127 + int samples;
  128 + int64_t old_ticks;
  129 + int nb_voices;
  130 + struct SWVoice **pvoice;
  131 + struct pcm_ops *pcm_ops;
  132 +};
  133 +
  134 +void audio_log (const char *fmt, ...);
  135 +void pcm_sw_free_resources (SWVoice *sw);
  136 +int pcm_sw_alloc_resources (SWVoice *sw);
  137 +void pcm_sw_fini (SWVoice *sw);
  138 +int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
  139 + int nchannels, audfmt_e fmt);
  140 +
  141 +void pcm_hw_clear (HWVoice *hw, void *buf, int len);
  142 +HWVoice * pcm_hw_find_any (HWVoice *hw);
  143 +HWVoice * pcm_hw_find_any_active (HWVoice *hw);
  144 +HWVoice * pcm_hw_find_any_passive (HWVoice *hw);
  145 +HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq,
  146 + int nchannels, audfmt_e fmt);
  147 +HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt);
  148 +int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw);
  149 +int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw);
  150 +SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt);
  151 +
  152 +void pcm_hw_free_resources (HWVoice *hw);
  153 +int pcm_hw_alloc_resources (HWVoice *hw);
  154 +void pcm_hw_fini (HWVoice *hw);
  155 +void pcm_hw_gc (HWVoice *hw);
  156 +int pcm_hw_get_live (HWVoice *hw);
  157 +int pcm_hw_get_live2 (HWVoice *hw, int *nb_active);
  158 +void pcm_hw_dec_live (HWVoice *hw, int decr);
  159 +int pcm_hw_write (SWVoice *sw, void *buf, int len);
  160 +
  161 +int audio_get_conf_int (const char *key, int defval);
  162 +const char *audio_get_conf_str (const char *key, const char *defval);
  163 +
  164 +/* Public API */
  165 +SWVoice * AUD_open (SWVoice *sw, const char *name, int freq,
  166 + int nchannels, audfmt_e fmt);
  167 +int AUD_write (SWVoice *sw, void *pcm_buf, int size);
  168 +void AUD_adjust (SWVoice *sw, int leftover);
  169 +void AUD_reset (SWVoice *sw);
  170 +int AUD_get_free (SWVoice *sw);
  171 +int AUD_get_buffer_size (SWVoice *sw);
  172 +void AUD_run (void);
  173 +void AUD_enable (SWVoice *sw, int on);
  174 +int AUD_calc_elapsed (SWVoice *sw);
  175 +
  176 +static inline void *advance (void *p, int incr)
  177 +{
  178 + uint8_t *d = p;
  179 + return (d + incr);
  180 +}
  181 +
  182 +uint32_t popcount (uint32_t u);
  183 +inline uint32_t lsbindex (uint32_t u);
  184 +
  185 +#define audio_MIN(a, b) ((a)>(b)?(b):(a))
  186 +#define audio_MAX(a, b) ((a)<(b)?(b):(a))
  187 +
  188 +#endif /* audio.h */
... ...
audio/fmodaudio.c 0 → 100644
  1 +/*
  2 + * QEMU FMOD audio output driver
  3 + *
  4 + * Copyright (c) 2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include <fmod.h>
  25 +#include <fmod_errors.h>
  26 +#include "vl.h"
  27 +
  28 +#define AUDIO_CAP "fmod"
  29 +#include "audio/audio.h"
  30 +#include "audio/fmodaudio.h"
  31 +
  32 +#define QC_FMOD_DRV "QEMU_FMOD_DRV"
  33 +#define QC_FMOD_FREQ "QEMU_FMOD_FREQ"
  34 +#define QC_FMOD_SAMPLES "QEMU_FMOD_SAMPLES"
  35 +#define QC_FMOD_CHANNELS "QEMU_FMOD_CHANNELS"
  36 +#define QC_FMOD_BUFSIZE "QEMU_FMOD_BUFSIZE"
  37 +#define QC_FMOD_THRESHOLD "QEMU_FMOD_THRESHOLD"
  38 +
  39 +static struct {
  40 + int nb_samples;
  41 + int freq;
  42 + int nb_channels;
  43 + int bufsize;
  44 + int threshold;
  45 +} conf = {
  46 + 2048,
  47 + 44100,
  48 + 1,
  49 + 0,
  50 + 128
  51 +};
  52 +
  53 +#define errstr() FMOD_ErrorString (FSOUND_GetError ())
  54 +
  55 +static int fmod_hw_write (SWVoice *sw, void *buf, int len)
  56 +{
  57 + return pcm_hw_write (sw, buf, len);
  58 +}
  59 +
  60 +static void fmod_clear_sample (FMODVoice *fmd)
  61 +{
  62 + HWVoice *hw = &fmd->hw;
  63 + int status;
  64 + void *p1 = 0, *p2 = 0;
  65 + unsigned int len1 = 0, len2 = 0;
  66 +
  67 + status = FSOUND_Sample_Lock (
  68 + fmd->fmod_sample,
  69 + 0,
  70 + hw->samples << hw->shift,
  71 + &p1,
  72 + &p2,
  73 + &len1,
  74 + &len2
  75 + );
  76 +
  77 + if (!status) {
  78 + dolog ("Failed to lock sample\nReason: %s\n", errstr ());
  79 + return;
  80 + }
  81 +
  82 + if ((len1 & hw->align) || (len2 & hw->align)) {
  83 + dolog ("Locking sample returned unaligned length %d, %d\n",
  84 + len1, len2);
  85 + goto fail;
  86 + }
  87 +
  88 + if (len1 + len2 != hw->samples << hw->shift) {
  89 + dolog ("Locking sample returned incomplete length %d, %d\n",
  90 + len1 + len2, hw->samples << hw->shift);
  91 + goto fail;
  92 + }
  93 + pcm_hw_clear (hw, p1, hw->samples);
  94 +
  95 + fail:
  96 + status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, len1, len2);
  97 + if (!status) {
  98 + dolog ("Failed to unlock sample\nReason: %s\n", errstr ());
  99 + }
  100 +}
  101 +
  102 +static int fmod_write_sample (HWVoice *hw, uint8_t *dst, st_sample_t *src,
  103 + int src_size, int src_pos, int dst_len)
  104 +{
  105 + int src_len1 = dst_len, src_len2 = 0, pos = src_pos + dst_len;
  106 + st_sample_t *src1 = src + src_pos, *src2 = 0;
  107 +
  108 + if (src_pos + dst_len > src_size) {
  109 + src_len1 = src_size - src_pos;
  110 + src2 = src;
  111 + src_len2 = dst_len - src_len1;
  112 + pos = src_len2;
  113 + }
  114 +
  115 + if (src_len1) {
  116 + hw->clip (dst, src1, src_len1);
  117 + memset (src1, 0, src_len1 * sizeof (st_sample_t));
  118 + advance (dst, src_len1);
  119 + }
  120 +
  121 + if (src_len2) {
  122 + hw->clip (dst, src2, src_len2);
  123 + memset (src2, 0, src_len2 * sizeof (st_sample_t));
  124 + }
  125 + return pos;
  126 +}
  127 +
  128 +static int fmod_unlock_sample (FMODVoice *fmd, void *p1, void *p2,
  129 + unsigned int blen1, unsigned int blen2)
  130 +{
  131 + int status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, blen1, blen2);
  132 + if (!status) {
  133 + dolog ("Failed to unlock sample\nReason: %s\n", errstr ());
  134 + return -1;
  135 + }
  136 + return 0;
  137 +}
  138 +
  139 +static int fmod_lock_sample (FMODVoice *fmd, int pos, int len,
  140 + void **p1, void **p2,
  141 + unsigned int *blen1, unsigned int *blen2)
  142 +{
  143 + HWVoice *hw = &fmd->hw;
  144 + int status;
  145 +
  146 + status = FSOUND_Sample_Lock (
  147 + fmd->fmod_sample,
  148 + pos << hw->shift,
  149 + len << hw->shift,
  150 + p1,
  151 + p2,
  152 + blen1,
  153 + blen2
  154 + );
  155 +
  156 + if (!status) {
  157 + dolog ("Failed to lock sample\nReason: %s\n", errstr ());
  158 + return -1;
  159 + }
  160 +
  161 + if ((*blen1 & hw->align) || (*blen2 & hw->align)) {
  162 + dolog ("Locking sample returned unaligned length %d, %d\n",
  163 + *blen1, *blen2);
  164 + fmod_unlock_sample (fmd, *p1, *p2, *blen1, *blen2);
  165 + return -1;
  166 + }
  167 + return 0;
  168 +}
  169 +
  170 +static void fmod_hw_run (HWVoice *hw)
  171 +{
  172 + FMODVoice *fmd = (FMODVoice *) hw;
  173 + int rpos, live, decr;
  174 + void *p1 = 0, *p2 = 0;
  175 + unsigned int blen1 = 0, blen2 = 0;
  176 + unsigned int len1 = 0, len2 = 0;
  177 + int nb_active;
  178 +
  179 + live = pcm_hw_get_live2 (hw, &nb_active);
  180 + if (live <= 0) {
  181 + return;
  182 + }
  183 +
  184 + if (!hw->pending_disable
  185 + && nb_active
  186 + && conf.threshold
  187 + && live <= conf.threshold) {
  188 + ldebug ("live=%d nb_active=%d\n", live, nb_active);
  189 + return;
  190 + }
  191 +
  192 + decr = live;
  193 +
  194 +#if 1
  195 + if (fmd->channel >= 0) {
  196 + int pos2 = (fmd->old_pos + decr) % hw->samples;
  197 + int pos = FSOUND_GetCurrentPosition (fmd->channel);
  198 +
  199 + if (fmd->old_pos < pos && pos2 >= pos) {
  200 + decr = pos - fmd->old_pos - (pos2 == pos) - 1;
  201 + }
  202 + else if (fmd->old_pos > pos && pos2 >= pos && pos2 < fmd->old_pos) {
  203 + decr = (hw->samples - fmd->old_pos) + pos - (pos2 == pos) - 1;
  204 + }
  205 +/* ldebug ("pos=%d pos2=%d old=%d live=%d decr=%d\n", */
  206 +/* pos, pos2, fmd->old_pos, live, decr); */
  207 + }
  208 +#endif
  209 +
  210 + if (decr <= 0) {
  211 + return;
  212 + }
  213 +
  214 + if (fmod_lock_sample (fmd, fmd->old_pos, decr, &p1, &p2, &blen1, &blen2)) {
  215 + return;
  216 + }
  217 +
  218 + len1 = blen1 >> hw->shift;
  219 + len2 = blen2 >> hw->shift;
  220 + ldebug ("%p %p %d %d %d %d\n", p1, p2, len1, len2, blen1, blen2);
  221 + decr = len1 + len2;
  222 + rpos = hw->rpos;
  223 +
  224 + if (len1) {
  225 + rpos = fmod_write_sample (hw, p1, hw->mix_buf, hw->samples, rpos, len1);
  226 + }
  227 +
  228 + if (len2) {
  229 + rpos = fmod_write_sample (hw, p2, hw->mix_buf, hw->samples, rpos, len2);
  230 + }
  231 +
  232 + fmod_unlock_sample (fmd, p1, p2, blen1, blen2);
  233 +
  234 + pcm_hw_dec_live (hw, decr);
  235 + hw->rpos = rpos % hw->samples;
  236 + fmd->old_pos = (fmd->old_pos + decr) % hw->samples;
  237 +}
  238 +
  239 +static int AUD_to_fmodfmt (audfmt_e fmt, int stereo)
  240 +{
  241 + int mode = FSOUND_LOOP_NORMAL;
  242 +
  243 + switch (fmt) {
  244 + case AUD_FMT_S8:
  245 + mode |= FSOUND_SIGNED | FSOUND_8BITS;
  246 + break;
  247 +
  248 + case AUD_FMT_U8:
  249 + mode |= FSOUND_UNSIGNED | FSOUND_8BITS;
  250 + break;
  251 +
  252 + case AUD_FMT_S16:
  253 + mode |= FSOUND_SIGNED | FSOUND_16BITS;
  254 + break;
  255 +
  256 + case AUD_FMT_U16:
  257 + mode |= FSOUND_UNSIGNED | FSOUND_16BITS;
  258 + break;
  259 +
  260 + default:
  261 + dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
  262 + exit (EXIT_FAILURE);
  263 + }
  264 + mode |= stereo ? FSOUND_STEREO : FSOUND_MONO;
  265 + return mode;
  266 +}
  267 +
  268 +static void fmod_hw_fini (HWVoice *hw)
  269 +{
  270 + FMODVoice *fmd = (FMODVoice *) hw;
  271 +
  272 + if (fmd->fmod_sample) {
  273 + FSOUND_Sample_Free (fmd->fmod_sample);
  274 + fmd->fmod_sample = 0;
  275 +
  276 + if (fmd->channel >= 0) {
  277 + FSOUND_StopSound (fmd->channel);
  278 + }
  279 + }
  280 +}
  281 +
  282 +static int fmod_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
  283 +{
  284 + int bits16, mode, channel;
  285 + FMODVoice *fmd = (FMODVoice *) hw;
  286 +
  287 + mode = AUD_to_fmodfmt (fmt, nchannels == 2 ? 1 : 0);
  288 + fmd->fmod_sample = FSOUND_Sample_Alloc (
  289 + FSOUND_FREE, /* index */
  290 + conf.nb_samples, /* length */
  291 + mode, /* mode */
  292 + freq, /* freq */
  293 + 255, /* volume */
  294 + 128, /* pan */
  295 + 255 /* priority */
  296 + );
  297 +
  298 + if (!fmd->fmod_sample) {
  299 + dolog ("Failed to allocate FMOD sample\nReason: %s\n", errstr ());
  300 + return -1;
  301 + }
  302 +
  303 + channel = FSOUND_PlaySoundEx (FSOUND_FREE, fmd->fmod_sample, 0, 1);
  304 + if (channel < 0) {
  305 + dolog ("Failed to start playing sound\nReason: %s\n", errstr ());
  306 + FSOUND_Sample_Free (fmd->fmod_sample);
  307 + return -1;
  308 + }
  309 + fmd->channel = channel;
  310 +
  311 + hw->freq = freq;
  312 + hw->fmt = fmt;
  313 + hw->nchannels = nchannels;
  314 + bits16 = fmt == AUD_FMT_U16 || fmt == AUD_FMT_S16;
  315 + hw->bufsize = conf.nb_samples << (nchannels == 2) << bits16;
  316 + return 0;
  317 +}
  318 +
  319 +static int fmod_hw_ctl (HWVoice *hw, int cmd, ...)
  320 +{
  321 + int status;
  322 + FMODVoice *fmd = (FMODVoice *) hw;
  323 +
  324 + switch (cmd) {
  325 + case VOICE_ENABLE:
  326 + fmod_clear_sample (fmd);
  327 + status = FSOUND_SetPaused (fmd->channel, 0);
  328 + if (!status) {
  329 + dolog ("Failed to resume channel %d\nReason: %s\n",
  330 + fmd->channel, errstr ());
  331 + }
  332 + break;
  333 +
  334 + case VOICE_DISABLE:
  335 + status = FSOUND_SetPaused (fmd->channel, 1);
  336 + if (!status) {
  337 + dolog ("Failed to pause channel %d\nReason: %s\n",
  338 + fmd->channel, errstr ());
  339 + }
  340 + break;
  341 + }
  342 + return 0;
  343 +}
  344 +
  345 +static struct {
  346 + const char *name;
  347 + int type;
  348 +} drvtab[] = {
  349 + {"none", FSOUND_OUTPUT_NOSOUND},
  350 +#ifdef _WIN32
  351 + {"winmm", FSOUND_OUTPUT_WINMM},
  352 + {"dsound", FSOUND_OUTPUT_DSOUND},
  353 + {"a3d", FSOUND_OUTPUT_A3D},
  354 + {"asio", FSOUND_OUTPUT_ASIO},
  355 +#endif
  356 +#ifdef __linux__
  357 + {"oss", FSOUND_OUTPUT_OSS},
  358 + {"alsa", FSOUND_OUTPUT_ALSA},
  359 + {"esd", FSOUND_OUTPUT_ESD},
  360 +#endif
  361 +#ifdef __APPLE__
  362 + {"mac", FSOUND_OUTPUT_MAC},
  363 +#endif
  364 +#if 0
  365 + {"xbox", FSOUND_OUTPUT_XBOX},
  366 + {"ps2", FSOUND_OUTPUT_PS2},
  367 + {"gcube", FSOUND_OUTPUT_GC},
  368 +#endif
  369 + {"nort", FSOUND_OUTPUT_NOSOUND_NONREALTIME}
  370 +};
  371 +
  372 +static void *fmod_audio_init (void)
  373 +{
  374 + int i;
  375 + double ver;
  376 + int status;
  377 + int output_type = -1;
  378 + const char *drv = audio_get_conf_str (QC_FMOD_DRV, NULL);
  379 +
  380 + ver = FSOUND_GetVersion ();
  381 + if (ver < FMOD_VERSION) {
  382 + dolog ("Wrong FMOD version %f, need at least %f\n", ver, FMOD_VERSION);
  383 + return NULL;
  384 + }
  385 +
  386 + if (drv) {
  387 + int found = 0;
  388 + for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
  389 + if (!strcmp (drv, drvtab[i].name)) {
  390 + output_type = drvtab[i].type;
  391 + found = 1;
  392 + break;
  393 + }
  394 + }
  395 + if (!found) {
  396 + dolog ("Unknown FMOD output driver `%s'\n", drv);
  397 + }
  398 + }
  399 +
  400 + if (output_type != -1) {
  401 + status = FSOUND_SetOutput (output_type);
  402 + if (!status) {
  403 + dolog ("FSOUND_SetOutput(%d) failed\nReason: %s\n",
  404 + output_type, errstr ());
  405 + return NULL;
  406 + }
  407 + }
  408 +
  409 + conf.freq = audio_get_conf_int (QC_FMOD_FREQ, conf.freq);
  410 + conf.nb_samples = audio_get_conf_int (QC_FMOD_SAMPLES, conf.nb_samples);
  411 + conf.nb_channels =
  412 + audio_get_conf_int (QC_FMOD_CHANNELS,
  413 + (audio_state.nb_hw_voices > 1
  414 + ? audio_state.nb_hw_voices
  415 + : conf.nb_channels));
  416 + conf.bufsize = audio_get_conf_int (QC_FMOD_BUFSIZE, conf.bufsize);
  417 + conf.threshold = audio_get_conf_int (QC_FMOD_THRESHOLD, conf.threshold);
  418 +
  419 + if (conf.bufsize) {
  420 + status = FSOUND_SetBufferSize (conf.bufsize);
  421 + if (!status) {
  422 + dolog ("FSOUND_SetBufferSize (%d) failed\nReason: %s\n",
  423 + conf.bufsize, errstr ());
  424 + }
  425 + }
  426 +
  427 + status = FSOUND_Init (conf.freq, conf.nb_channels, 0);
  428 + if (!status) {
  429 + dolog ("FSOUND_Init failed\nReason: %s\n", errstr ());
  430 + return NULL;
  431 + }
  432 +
  433 + return &conf;
  434 +}
  435 +
  436 +static void fmod_audio_fini (void *opaque)
  437 +{
  438 + FSOUND_Close ();
  439 +}
  440 +
  441 +struct pcm_ops fmod_pcm_ops = {
  442 + fmod_hw_init,
  443 + fmod_hw_fini,
  444 + fmod_hw_run,
  445 + fmod_hw_write,
  446 + fmod_hw_ctl
  447 +};
  448 +
  449 +struct audio_output_driver fmod_output_driver = {
  450 + "fmod",
  451 + fmod_audio_init,
  452 + fmod_audio_fini,
  453 + &fmod_pcm_ops,
  454 + 1,
  455 + INT_MAX,
  456 + sizeof (FMODVoice)
  457 +};
... ...
audio/fmodaudio.h 0 → 100644
  1 +/*
  2 + * QEMU FMOD audio output driver header
  3 + *
  4 + * Copyright (c) 2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#ifndef QEMU_FMODAUDIO_H
  25 +#define QEMU_FMODAUDIO_H
  26 +
  27 +#include <fmod.h>
  28 +
  29 +typedef struct FMODVoice {
  30 + struct HWVoice hw;
  31 + unsigned int old_pos;
  32 + FSOUND_SAMPLE *fmod_sample;
  33 + int channel;
  34 +} FMODVoice;
  35 +
  36 +extern struct pcm_ops fmod_pcm_ops;
  37 +extern struct audio_output_driver fmod_output_driver;
  38 +
  39 +#endif /* fmodaudio.h */
... ...
audio/mixeng.c 0 → 100644
  1 +/*
  2 + * QEMU Mixing engine
  3 + *
  4 + * Copyright (c) 2004 Vassili Karpov (malc)
  5 + * Copyright (c) 1998 Fabrice Bellard
  6 + *
  7 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  8 + * of this software and associated documentation files (the "Software"), to deal
  9 + * in the Software without restriction, including without limitation the rights
  10 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 + * copies of the Software, and to permit persons to whom the Software is
  12 + * furnished to do so, subject to the following conditions:
  13 + *
  14 + * The above copyright notice and this permission notice shall be included in
  15 + * all copies or substantial portions of the Software.
  16 + *
  17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 + * THE SOFTWARE.
  24 + */
  25 +#include "vl.h"
  26 +//#define DEBUG_FP
  27 +#include "audio/mixeng.h"
  28 +
  29 +#define IN_T int8_t
  30 +#define IN_MIN CHAR_MIN
  31 +#define IN_MAX CHAR_MAX
  32 +#define SIGNED
  33 +#include "mixeng_template.h"
  34 +#undef SIGNED
  35 +#undef IN_MAX
  36 +#undef IN_MIN
  37 +#undef IN_T
  38 +
  39 +#define IN_T uint8_t
  40 +#define IN_MIN 0
  41 +#define IN_MAX UCHAR_MAX
  42 +#include "mixeng_template.h"
  43 +#undef IN_MAX
  44 +#undef IN_MIN
  45 +#undef IN_T
  46 +
  47 +#define IN_T int16_t
  48 +#define IN_MIN SHRT_MIN
  49 +#define IN_MAX SHRT_MAX
  50 +#define SIGNED
  51 +#include "mixeng_template.h"
  52 +#undef SIGNED
  53 +#undef IN_MAX
  54 +#undef IN_MIN
  55 +#undef IN_T
  56 +
  57 +#define IN_T uint16_t
  58 +#define IN_MIN 0
  59 +#define IN_MAX USHRT_MAX
  60 +#include "mixeng_template.h"
  61 +#undef IN_MAX
  62 +#undef IN_MIN
  63 +#undef IN_T
  64 +
  65 +t_sample *mixeng_conv[2][2][2] = {
  66 + {
  67 + {
  68 + conv_uint8_t_to_mono,
  69 + conv_uint16_t_to_mono
  70 + },
  71 + {
  72 + conv_int8_t_to_mono,
  73 + conv_int16_t_to_mono
  74 + }
  75 + },
  76 + {
  77 + {
  78 + conv_uint8_t_to_stereo,
  79 + conv_uint16_t_to_stereo
  80 + },
  81 + {
  82 + conv_int8_t_to_stereo,
  83 + conv_int16_t_to_stereo
  84 + }
  85 + }
  86 +};
  87 +
  88 +f_sample *mixeng_clip[2][2][2] = {
  89 + {
  90 + {
  91 + clip_uint8_t_from_mono,
  92 + clip_uint16_t_from_mono
  93 + },
  94 + {
  95 + clip_int8_t_from_mono,
  96 + clip_int16_t_from_mono
  97 + }
  98 + },
  99 + {
  100 + {
  101 + clip_uint8_t_from_stereo,
  102 + clip_uint16_t_from_stereo
  103 + },
  104 + {
  105 + clip_int8_t_from_stereo,
  106 + clip_int16_t_from_stereo
  107 + }
  108 + }
  109 +};
  110 +
  111 +/*
  112 + * August 21, 1998
  113 + * Copyright 1998 Fabrice Bellard.
  114 + *
  115 + * [Rewrote completly the code of Lance Norskog And Sundry
  116 + * Contributors with a more efficient algorithm.]
  117 + *
  118 + * This source code is freely redistributable and may be used for
  119 + * any purpose. This copyright notice must be maintained.
  120 + * Lance Norskog And Sundry Contributors are not responsible for
  121 + * the consequences of using this software.
  122 + */
  123 +
  124 +/*
  125 + * Sound Tools rate change effect file.
  126 + */
  127 +/*
  128 + * Linear Interpolation.
  129 + *
  130 + * The use of fractional increment allows us to use no buffer. It
  131 + * avoid the problems at the end of the buffer we had with the old
  132 + * method which stored a possibly big buffer of size
  133 + * lcm(in_rate,out_rate).
  134 + *
  135 + * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
  136 + * the input & output frequencies are equal, a delay of one sample is
  137 + * introduced. Limited to processing 32-bit count worth of samples.
  138 + *
  139 + * 1 << FRAC_BITS evaluating to zero in several places. Changed with
  140 + * an (unsigned long) cast to make it safe. MarkMLl 2/1/99
  141 + */
  142 +
  143 +/* Private data */
  144 +typedef struct ratestuff {
  145 + uint64_t opos;
  146 + uint64_t opos_inc;
  147 + uint32_t ipos; /* position in the input stream (integer) */
  148 + st_sample_t ilast; /* last sample in the input stream */
  149 +} *rate_t;
  150 +
  151 +/*
  152 + * Prepare processing.
  153 + */
  154 +void *st_rate_start (int inrate, int outrate)
  155 +{
  156 + rate_t rate = (rate_t) qemu_mallocz (sizeof (struct ratestuff));
  157 +
  158 + if (!rate) {
  159 + exit (EXIT_FAILURE);
  160 + }
  161 +
  162 + if (inrate == outrate) {
  163 + // exit (EXIT_FAILURE);
  164 + }
  165 +
  166 + if (inrate >= 65535 || outrate >= 65535) {
  167 + // exit (EXIT_FAILURE);
  168 + }
  169 +
  170 + rate->opos = 0;
  171 +
  172 + /* increment */
  173 + rate->opos_inc = (inrate * ((int64_t) UINT_MAX)) / outrate;
  174 +
  175 + rate->ipos = 0;
  176 + rate->ilast.l = 0;
  177 + rate->ilast.r = 0;
  178 + return rate;
  179 +}
  180 +
  181 +/*
  182 + * Processed signed long samples from ibuf to obuf.
  183 + * Return number of samples processed.
  184 + */
  185 +void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
  186 + int *isamp, int *osamp)
  187 +{
  188 + rate_t rate = (rate_t) opaque;
  189 + st_sample_t *istart, *iend;
  190 + st_sample_t *ostart, *oend;
  191 + st_sample_t ilast, icur, out;
  192 + int64_t t;
  193 +
  194 + ilast = rate->ilast;
  195 +
  196 + istart = ibuf;
  197 + iend = ibuf + *isamp;
  198 +
  199 + ostart = obuf;
  200 + oend = obuf + *osamp;
  201 +
  202 + if (rate->opos_inc == 1ULL << 32) {
  203 + int i, n = *isamp > *osamp ? *osamp : *isamp;
  204 + for (i = 0; i < n; i++) {
  205 + obuf[i].l += ibuf[i].r;
  206 + obuf[i].r += ibuf[i].r;
  207 + }
  208 + *isamp = n;
  209 + *osamp = n;
  210 + return;
  211 + }
  212 +
  213 + while (obuf < oend) {
  214 +
  215 + /* Safety catch to make sure we have input samples. */
  216 + if (ibuf >= iend)
  217 + break;
  218 +
  219 + /* read as many input samples so that ipos > opos */
  220 +
  221 + while (rate->ipos <= (rate->opos >> 32)) {
  222 + ilast = *ibuf++;
  223 + rate->ipos++;
  224 + /* See if we finished the input buffer yet */
  225 + if (ibuf >= iend) goto the_end;
  226 + }
  227 +
  228 + icur = *ibuf;
  229 +
  230 + /* interpolate */
  231 + t = rate->opos & 0xffffffff;
  232 + out.l = (ilast.l * (INT_MAX - t) + icur.l * t) / INT_MAX;
  233 + out.r = (ilast.r * (INT_MAX - t) + icur.r * t) / INT_MAX;
  234 +
  235 + /* output sample & increment position */
  236 +#if 0
  237 + *obuf++ = out;
  238 +#else
  239 + obuf->l += out.l;
  240 + obuf->r += out.r;
  241 + obuf += 1;
  242 +#endif
  243 + rate->opos += rate->opos_inc;
  244 + }
  245 +
  246 +the_end:
  247 + *isamp = ibuf - istart;
  248 + *osamp = obuf - ostart;
  249 + rate->ilast = ilast;
  250 +}
  251 +
  252 +void st_rate_stop (void *opaque)
  253 +{
  254 + qemu_free (opaque);
  255 +}
... ...
audio/mixeng.h 0 → 100644
  1 +/*
  2 + * QEMU Mixing engine header
  3 + *
  4 + * Copyright (c) 2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#ifndef QEMU_MIXENG_H
  25 +#define QEMU_MIXENG_H
  26 +
  27 +typedef void (t_sample) (void *dst, const void *src, int samples);
  28 +typedef void (f_sample) (void *dst, const void *src, int samples);
  29 +typedef struct { int64_t l; int64_t r; } st_sample_t;
  30 +
  31 +extern t_sample *mixeng_conv[2][2][2];
  32 +extern f_sample *mixeng_clip[2][2][2];
  33 +
  34 +void *st_rate_start (int inrate, int outrate);
  35 +void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
  36 + int *isamp, int *osamp);
  37 +void st_rate_stop (void *opaque);
  38 +
  39 +#endif /* mixeng.h */
... ...
audio/mixeng_template.h 0 → 100644
  1 +/*
  2 + * QEMU Mixing engine
  3 + *
  4 + * Copyright (c) 2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +/*
  26 + * Tusen tack till Mike Nordell
  27 + * dec++'ified by Dscho
  28 + */
  29 +
  30 +#ifdef SIGNED
  31 +#define HALFT IN_MAX
  32 +#define HALF IN_MAX
  33 +#else
  34 +#define HALFT ((IN_MAX)>>1)
  35 +#define HALF HALFT
  36 +#endif
  37 +
  38 +static int64_t inline glue(conv_,IN_T) (IN_T v)
  39 +{
  40 +#ifdef SIGNED
  41 + return (INT_MAX*(int64_t)v)/HALF;
  42 +#else
  43 + return (INT_MAX*((int64_t)v-HALFT))/HALF;
  44 +#endif
  45 +}
  46 +
  47 +static IN_T inline glue(clip_,IN_T) (int64_t v)
  48 +{
  49 + if (v >= INT_MAX)
  50 + return IN_MAX;
  51 + else if (v < -INT_MAX)
  52 + return IN_MIN;
  53 +
  54 +#ifdef SIGNED
  55 + return (IN_T) (v*HALF/INT_MAX);
  56 +#else
  57 + return (IN_T) (v+INT_MAX/2)*HALF/INT_MAX;
  58 +#endif
  59 +}
  60 +
  61 +static void glue(glue(conv_,IN_T),_to_stereo) (void *dst, const void *src,
  62 + int samples)
  63 +{
  64 + st_sample_t *out = (st_sample_t *) dst;
  65 + IN_T *in = (IN_T *) src;
  66 + while (samples--) {
  67 + out->l = glue(conv_,IN_T) (*in++);
  68 + out->r = glue(conv_,IN_T) (*in++);
  69 + out += 1;
  70 + }
  71 +}
  72 +
  73 +static void glue(glue(conv_,IN_T),_to_mono) (void *dst, const void *src,
  74 + int samples)
  75 +{
  76 + st_sample_t *out = (st_sample_t *) dst;
  77 + IN_T *in = (IN_T *) src;
  78 + while (samples--) {
  79 + out->l = glue(conv_,IN_T) (in[0]);
  80 + out->r = out->l;
  81 + out += 1;
  82 + in += 1;
  83 + }
  84 +}
  85 +
  86 +static void glue(glue(clip_,IN_T),_from_stereo) (void *dst, const void *src,
  87 + int samples)
  88 +{
  89 + st_sample_t *in = (st_sample_t *) src;
  90 + IN_T *out = (IN_T *) dst;
  91 + while (samples--) {
  92 + *out++ = glue(clip_,IN_T) (in->l);
  93 + *out++ = glue(clip_,IN_T) (in->r);
  94 + in += 1;
  95 + }
  96 +}
  97 +
  98 +static void glue(glue(clip_,IN_T),_from_mono) (void *dst, const void *src,
  99 + int samples)
  100 +{
  101 + st_sample_t *in = (st_sample_t *) src;
  102 + IN_T *out = (IN_T *) dst;
  103 + while (samples--) {
  104 + *out++ = glue(clip_,IN_T) (in->l + in->r);
  105 + in += 1;
  106 + }
  107 +}
  108 +
  109 +#undef HALF
  110 +#undef HALFT
  111 +
... ...
audio/ossaudio.c 0 → 100644
  1 +/*
  2 + * QEMU OSS audio output driver
  3 + *
  4 + * Copyright (c) 2003-2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +/* Temporary kludge */
  26 +#if defined __linux__ || (defined _BSD && !defined __APPLE__)
  27 +#include <assert.h>
  28 +#include "vl.h"
  29 +
  30 +#include <sys/mman.h>
  31 +#include <sys/types.h>
  32 +#include <sys/ioctl.h>
  33 +#include <sys/soundcard.h>
  34 +
  35 +#define AUDIO_CAP "oss"
  36 +#include "audio/audio.h"
  37 +#include "audio/ossaudio.h"
  38 +
  39 +#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
  40 +#define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS"
  41 +#define QC_OSS_MMAP "QEMU_OSS_MMAP"
  42 +#define QC_OSS_DEV "QEMU_OSS_DEV"
  43 +
  44 +#define errstr() strerror (errno)
  45 +
  46 +static struct {
  47 + int try_mmap;
  48 + int nfrags;
  49 + int fragsize;
  50 + const char *dspname;
  51 +} conf = {
  52 + .try_mmap = 0,
  53 + .nfrags = 4,
  54 + .fragsize = 4096,
  55 + .dspname = "/dev/dsp"
  56 +};
  57 +
  58 +struct oss_params {
  59 + int freq;
  60 + audfmt_e fmt;
  61 + int nchannels;
  62 + int nfrags;
  63 + int fragsize;
  64 +};
  65 +
  66 +static int oss_hw_write (SWVoice *sw, void *buf, int len)
  67 +{
  68 + return pcm_hw_write (sw, buf, len);
  69 +}
  70 +
  71 +static int AUD_to_ossfmt (audfmt_e fmt)
  72 +{
  73 + switch (fmt) {
  74 + case AUD_FMT_S8: return AFMT_S8;
  75 + case AUD_FMT_U8: return AFMT_U8;
  76 + case AUD_FMT_S16: return AFMT_S16_LE;
  77 + case AUD_FMT_U16: return AFMT_U16_LE;
  78 + default:
  79 + dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
  80 + exit (EXIT_FAILURE);
  81 + }
  82 +}
  83 +
  84 +static int oss_to_audfmt (int fmt)
  85 +{
  86 + switch (fmt) {
  87 + case AFMT_S8: return AUD_FMT_S8;
  88 + case AFMT_U8: return AUD_FMT_U8;
  89 + case AFMT_S16_LE: return AUD_FMT_S16;
  90 + case AFMT_U16_LE: return AUD_FMT_U16;
  91 + default:
  92 + dolog ("Internal logic error: Unrecognized OSS audio format %d\n"
  93 + "Aborting\n",
  94 + fmt);
  95 + exit (EXIT_FAILURE);
  96 + }
  97 +}
  98 +
  99 +#ifdef DEBUG_PCM
  100 +static void oss_dump_pcm_info (struct oss_params *req, struct oss_params *obt)
  101 +{
  102 + dolog ("parameter | requested value | obtained value\n");
  103 + dolog ("format | %10d | %10d\n", req->fmt, obt->fmt);
  104 + dolog ("channels | %10d | %10d\n", req->nchannels, obt->nchannels);
  105 + dolog ("frequency | %10d | %10d\n", req->freq, obt->freq);
  106 + dolog ("nfrags | %10d | %10d\n", req->nfrags, obt->nfrags);
  107 + dolog ("fragsize | %10d | %10d\n", req->fragsize, obt->fragsize);
  108 +}
  109 +#endif
  110 +
  111 +static int oss_open (struct oss_params *req, struct oss_params *obt, int *pfd)
  112 +{
  113 + int fd;
  114 + int mmmmssss;
  115 + audio_buf_info abinfo;
  116 + int fmt, freq, nchannels;
  117 + const char *dspname = conf.dspname;
  118 +
  119 + fd = open (dspname, O_RDWR | O_NONBLOCK);
  120 + if (-1 == fd) {
  121 + dolog ("Could not initialize audio hardware. Failed to open `%s':\n"
  122 + "Reason:%s\n",
  123 + dspname,
  124 + errstr ());
  125 + return -1;
  126 + }
  127 +
  128 + freq = req->freq;
  129 + nchannels = req->nchannels;
  130 + fmt = req->fmt;
  131 +
  132 + if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
  133 + dolog ("Could not initialize audio hardware\n"
  134 + "Failed to set sample size\n"
  135 + "Reason: %s\n",
  136 + errstr ());
  137 + goto err;
  138 + }
  139 +
  140 + if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
  141 + dolog ("Could not initialize audio hardware\n"
  142 + "Failed to set number of channels\n"
  143 + "Reason: %s\n",
  144 + errstr ());
  145 + goto err;
  146 + }
  147 +
  148 + if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
  149 + dolog ("Could not initialize audio hardware\n"
  150 + "Failed to set frequency\n"
  151 + "Reason: %s\n",
  152 + errstr ());
  153 + goto err;
  154 + }
  155 +
  156 + if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) {
  157 + dolog ("Could not initialize audio hardware\n"
  158 + "Failed to set non-blocking mode\n"
  159 + "Reason: %s\n",
  160 + errstr ());
  161 + goto err;
  162 + }
  163 +
  164 + mmmmssss = (req->nfrags << 16) | lsbindex (req->fragsize);
  165 + if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
  166 + dolog ("Could not initialize audio hardware\n"
  167 + "Failed to set buffer length (%d, %d)\n"
  168 + "Reason:%s\n",
  169 + conf.nfrags, conf.fragsize,
  170 + errstr ());
  171 + goto err;
  172 + }
  173 +
  174 + if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &abinfo)) {
  175 + dolog ("Could not initialize audio hardware\n"
  176 + "Failed to get buffer length\n"
  177 + "Reason:%s\n",
  178 + errstr ());
  179 + goto err;
  180 + }
  181 +
  182 + obt->fmt = fmt;
  183 + obt->nchannels = nchannels;
  184 + obt->freq = freq;
  185 + obt->nfrags = abinfo.fragstotal;
  186 + obt->fragsize = abinfo.fragsize;
  187 + *pfd = fd;
  188 +
  189 + if ((req->fmt != obt->fmt) ||
  190 + (req->nchannels != obt->nchannels) ||
  191 + (req->freq != obt->freq) ||
  192 + (req->fragsize != obt->fragsize) ||
  193 + (req->nfrags != obt->nfrags)) {
  194 +#ifdef DEBUG_PCM
  195 + dolog ("Audio parameters mismatch\n");
  196 + oss_dump_pcm_info (req, obt);
  197 +#endif
  198 + }
  199 +
  200 +#ifdef DEBUG_PCM
  201 + oss_dump_pcm_info (req, obt);
  202 +#endif
  203 + return 0;
  204 +
  205 +err:
  206 + close (fd);
  207 + return -1;
  208 +}
  209 +
  210 +static void oss_hw_run (HWVoice *hw)
  211 +{
  212 + OSSVoice *oss = (OSSVoice *) hw;
  213 + int err, rpos, live, decr;
  214 + int samples;
  215 + uint8_t *dst;
  216 + st_sample_t *src;
  217 + struct audio_buf_info abinfo;
  218 + struct count_info cntinfo;
  219 +
  220 + live = pcm_hw_get_live (hw);
  221 + if (live <= 0)
  222 + return;
  223 +
  224 + if (oss->mmapped) {
  225 + int bytes;
  226 +
  227 + err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
  228 + if (err < 0) {
  229 + dolog ("SNDCTL_DSP_GETOPTR failed\nReason: %s\n", errstr ());
  230 + return;
  231 + }
  232 +
  233 + if (cntinfo.ptr == oss->old_optr) {
  234 + if (abs (hw->samples - live) < 64)
  235 + dolog ("overrun\n");
  236 + return;
  237 + }
  238 +
  239 + if (cntinfo.ptr > oss->old_optr) {
  240 + bytes = cntinfo.ptr - oss->old_optr;
  241 + }
  242 + else {
  243 + bytes = hw->bufsize + cntinfo.ptr - oss->old_optr;
  244 + }
  245 +
  246 + decr = audio_MIN (bytes >> hw->shift, live);
  247 + }
  248 + else {
  249 + err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
  250 + if (err < 0) {
  251 + dolog ("SNDCTL_DSP_GETOSPACE failed\nReason: %s\n", errstr ());
  252 + return;
  253 + }
  254 +
  255 + decr = audio_MIN (abinfo.bytes >> hw->shift, live);
  256 + if (decr <= 0)
  257 + return;
  258 + }
  259 +
  260 + samples = decr;
  261 + rpos = hw->rpos;
  262 + while (samples) {
  263 + int left_till_end_samples = hw->samples - rpos;
  264 + int convert_samples = audio_MIN (samples, left_till_end_samples);
  265 +
  266 + src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
  267 + dst = advance (oss->pcm_buf, rpos << hw->shift);
  268 +
  269 + hw->clip (dst, src, convert_samples);
  270 + if (!oss->mmapped) {
  271 + int written;
  272 +
  273 + written = write (oss->fd, dst, convert_samples << hw->shift);
  274 + /* XXX: follow errno recommendations ? */
  275 + if (written == -1) {
  276 + dolog ("Failed to write audio\nReason: %s\n", errstr ());
  277 + continue;
  278 + }
  279 +
  280 + if (written != convert_samples << hw->shift) {
  281 + int wsamples = written >> hw->shift;
  282 + int wbytes = wsamples << hw->shift;
  283 + if (wbytes != written) {
  284 + dolog ("Unaligned write %d, %d\n", wbytes, written);
  285 + }
  286 + memset (src, 0, wbytes);
  287 + decr -= samples;
  288 + rpos = (rpos + wsamples) % hw->samples;
  289 + break;
  290 + }
  291 + }
  292 + memset (src, 0, convert_samples * sizeof (st_sample_t));
  293 +
  294 + rpos = (rpos + convert_samples) % hw->samples;
  295 + samples -= convert_samples;
  296 + }
  297 + if (oss->mmapped) {
  298 + oss->old_optr = cntinfo.ptr;
  299 + }
  300 +
  301 + pcm_hw_dec_live (hw, decr);
  302 + hw->rpos = rpos;
  303 +}
  304 +
  305 +static void oss_hw_fini (HWVoice *hw)
  306 +{
  307 + int err;
  308 + OSSVoice *oss = (OSSVoice *) hw;
  309 +
  310 + ldebug ("oss_hw_fini\n");
  311 + err = close (oss->fd);
  312 + if (err) {
  313 + dolog ("Failed to close OSS descriptor\nReason: %s\n", errstr ());
  314 + }
  315 + oss->fd = -1;
  316 +
  317 + if (oss->pcm_buf) {
  318 + if (oss->mmapped) {
  319 + err = munmap (oss->pcm_buf, hw->bufsize);
  320 + if (err) {
  321 + dolog ("Failed to unmap OSS buffer\nReason: %s\n",
  322 + errstr ());
  323 + }
  324 + }
  325 + else {
  326 + qemu_free (oss->pcm_buf);
  327 + }
  328 + oss->pcm_buf = NULL;
  329 + }
  330 +}
  331 +
  332 +static int oss_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
  333 +{
  334 + OSSVoice *oss = (OSSVoice *) hw;
  335 + struct oss_params req, obt;
  336 +
  337 + assert (!oss->fd);
  338 + req.fmt = AUD_to_ossfmt (fmt);
  339 + req.freq = freq;
  340 + req.nchannels = nchannels;
  341 + req.fragsize = conf.fragsize;
  342 + req.nfrags = conf.nfrags;
  343 +
  344 + if (oss_open (&req, &obt, &oss->fd))
  345 + return -1;
  346 +
  347 + hw->freq = obt.freq;
  348 + hw->fmt = oss_to_audfmt (obt.fmt);
  349 + hw->nchannels = obt.nchannels;
  350 +
  351 + oss->nfrags = obt.nfrags;
  352 + oss->fragsize = obt.fragsize;
  353 + hw->bufsize = obt.nfrags * obt.fragsize;
  354 +
  355 + oss->mmapped = 0;
  356 + if (conf.try_mmap) {
  357 + oss->pcm_buf = mmap (0, hw->bufsize, PROT_READ | PROT_WRITE,
  358 + MAP_SHARED, oss->fd, 0);
  359 + if (oss->pcm_buf == MAP_FAILED) {
  360 + dolog ("Failed to mmap OSS device\nReason: %s\n",
  361 + errstr ());
  362 + }
  363 +
  364 + for (;;) {
  365 + int err;
  366 + int trig = 0;
  367 + if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
  368 + dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
  369 + errstr ());
  370 + goto fail;
  371 + }
  372 +
  373 + trig = PCM_ENABLE_OUTPUT;
  374 + if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
  375 + dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
  376 + "Reason: %s\n", errstr ());
  377 + goto fail;
  378 + }
  379 + oss->mmapped = 1;
  380 + break;
  381 +
  382 + fail:
  383 + err = munmap (oss->pcm_buf, hw->bufsize);
  384 + if (err) {
  385 + dolog ("Failed to unmap OSS device\nReason: %s\n",
  386 + errstr ());
  387 + }
  388 + }
  389 + }
  390 +
  391 + if (!oss->mmapped) {
  392 + oss->pcm_buf = qemu_mallocz (hw->bufsize);
  393 + if (!oss->pcm_buf) {
  394 + close (oss->fd);
  395 + oss->fd = -1;
  396 + return -1;
  397 + }
  398 + }
  399 +
  400 + return 0;
  401 +}
  402 +
  403 +static int oss_hw_ctl (HWVoice *hw, int cmd, ...)
  404 +{
  405 + int trig;
  406 + OSSVoice *oss = (OSSVoice *) hw;
  407 +
  408 + if (!oss->mmapped)
  409 + return 0;
  410 +
  411 + switch (cmd) {
  412 + case VOICE_ENABLE:
  413 + ldebug ("enabling voice\n");
  414 + pcm_hw_clear (hw, oss->pcm_buf, hw->samples);
  415 + trig = PCM_ENABLE_OUTPUT;
  416 + if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
  417 + dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
  418 + "Reason: %s\n", errstr ());
  419 + return -1;
  420 + }
  421 + break;
  422 +
  423 + case VOICE_DISABLE:
  424 + ldebug ("disabling voice\n");
  425 + trig = 0;
  426 + if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
  427 + dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
  428 + errstr ());
  429 + return -1;
  430 + }
  431 + break;
  432 + }
  433 + return 0;
  434 +}
  435 +
  436 +static void *oss_audio_init (void)
  437 +{
  438 + conf.fragsize = audio_get_conf_int (QC_OSS_FRAGSIZE, conf.fragsize);
  439 + conf.nfrags = audio_get_conf_int (QC_OSS_NFRAGS, conf.nfrags);
  440 + conf.try_mmap = audio_get_conf_int (QC_OSS_MMAP, conf.try_mmap);
  441 + conf.dspname = audio_get_conf_str (QC_OSS_DEV, conf.dspname);
  442 + return &conf;
  443 +}
  444 +
  445 +static void oss_audio_fini (void *opaque)
  446 +{
  447 +}
  448 +
  449 +struct pcm_ops oss_pcm_ops = {
  450 + oss_hw_init,
  451 + oss_hw_fini,
  452 + oss_hw_run,
  453 + oss_hw_write,
  454 + oss_hw_ctl
  455 +};
  456 +
  457 +struct audio_output_driver oss_output_driver = {
  458 + "oss",
  459 + oss_audio_init,
  460 + oss_audio_fini,
  461 + &oss_pcm_ops,
  462 + 1,
  463 + INT_MAX,
  464 + sizeof (OSSVoice)
  465 +};
  466 +#endif
... ...
audio/ossaudio.h 0 → 100644
  1 +/*
  2 + * QEMU OSS audio output driver header
  3 + *
  4 + * Copyright (c) 2003-2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#ifndef QEMU_OSSAUDIO_H
  25 +#define QEMU_OSSAUDIO_H
  26 +
  27 +typedef struct OSSVoice {
  28 + struct HWVoice hw;
  29 + void *pcm_buf;
  30 + int fd;
  31 + int nfrags;
  32 + int fragsize;
  33 + int mmapped;
  34 + int old_optr;
  35 +} OSSVoice;
  36 +
  37 +extern struct pcm_ops oss_pcm_ops;
  38 +extern struct audio_output_driver oss_output_driver;
  39 +
  40 +#endif /* ossaudio.h */
... ...
audio/sdlaudio.c 0 → 100644
  1 +/*
  2 + * QEMU SDL audio output driver
  3 + *
  4 + * Copyright (c) 2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include <SDL/SDL.h>
  25 +#include <SDL/SDL_thread.h>
  26 +#include "vl.h"
  27 +
  28 +#define AUDIO_CAP "sdl"
  29 +#include "audio/audio.h"
  30 +#include "audio/sdlaudio.h"
  31 +
  32 +#define QC_SDL_SAMPLES "QEMU_SDL_SAMPLES"
  33 +
  34 +#define errstr() SDL_GetError ()
  35 +
  36 +static struct {
  37 + int nb_samples;
  38 +} conf = {
  39 + 1024
  40 +};
  41 +
  42 +struct SDLAudioState {
  43 + int exit;
  44 + SDL_mutex *mutex;
  45 + SDL_sem *sem;
  46 + int initialized;
  47 +} glob_sdl;
  48 +typedef struct SDLAudioState SDLAudioState;
  49 +
  50 +static void sdl_hw_run (HWVoice *hw)
  51 +{
  52 + (void) hw;
  53 +}
  54 +
  55 +static int sdl_lock (SDLAudioState *s)
  56 +{
  57 + if (SDL_LockMutex (s->mutex)) {
  58 + dolog ("SDL_LockMutex failed\nReason: %s\n", errstr ());
  59 + return -1;
  60 + }
  61 + return 0;
  62 +}
  63 +
  64 +static int sdl_unlock (SDLAudioState *s)
  65 +{
  66 + if (SDL_UnlockMutex (s->mutex)) {
  67 + dolog ("SDL_UnlockMutex failed\nReason: %s\n", errstr ());
  68 + return -1;
  69 + }
  70 + return 0;
  71 +}
  72 +
  73 +static int sdl_post (SDLAudioState *s)
  74 +{
  75 + if (SDL_SemPost (s->sem)) {
  76 + dolog ("SDL_SemPost failed\nReason: %s\n", errstr ());
  77 + return -1;
  78 + }
  79 + return 0;
  80 +}
  81 +
  82 +static int sdl_wait (SDLAudioState *s)
  83 +{
  84 + if (SDL_SemWait (s->sem)) {
  85 + dolog ("SDL_SemWait failed\nReason: %s\n", errstr ());
  86 + return -1;
  87 + }
  88 + return 0;
  89 +}
  90 +
  91 +static int sdl_unlock_and_post (SDLAudioState *s)
  92 +{
  93 + if (sdl_unlock (s))
  94 + return -1;
  95 +
  96 + return sdl_post (s);
  97 +}
  98 +
  99 +static int sdl_hw_write (SWVoice *sw, void *buf, int len)
  100 +{
  101 + int ret;
  102 + SDLAudioState *s = &glob_sdl;
  103 + sdl_lock (s);
  104 + ret = pcm_hw_write (sw, buf, len);
  105 + sdl_unlock_and_post (s);
  106 + return ret;
  107 +}
  108 +
  109 +static int AUD_to_sdlfmt (audfmt_e fmt, int *shift)
  110 +{
  111 + *shift = 0;
  112 + switch (fmt) {
  113 + case AUD_FMT_S8: return AUDIO_S8;
  114 + case AUD_FMT_U8: return AUDIO_U8;
  115 + case AUD_FMT_S16: *shift = 1; return AUDIO_S16LSB;
  116 + case AUD_FMT_U16: *shift = 1; return AUDIO_U16LSB;
  117 + default:
  118 + dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
  119 + exit (EXIT_FAILURE);
  120 + }
  121 +}
  122 +
  123 +static int sdl_to_audfmt (int fmt)
  124 +{
  125 + switch (fmt) {
  126 + case AUDIO_S8: return AUD_FMT_S8;
  127 + case AUDIO_U8: return AUD_FMT_U8;
  128 + case AUDIO_S16LSB: return AUD_FMT_S16;
  129 + case AUDIO_U16LSB: return AUD_FMT_U16;
  130 + default:
  131 + dolog ("Internal logic error: Unrecognized SDL audio format %d\n"
  132 + "Aborting\n", fmt);
  133 + exit (EXIT_FAILURE);
  134 + }
  135 +}
  136 +
  137 +static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
  138 +{
  139 + int status;
  140 +
  141 + status = SDL_OpenAudio (req, obt);
  142 + if (status) {
  143 + dolog ("SDL_OpenAudio failed\nReason: %s\n", errstr ());
  144 + }
  145 + return status;
  146 +}
  147 +
  148 +static void sdl_close (SDLAudioState *s)
  149 +{
  150 + if (s->initialized) {
  151 + sdl_lock (s);
  152 + s->exit = 1;
  153 + sdl_unlock_and_post (s);
  154 + SDL_PauseAudio (1);
  155 + SDL_CloseAudio ();
  156 + s->initialized = 0;
  157 + }
  158 +}
  159 +
  160 +static void sdl_callback (void *opaque, Uint8 *buf, int len)
  161 +{
  162 + SDLVoice *sdl = opaque;
  163 + SDLAudioState *s = &glob_sdl;
  164 + HWVoice *hw = &sdl->hw;
  165 + int samples = len >> hw->shift;
  166 +
  167 + if (s->exit) {
  168 + return;
  169 + }
  170 +
  171 + while (samples) {
  172 + int to_mix, live, decr;
  173 +
  174 + /* dolog ("in callback samples=%d\n", samples); */
  175 + sdl_wait (s);
  176 + if (s->exit) {
  177 + return;
  178 + }
  179 +
  180 + sdl_lock (s);
  181 + live = pcm_hw_get_live (hw);
  182 + if (live <= 0)
  183 + goto again;
  184 +
  185 + /* dolog ("in callback live=%d\n", live); */
  186 + to_mix = audio_MIN (samples, live);
  187 + decr = to_mix;
  188 + while (to_mix) {
  189 + int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
  190 + st_sample_t *src = hw->mix_buf + hw->rpos;
  191 +
  192 + /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
  193 + hw->clip (buf, src, chunk);
  194 + memset (src, 0, chunk * sizeof (st_sample_t));
  195 + hw->rpos = (hw->rpos + chunk) % hw->samples;
  196 + to_mix -= chunk;
  197 + buf += chunk << hw->shift;
  198 + }
  199 + samples -= decr;
  200 + pcm_hw_dec_live (hw, decr);
  201 +
  202 + again:
  203 + sdl_unlock (s);
  204 + }
  205 + /* dolog ("done len=%d\n", len); */
  206 +}
  207 +
  208 +static void sdl_hw_fini (HWVoice *hw)
  209 +{
  210 + ldebug ("sdl_hw_fini %d fixed=%d\n",
  211 + glob_sdl.initialized, audio_conf.fixed_format);
  212 + sdl_close (&glob_sdl);
  213 +}
  214 +
  215 +static int sdl_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
  216 +{
  217 + SDLVoice *sdl = (SDLVoice *) hw;
  218 + SDLAudioState *s = &glob_sdl;
  219 + SDL_AudioSpec req, obt;
  220 + int shift;
  221 +
  222 + ldebug ("sdl_hw_init %d freq=%d fixed=%d\n",
  223 + s->initialized, freq, audio_conf.fixed_format);
  224 +
  225 + if (nchannels != 2) {
  226 + dolog ("Bogus channel count %d\n", nchannels);
  227 + return -1;
  228 + }
  229 +
  230 + req.freq = freq;
  231 + req.format = AUD_to_sdlfmt (fmt, &shift);
  232 + req.channels = nchannels;
  233 + req.samples = conf.nb_samples;
  234 + shift <<= nchannels == 2;
  235 +
  236 + req.callback = sdl_callback;
  237 + req.userdata = sdl;
  238 +
  239 + if (sdl_open (&req, &obt))
  240 + return -1;
  241 +
  242 + hw->freq = obt.freq;
  243 + hw->fmt = sdl_to_audfmt (obt.format);
  244 + hw->nchannels = obt.channels;
  245 + hw->bufsize = obt.samples << shift;
  246 +
  247 + s->initialized = 1;
  248 + s->exit = 0;
  249 + SDL_PauseAudio (0);
  250 + return 0;
  251 +}
  252 +
  253 +static int sdl_hw_ctl (HWVoice *hw, int cmd, ...)
  254 +{
  255 + (void) hw;
  256 +
  257 + switch (cmd) {
  258 + case VOICE_ENABLE:
  259 + SDL_PauseAudio (0);
  260 + break;
  261 +
  262 + case VOICE_DISABLE:
  263 + SDL_PauseAudio (1);
  264 + break;
  265 + }
  266 + return 0;
  267 +}
  268 +
  269 +static void *sdl_audio_init (void)
  270 +{
  271 + SDLAudioState *s = &glob_sdl;
  272 + conf.nb_samples = audio_get_conf_int (QC_SDL_SAMPLES, conf.nb_samples);
  273 +
  274 + if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
  275 + dolog ("SDL failed to initialize audio subsystem\nReason: %s\n",
  276 + errstr ());
  277 + return NULL;
  278 + }
  279 +
  280 + s->mutex = SDL_CreateMutex ();
  281 + if (!s->mutex) {
  282 + dolog ("Failed to create SDL mutex\nReason: %s\n", errstr ());
  283 + SDL_QuitSubSystem (SDL_INIT_AUDIO);
  284 + return NULL;
  285 + }
  286 +
  287 + s->sem = SDL_CreateSemaphore (0);
  288 + if (!s->sem) {
  289 + dolog ("Failed to create SDL semaphore\nReason: %s\n", errstr ());
  290 + SDL_DestroyMutex (s->mutex);
  291 + SDL_QuitSubSystem (SDL_INIT_AUDIO);
  292 + return NULL;
  293 + }
  294 +
  295 + return s;
  296 +}
  297 +
  298 +static void sdl_audio_fini (void *opaque)
  299 +{
  300 + SDLAudioState *s = opaque;
  301 + sdl_close (s);
  302 + SDL_DestroySemaphore (s->sem);
  303 + SDL_DestroyMutex (s->mutex);
  304 + SDL_QuitSubSystem (SDL_INIT_AUDIO);
  305 +}
  306 +
  307 +struct pcm_ops sdl_pcm_ops = {
  308 + sdl_hw_init,
  309 + sdl_hw_fini,
  310 + sdl_hw_run,
  311 + sdl_hw_write,
  312 + sdl_hw_ctl
  313 +};
  314 +
  315 +struct audio_output_driver sdl_output_driver = {
  316 + "sdl",
  317 + sdl_audio_init,
  318 + sdl_audio_fini,
  319 + &sdl_pcm_ops,
  320 + 1,
  321 + 1,
  322 + sizeof (SDLVoice)
  323 +};
... ...
audio/sdlaudio.h 0 → 100644
  1 +/*
  2 + * QEMU SDL audio output driver header
  3 + *
  4 + * Copyright (c) 2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#ifndef QEMU_SDLAUDIO_H
  25 +#define QEMU_SDLAUDIO_H
  26 +
  27 +typedef struct SDLVoice {
  28 + struct HWVoice hw;
  29 +} SDLVoice;
  30 +
  31 +extern struct pcm_ops sdl_pcm_ops;
  32 +extern struct audio_output_driver sdl_output_driver;
  33 +
  34 +#endif /* sdlaudio.h */
... ...
audio/wavaudio.c 0 → 100644
  1 +/*
  2 + * QEMU WAV audio output driver
  3 + *
  4 + * Copyright (c) 2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +#define AUDIO_CAP "wav"
  27 +#include "audio/audio.h"
  28 +#include "audio/wavaudio.h"
  29 +
  30 +static struct {
  31 + const char *wav_path;
  32 +} conf = {
  33 + .wav_path = "qemu.wav"
  34 +};
  35 +
  36 +static void wav_hw_run (HWVoice *hw)
  37 +{
  38 + WAVVoice *wav = (WAVVoice *) hw;
  39 + int rpos, live, decr, samples;
  40 + uint8_t *dst;
  41 + st_sample_t *src;
  42 + int64_t now = qemu_get_clock (vm_clock);
  43 + int64_t ticks = now - wav->old_ticks;
  44 + int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec;
  45 + wav->old_ticks = now;
  46 +
  47 + if (bytes > INT_MAX)
  48 + samples = INT_MAX >> hw->shift;
  49 + else
  50 + samples = bytes >> hw->shift;
  51 +
  52 + live = pcm_hw_get_live (hw);
  53 + if (live <= 0)
  54 + return;
  55 +
  56 + decr = audio_MIN (live, samples);
  57 + samples = decr;
  58 + rpos = hw->rpos;
  59 + while (samples) {
  60 + int left_till_end_samples = hw->samples - rpos;
  61 + int convert_samples = audio_MIN (samples, left_till_end_samples);
  62 +
  63 + src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
  64 + dst = advance (wav->pcm_buf, rpos << hw->shift);
  65 +
  66 + hw->clip (dst, src, convert_samples);
  67 + qemu_put_buffer (wav->f, dst, convert_samples << hw->shift);
  68 + memset (src, 0, convert_samples * sizeof (st_sample_t));
  69 +
  70 + rpos = (rpos + convert_samples) % hw->samples;
  71 + samples -= convert_samples;
  72 + wav->total_samples += convert_samples;
  73 + }
  74 +
  75 + pcm_hw_dec_live (hw, decr);
  76 + hw->rpos = rpos;
  77 +}
  78 +
  79 +static int wav_hw_write (SWVoice *sw, void *buf, int len)
  80 +{
  81 + return pcm_hw_write (sw, buf, len);
  82 +}
  83 +
  84 +
  85 +/* VICE code: Store number as little endian. */
  86 +static void le_store (uint8_t *buf, uint32_t val, int len)
  87 +{
  88 + int i;
  89 + for (i = 0; i < len; i++) {
  90 + buf[i] = (uint8_t) (val & 0xff);
  91 + val >>= 8;
  92 + }
  93 +}
  94 +
  95 +static int wav_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
  96 +{
  97 + WAVVoice *wav = (WAVVoice *) hw;
  98 + int bits16 = 0, stereo = audio_state.fixed_channels == 2;
  99 + uint8_t hdr[] = {
  100 + 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
  101 + 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
  102 + 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
  103 + 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
  104 + };
  105 +
  106 + switch (audio_state.fixed_fmt) {
  107 + case AUD_FMT_S8:
  108 + case AUD_FMT_U8:
  109 + break;
  110 +
  111 + case AUD_FMT_S16:
  112 + case AUD_FMT_U16:
  113 + bits16 = 1;
  114 + break;
  115 + }
  116 +
  117 + hdr[34] = bits16 ? 0x10 : 0x08;
  118 + hw->freq = 44100;
  119 + hw->nchannels = stereo ? 2 : 1;
  120 + hw->fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
  121 + hw->bufsize = 4096;
  122 + wav->pcm_buf = qemu_mallocz (hw->bufsize);
  123 + if (!wav->pcm_buf)
  124 + return -1;
  125 +
  126 + le_store (hdr + 22, hw->nchannels, 2);
  127 + le_store (hdr + 24, hw->freq, 4);
  128 + le_store (hdr + 28, hw->freq << (bits16 + stereo), 4);
  129 + le_store (hdr + 32, 1 << (bits16 + stereo), 2);
  130 +
  131 + wav->f = fopen (conf.wav_path, "wb");
  132 + if (!wav->f) {
  133 + dolog ("failed to open wave file `%s'\nReason: %s\n",
  134 + conf.wav_path, strerror (errno));
  135 + return -1;
  136 + }
  137 +
  138 + qemu_put_buffer (wav->f, hdr, sizeof (hdr));
  139 + return 0;
  140 +}
  141 +
  142 +static void wav_hw_fini (HWVoice *hw)
  143 +{
  144 + WAVVoice *wav = (WAVVoice *) hw;
  145 + int stereo = hw->nchannels == 2;
  146 + uint8_t rlen[4];
  147 + uint8_t dlen[4];
  148 + uint32_t rifflen = (wav->total_samples << stereo) + 36;
  149 + uint32_t datalen = wav->total_samples << stereo;
  150 +
  151 + if (!wav->f || !hw->active)
  152 + return;
  153 +
  154 + le_store (rlen, rifflen, 4);
  155 + le_store (dlen, datalen, 4);
  156 +
  157 + qemu_fseek (wav->f, 4, SEEK_SET);
  158 + qemu_put_buffer (wav->f, rlen, 4);
  159 +
  160 + qemu_fseek (wav->f, 32, SEEK_CUR);
  161 + qemu_put_buffer (wav->f, dlen, 4);
  162 +
  163 + fclose (wav->f);
  164 + wav->f = NULL;
  165 +}
  166 +
  167 +static int wav_hw_ctl (HWVoice *hw, int cmd, ...)
  168 +{
  169 + (void) hw;
  170 + (void) cmd;
  171 + return 0;
  172 +}
  173 +
  174 +static void *wav_audio_init (void)
  175 +{
  176 + return &conf;
  177 +}
  178 +
  179 +static void wav_audio_fini (void *opaque)
  180 +{
  181 + ldebug ("wav_fini");
  182 +}
  183 +
  184 +struct pcm_ops wav_pcm_ops = {
  185 + wav_hw_init,
  186 + wav_hw_fini,
  187 + wav_hw_run,
  188 + wav_hw_write,
  189 + wav_hw_ctl
  190 +};
  191 +
  192 +struct audio_output_driver wav_output_driver = {
  193 + "wav",
  194 + wav_audio_init,
  195 + wav_audio_fini,
  196 + &wav_pcm_ops,
  197 + 1,
  198 + 1,
  199 + sizeof (WAVVoice)
  200 +};
... ...
audio/wavaudio.h 0 → 100644
  1 +/*
  2 + * QEMU WAV audio output driver header
  3 + *
  4 + * Copyright (c) 2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#ifndef QEMU_WAVAUDIO_H
  25 +#define QEMU_WAVAUDIO_H
  26 +
  27 +typedef struct WAVVoice {
  28 + struct HWVoice hw;
  29 + QEMUFile *f;
  30 + int64_t old_ticks;
  31 + void *pcm_buf;
  32 + int total_samples;
  33 +} WAVVoice;
  34 +
  35 +extern struct pcm_ops wav_pcm_ops;
  36 +extern struct audio_output_driver wav_output_driver;
  37 +
  38 +#endif /* wavaudio.h */
... ...
hw/adlib.c 0 → 100644
  1 +/*
  2 + * QEMU Adlib emulation
  3 + *
  4 + * Copyright (c) 2004 Vassili Karpov (malc)
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +#define AUDIO_CAP "adlib"
  27 +#include "audio/audio.h"
  28 +
  29 +#ifdef USE_YMF262
  30 +#define HAS_YMF262 1
  31 +#include "ymf262.h"
  32 +void YMF262UpdateOneQEMU(int which, INT16 *dst, int length);
  33 +#define SHIFT 2
  34 +#else
  35 +#include "fmopl.h"
  36 +#define SHIFT 1
  37 +#endif
  38 +
  39 +#ifdef _WIN32
  40 +#include <windows.h>
  41 +#define small_delay() Sleep (1)
  42 +#else
  43 +#define small_delay() usleep (1)
  44 +#endif
  45 +
  46 +#define IO_READ_PROTO(name) \
  47 + uint32_t name (void *opaque, uint32_t nport)
  48 +#define IO_WRITE_PROTO(name) \
  49 + void name (void *opaque, uint32_t nport, uint32_t val)
  50 +
  51 +static struct {
  52 + int port;
  53 + int freq;
  54 +} conf = {0x220, 44100};
  55 +
  56 +typedef struct {
  57 + int enabled;
  58 + int active;
  59 + int cparam;
  60 + int64_t ticks;
  61 + int bufpos;
  62 + int16_t *mixbuf;
  63 + double interval;
  64 + QEMUTimer *ts, *opl_ts;
  65 + SWVoice *voice;
  66 + int left, pos, samples, bytes_per_second, old_free;
  67 + int refcount;
  68 +#ifndef USE_YMF262
  69 + FM_OPL *opl;
  70 +#endif
  71 +} AdlibState;
  72 +
  73 +static AdlibState adlib;
  74 +
  75 +static IO_WRITE_PROTO(adlib_write)
  76 +{
  77 + AdlibState *s = opaque;
  78 + int a = nport & 3;
  79 + int status;
  80 +
  81 + s->ticks = qemu_get_clock (vm_clock);
  82 + s->active = 1;
  83 + AUD_enable (s->voice, 1);
  84 +
  85 +#ifdef USE_YMF262
  86 + status = YMF262Write (0, a, val);
  87 +#else
  88 + status = OPLWrite (s->opl, a, val);
  89 +#endif
  90 +}
  91 +
  92 +static IO_READ_PROTO(adlib_read)
  93 +{
  94 + AdlibState *s = opaque;
  95 + uint8_t data;
  96 + int a = nport & 3;
  97 +
  98 +#ifdef USE_YMF262
  99 + (void) s;
  100 + data = YMF262Read (0, a);
  101 +#else
  102 + data = OPLRead (s->opl, a);
  103 +#endif
  104 + return data;
  105 +}
  106 +
  107 +static void OPL_timer (void *opaque)
  108 +{
  109 + AdlibState *s = opaque;
  110 +#ifdef USE_YMF262
  111 + YMF262TimerOver (s->cparam >> 1, s->cparam & 1);
  112 +#else
  113 + OPLTimerOver (s->opl, s->cparam);
  114 +#endif
  115 + qemu_mod_timer (s->opl_ts, qemu_get_clock (vm_clock) + s->interval);
  116 +}
  117 +
  118 +static void YMF262TimerHandler (int c, double interval_Sec)
  119 +{
  120 + AdlibState *s = &adlib;
  121 + if (interval_Sec == 0.0) {
  122 + qemu_del_timer (s->opl_ts);
  123 + return;
  124 + }
  125 + s->cparam = c;
  126 + s->interval = ticks_per_sec * interval_Sec;
  127 + qemu_mod_timer (s->opl_ts, qemu_get_clock (vm_clock) + s->interval);
  128 + small_delay ();
  129 +}
  130 +
  131 +static int write_audio (AdlibState *s, int samples)
  132 +{
  133 + int net = 0;
  134 + int ss = samples;
  135 + while (samples) {
  136 + int nbytes = samples << SHIFT;
  137 + int wbytes = AUD_write (s->voice,
  138 + s->mixbuf + (s->pos << (SHIFT - 1)),
  139 + nbytes);
  140 + int wsampl = wbytes >> SHIFT;
  141 + samples -= wsampl;
  142 + s->pos = (s->pos + wsampl) % s->samples;
  143 + net += wsampl;
  144 + if (!wbytes)
  145 + break;
  146 + }
  147 + if (net > ss) {
  148 + dolog ("WARNING: net > ss\n");
  149 + }
  150 + return net;
  151 +}
  152 +
  153 +static void timer (void *opaque)
  154 +{
  155 + AdlibState *s = opaque;
  156 + int elapsed, samples, net = 0;
  157 +
  158 + if (s->refcount)
  159 + dolog ("refcount=%d\n", s->refcount);
  160 +
  161 + s->refcount += 1;
  162 + if (!(s->active && s->enabled))
  163 + goto reset;
  164 +
  165 + AUD_run ();
  166 +
  167 + while (s->left) {
  168 + int written = write_audio (s, s->left);
  169 + net += written;
  170 + if (!written)
  171 + goto reset2;
  172 + s->left -= written;
  173 + }
  174 + s->pos = 0;
  175 +
  176 + elapsed = AUD_calc_elapsed (s->voice);
  177 + if (!elapsed)
  178 + goto reset2;
  179 +
  180 + /* elapsed = AUD_get_free (s->voice); */
  181 + samples = elapsed >> SHIFT;
  182 + if (!samples)
  183 + goto reset2;
  184 +
  185 + samples = audio_MIN (samples, s->samples - s->pos);
  186 + if (s->left)
  187 + dolog ("left=%d samples=%d elapsed=%d free=%d\n",
  188 + s->left, samples, elapsed, AUD_get_free (s->voice));
  189 +
  190 + if (!samples)
  191 + goto reset2;
  192 +
  193 +#ifdef USE_YMF262
  194 + YMF262UpdateOneQEMU (0, s->mixbuf + s->pos * 2, samples);
  195 +#else
  196 + YM3812UpdateOne (s->opl, s->mixbuf + s->pos, samples);
  197 +#endif
  198 +
  199 + while (samples) {
  200 + int written = write_audio (s, samples);
  201 + net += written;
  202 + if (!written)
  203 + break;
  204 + samples -= written;
  205 + }
  206 + if (!samples)
  207 + s->pos = 0;
  208 + s->left = samples;
  209 +
  210 +reset2:
  211 + AUD_adjust (s->voice, net << SHIFT);
  212 +reset:
  213 + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + ticks_per_sec / 1024);
  214 + s->refcount -= 1;
  215 +}
  216 +
  217 +static void Adlib_fini (AdlibState *s)
  218 +{
  219 +#ifdef USE_YMF262
  220 + YMF262Shutdown ();
  221 +#else
  222 + if (s->opl) {
  223 + OPLDestroy (s->opl);
  224 + s->opl = NULL;
  225 + }
  226 +#endif
  227 +
  228 + if (s->opl_ts)
  229 + qemu_free_timer (s->opl_ts);
  230 +
  231 + if (s->ts)
  232 + qemu_free_timer (s->ts);
  233 +
  234 +#define maybe_free(p) if (p) qemu_free (p)
  235 + maybe_free (s->mixbuf);
  236 +#undef maybe_free
  237 +
  238 + s->active = 0;
  239 + s->enabled = 0;
  240 +}
  241 +
  242 +void Adlib_init (void)
  243 +{
  244 + AdlibState *s = &adlib;
  245 +
  246 + memset (s, 0, sizeof (*s));
  247 +
  248 +#ifdef USE_YMF262
  249 + if (YMF262Init (1, 14318180, conf.freq)) {
  250 + dolog ("YMF262Init %d failed\n", conf.freq);
  251 + return;
  252 + }
  253 + else {
  254 + YMF262SetTimerHandler (0, YMF262TimerHandler, 0);
  255 + s->enabled = 1;
  256 + }
  257 +#else
  258 + s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, conf.freq);
  259 + if (!s->opl) {
  260 + dolog ("OPLCreate %d failed\n", conf.freq);
  261 + return;
  262 + }
  263 + else {
  264 + OPLSetTimerHandler (s->opl, YMF262TimerHandler, 0);
  265 + s->enabled = 1;
  266 + }
  267 +#endif
  268 +
  269 + s->opl_ts = qemu_new_timer (vm_clock, OPL_timer, s);
  270 + if (!s->opl_ts) {
  271 + dolog ("Can not get timer for adlib emulation\n");
  272 + Adlib_fini (s);
  273 + return;
  274 + }
  275 +
  276 + s->ts = qemu_new_timer (vm_clock, timer, s);
  277 + if (!s->opl_ts) {
  278 + dolog ("Can not get timer for adlib emulation\n");
  279 + Adlib_fini (s);
  280 + return;
  281 + }
  282 +
  283 + s->voice = AUD_open (s->voice, "adlib", conf.freq, SHIFT, AUD_FMT_S16);
  284 + if (!s->voice) {
  285 + Adlib_fini (s);
  286 + return;
  287 + }
  288 +
  289 + s->bytes_per_second = conf.freq << SHIFT;
  290 + s->samples = AUD_get_buffer_size (s->voice) >> SHIFT;
  291 + s->mixbuf = qemu_mallocz (s->samples << SHIFT);
  292 +
  293 + if (!s->mixbuf) {
  294 + dolog ("not enough memory for adlib mixing buffer (%d)\n",
  295 + s->samples << SHIFT);
  296 + Adlib_fini (s);
  297 + return;
  298 + }
  299 + register_ioport_read (0x388, 4, 1, adlib_read, s);
  300 + register_ioport_write (0x388, 4, 1, adlib_write, s);
  301 +
  302 + register_ioport_read (conf.port, 4, 1, adlib_read, s);
  303 + register_ioport_write (conf.port, 4, 1, adlib_write, s);
  304 +
  305 + register_ioport_read (conf.port + 8, 2, 1, adlib_read, s);
  306 + register_ioport_write (conf.port + 8, 2, 1, adlib_write, s);
  307 +
  308 + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
  309 +}
... ...
hw/dma.c
1 1 /*
2 2 * QEMU DMA emulation
3   - *
4   - * Copyright (c) 2003 Vassili Karpov (malc)
5   - *
  3 + *
  4 + * Copyright (c) 2003-2004 Vassili Karpov (malc)
  5 + *
6 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 7 * of this software and associated documentation files (the "Software"), to deal
8 8 * in the Software without restriction, including without limitation the rights
... ... @@ -23,9 +23,9 @@
23 23 */
24 24 #include "vl.h"
25 25  
26   -//#define DEBUG_DMA
  26 +/* #define DEBUG_DMA */
27 27  
28   -#define log(...) fprintf (stderr, "dma: " __VA_ARGS__)
  28 +#define dolog(...) fprintf (stderr, "dma: " __VA_ARGS__)
29 29 #ifdef DEBUG_DMA
30 30 #define lwarn(...) fprintf (stderr, "dma: " __VA_ARGS__)
31 31 #define linfo(...) fprintf (stderr, "dma: " __VA_ARGS__)
... ... @@ -86,7 +86,7 @@ static void write_page (void *opaque, uint32_t nport, uint32_t data)
86 86  
87 87 ichan = channels[nport & 7];
88 88 if (-1 == ichan) {
89   - log ("invalid channel %#x %#x\n", nport, data);
  89 + dolog ("invalid channel %#x %#x\n", nport, data);
90 90 return;
91 91 }
92 92 d->regs[ichan].page = data;
... ... @@ -99,7 +99,7 @@ static void write_pageh (void *opaque, uint32_t nport, uint32_t data)
99 99  
100 100 ichan = channels[nport & 7];
101 101 if (-1 == ichan) {
102   - log ("invalid channel %#x %#x\n", nport, data);
  102 + dolog ("invalid channel %#x %#x\n", nport, data);
103 103 return;
104 104 }
105 105 d->regs[ichan].pageh = data;
... ... @@ -112,7 +112,7 @@ static uint32_t read_page (void *opaque, uint32_t nport)
112 112  
113 113 ichan = channels[nport & 7];
114 114 if (-1 == ichan) {
115   - log ("invalid channel read %#x\n", nport);
  115 + dolog ("invalid channel read %#x\n", nport);
116 116 return 0;
117 117 }
118 118 return d->regs[ichan].page;
... ... @@ -125,7 +125,7 @@ static uint32_t read_pageh (void *opaque, uint32_t nport)
125 125  
126 126 ichan = channels[nport & 7];
127 127 if (-1 == ichan) {
128   - log ("invalid channel read %#x\n", nport);
  128 + dolog ("invalid channel read %#x\n", nport);
129 129 return 0;
130 130 }
131 131 return d->regs[ichan].pageh;
... ... @@ -136,7 +136,7 @@ static inline void init_chan (struct dma_cont *d, int ichan)
136 136 struct dma_regs *r;
137 137  
138 138 r = d->regs + ichan;
139   - r->now[ADDR] = r->base[0] << d->dshift;
  139 + r->now[ADDR] = r->base[ADDR] << d->dshift;
140 140 r->now[COUNT] = 0;
141 141 }
142 142  
... ... @@ -152,7 +152,7 @@ static inline int getff (struct dma_cont *d)
152 152 static uint32_t read_chan (void *opaque, uint32_t nport)
153 153 {
154 154 struct dma_cont *d = opaque;
155   - int ichan, nreg, iport, ff, val;
  155 + int ichan, nreg, iport, ff, val, dir;
156 156 struct dma_regs *r;
157 157  
158 158 iport = (nport >> d->dshift) & 0x0f;
... ... @@ -160,12 +160,14 @@ static uint32_t read_chan (void *opaque, uint32_t nport)
160 160 nreg = iport & 1;
161 161 r = d->regs + ichan;
162 162  
  163 + dir = ((r->mode >> 5) & 1) ? -1 : 1;
163 164 ff = getff (d);
164 165 if (nreg)
165 166 val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
166 167 else
167   - val = r->now[ADDR] + r->now[COUNT];
  168 + val = r->now[ADDR] + r->now[COUNT] * dir;
168 169  
  170 + ldebug ("read_chan %#x -> %d\n", iport, val);
169 171 return (val >> (d->dshift + (ff << 3))) & 0xff;
170 172 }
171 173  
... ... @@ -190,19 +192,19 @@ static void write_chan (void *opaque, uint32_t nport, uint32_t data)
190 192 static void write_cont (void *opaque, uint32_t nport, uint32_t data)
191 193 {
192 194 struct dma_cont *d = opaque;
193   - int iport, ichan;
  195 + int iport, ichan = 0;
194 196  
195 197 iport = (nport >> d->dshift) & 0x0f;
196 198 switch (iport) {
197   - case 8: /* command */
  199 + case 0x08: /* command */
198 200 if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
199   - log ("command %#x not supported\n", data);
  201 + dolog ("command %#x not supported\n", data);
200 202 return;
201 203 }
202 204 d->command = data;
203 205 break;
204 206  
205   - case 9:
  207 + case 0x09:
206 208 ichan = data & 3;
207 209 if (data & 4) {
208 210 d->status |= 1 << (ichan + 4);
... ... @@ -213,22 +215,19 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
213 215 d->status &= ~(1 << ichan);
214 216 break;
215 217  
216   - case 0xa: /* single mask */
  218 + case 0x0a: /* single mask */
217 219 if (data & 4)
218 220 d->mask |= 1 << (data & 3);
219 221 else
220 222 d->mask &= ~(1 << (data & 3));
221 223 break;
222 224  
223   - case 0xb: /* mode */
  225 + case 0x0b: /* mode */
224 226 {
225 227 ichan = data & 3;
226 228 #ifdef DEBUG_DMA
227   - int op;
228   - int ai;
229   - int dir;
230   - int opmode;
231   -
  229 + {
  230 + int op, ai, dir, opmode;
232 231 op = (data >> 2) & 3;
233 232 ai = (data >> 4) & 1;
234 233 dir = (data >> 5) & 1;
... ... @@ -236,39 +235,39 @@ static void write_cont (void *opaque, uint32_t nport, uint32_t data)
236 235  
237 236 linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n",
238 237 ichan, op, ai, dir, opmode);
  238 + }
239 239 #endif
240   -
241 240 d->regs[ichan].mode = data;
242 241 break;
243 242 }
244 243  
245   - case 0xc: /* clear flip flop */
  244 + case 0x0c: /* clear flip flop */
246 245 d->flip_flop = 0;
247 246 break;
248 247  
249   - case 0xd: /* reset */
  248 + case 0x0d: /* reset */
250 249 d->flip_flop = 0;
251 250 d->mask = ~0;
252 251 d->status = 0;
253 252 d->command = 0;
254 253 break;
255 254  
256   - case 0xe: /* clear mask for all channels */
  255 + case 0x0e: /* clear mask for all channels */
257 256 d->mask = 0;
258 257 break;
259 258  
260   - case 0xf: /* write mask for all channels */
  259 + case 0x0f: /* write mask for all channels */
261 260 d->mask = data;
262 261 break;
263 262  
264 263 default:
265   - log ("dma: unknown iport %#x\n", iport);
  264 + dolog ("unknown iport %#x\n", iport);
266 265 break;
267 266 }
268 267  
269 268 #ifdef DEBUG_DMA
270 269 if (0xc != iport) {
271   - linfo ("nport %#06x, ichan % 2d, val %#06x\n",
  270 + linfo ("write_cont: nport %#06x, ichan % 2d, val %#06x\n",
272 271 nport, ichan, data);
273 272 }
274 273 #endif
... ... @@ -278,20 +277,22 @@ static uint32_t read_cont (void *opaque, uint32_t nport)
278 277 {
279 278 struct dma_cont *d = opaque;
280 279 int iport, val;
281   -
  280 +
282 281 iport = (nport >> d->dshift) & 0x0f;
283 282 switch (iport) {
284   - case 0x08: /* status */
  283 + case 0x08: /* status */
285 284 val = d->status;
286 285 d->status &= 0xf0;
287 286 break;
288   - case 0x0f: /* mask */
  287 + case 0x0f: /* mask */
289 288 val = d->mask;
290 289 break;
291 290 default:
292 291 val = 0;
293 292 break;
294 293 }
  294 +
  295 + ldebug ("read_cont: nport %#06x, iport %#04x val %#x\n", nport, iport, val);
295 296 return val;
296 297 }
297 298  
... ... @@ -322,23 +323,27 @@ void DMA_release_DREQ (int nchan)
322 323  
323 324 static void channel_run (int ncont, int ichan)
324 325 {
325   - struct dma_regs *r;
326 326 int n;
327   - target_ulong addr;
328   -/* int ai, dir; */
  327 + struct dma_regs *r = &dma_controllers[ncont].regs[ichan];
  328 +#ifdef DEBUG_DMA
  329 + int dir, opmode;
329 330  
330   - r = dma_controllers[ncont].regs + ichan;
331   -/* ai = r->mode & 16; */
332   -/* dir = r->mode & 32 ? -1 : 1; */
  331 + dir = (r->mode >> 5) & 1;
  332 + opmode = (r->mode >> 6) & 3;
333 333  
334   - /* NOTE: pageh is only used by PPC PREP */
335   - addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
336   - n = r->transfer_handler (r->opaque, addr,
337   - (r->base[COUNT] << ncont) + (1 << ncont));
338   - r->now[COUNT] = n;
  334 + if (dir) {
  335 + dolog ("DMA in address decrement mode\n");
  336 + }
  337 + if (opmode != 1) {
  338 + dolog ("DMA not in single mode select %#x\n", opmode);
  339 + }
  340 +#endif
339 341  
340   - ldebug ("dma_pos %d size %d\n",
341   - n, (r->base[1] << ncont) + (1 << ncont));
  342 + r = dma_controllers[ncont].regs + ichan;
  343 + n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
  344 + r->now[COUNT], (r->base[COUNT] + 1) << ncont);
  345 + r->now[COUNT] = n;
  346 + ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
342 347 }
343 348  
344 349 void DMA_run (void)
... ... @@ -361,7 +366,7 @@ void DMA_run (void)
361 366 }
362 367  
363 368 void DMA_register_channel (int nchan,
364   - DMA_transfer_handler transfer_handler,
  369 + DMA_transfer_handler transfer_handler,
365 370 void *opaque)
366 371 {
367 372 struct dma_regs *r;
... ... @@ -375,6 +380,50 @@ void DMA_register_channel (int nchan,
375 380 r->opaque = opaque;
376 381 }
377 382  
  383 +int DMA_read_memory (int nchan, void *buf, int pos, int len)
  384 +{
  385 + struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3];
  386 + target_ulong addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
  387 +
  388 + if (r->mode & 0x20) {
  389 + int i;
  390 + uint8_t *p = buf;
  391 +
  392 + cpu_physical_memory_read (addr - pos - len, buf, len);
  393 + /* What about 16bit transfers? */
  394 + for (i = 0; i < len >> 1; i++) {
  395 + uint8_t b = p[len - i - 1];
  396 + p[i] = b;
  397 + }
  398 + }
  399 + else
  400 + cpu_physical_memory_read (addr + pos, buf, len);
  401 +
  402 + return len;
  403 +}
  404 +
  405 +int DMA_write_memory (int nchan, void *buf, int pos, int len)
  406 +{
  407 + struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3];
  408 + target_ulong addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
  409 +
  410 + if (r->mode & 0x20) {
  411 + int i;
  412 + uint8_t *p = buf;
  413 +
  414 + cpu_physical_memory_write (addr - pos - len, buf, len);
  415 + /* What about 16bit transfers? */
  416 + for (i = 0; i < len; i++) {
  417 + uint8_t b = p[len - i - 1];
  418 + p[i] = b;
  419 + }
  420 + }
  421 + else
  422 + cpu_physical_memory_write (addr + pos, buf, len);
  423 +
  424 + return len;
  425 +}
  426 +
378 427 /* request the emulator to transfer a new DMA memory block ASAP */
379 428 void DMA_schedule(int nchan)
380 429 {
... ... @@ -388,7 +437,7 @@ static void dma_reset(void *opaque)
388 437 }
389 438  
390 439 /* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
391   -static void dma_init2(struct dma_cont *d, int base, int dshift,
  440 +static void dma_init2(struct dma_cont *d, int base, int dshift,
392 441 int page_base, int pageh_base)
393 442 {
394 443 const static int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
... ... @@ -400,31 +449,87 @@ static void dma_init2(struct dma_cont *d, int base, int dshift,
400 449 register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
401 450 }
402 451 for (i = 0; i < LENOFA (page_port_list); i++) {
403   - register_ioport_write (page_base + page_port_list[i], 1, 1,
  452 + register_ioport_write (page_base + page_port_list[i], 1, 1,
404 453 write_page, d);
405   - register_ioport_read (page_base + page_port_list[i], 1, 1,
  454 + register_ioport_read (page_base + page_port_list[i], 1, 1,
406 455 read_page, d);
407 456 if (pageh_base >= 0) {
408   - register_ioport_write (pageh_base + page_port_list[i], 1, 1,
  457 + register_ioport_write (pageh_base + page_port_list[i], 1, 1,
409 458 write_pageh, d);
410   - register_ioport_read (pageh_base + page_port_list[i], 1, 1,
  459 + register_ioport_read (pageh_base + page_port_list[i], 1, 1,
411 460 read_pageh, d);
412 461 }
413 462 }
414 463 for (i = 0; i < 8; i++) {
415   - register_ioport_write (base + ((i + 8) << dshift), 1, 1,
  464 + register_ioport_write (base + ((i + 8) << dshift), 1, 1,
416 465 write_cont, d);
417   - register_ioport_read (base + ((i + 8) << dshift), 1, 1,
  466 + register_ioport_read (base + ((i + 8) << dshift), 1, 1,
418 467 read_cont, d);
419 468 }
420 469 qemu_register_reset(dma_reset, d);
421 470 dma_reset(d);
422 471 }
423 472  
  473 +static void dma_save (QEMUFile *f, void *opaque)
  474 +{
  475 + struct dma_cont *d = opaque;
  476 + int i;
  477 +
  478 + /* qemu_put_8s (f, &d->status); */
  479 + qemu_put_8s (f, &d->command);
  480 + qemu_put_8s (f, &d->mask);
  481 + qemu_put_8s (f, &d->flip_flop);
  482 + qemu_put_be32s (f, &d->dshift);
  483 +
  484 + for (i = 0; i < 4; ++i) {
  485 + struct dma_regs *r = &d->regs[i];
  486 + qemu_put_be32s (f, &r->now[0]);
  487 + qemu_put_be32s (f, &r->now[1]);
  488 + qemu_put_be16s (f, &r->base[0]);
  489 + qemu_put_be16s (f, &r->base[1]);
  490 + qemu_put_8s (f, &r->mode);
  491 + qemu_put_8s (f, &r->page);
  492 + qemu_put_8s (f, &r->pageh);
  493 + qemu_put_8s (f, &r->dack);
  494 + qemu_put_8s (f, &r->eop);
  495 + }
  496 +}
  497 +
  498 +static int dma_load (QEMUFile *f, void *opaque, int version_id)
  499 +{
  500 + struct dma_cont *d = opaque;
  501 + int i;
  502 +
  503 + if (version_id != 1)
  504 + return -EINVAL;
  505 +
  506 + /* qemu_get_8s (f, &d->status); */
  507 + qemu_get_8s (f, &d->command);
  508 + qemu_get_8s (f, &d->mask);
  509 + qemu_get_8s (f, &d->flip_flop);
  510 + qemu_get_be32s (f, &d->dshift);
  511 +
  512 + for (i = 0; i < 4; ++i) {
  513 + struct dma_regs *r = &d->regs[i];
  514 + qemu_get_be32s (f, &r->now[0]);
  515 + qemu_get_be32s (f, &r->now[1]);
  516 + qemu_get_be16s (f, &r->base[0]);
  517 + qemu_get_be16s (f, &r->base[1]);
  518 + qemu_get_8s (f, &r->mode);
  519 + qemu_get_8s (f, &r->page);
  520 + qemu_get_8s (f, &r->pageh);
  521 + qemu_get_8s (f, &r->dack);
  522 + qemu_get_8s (f, &r->eop);
  523 + }
  524 + return 0;
  525 +}
  526 +
424 527 void DMA_init (int high_page_enable)
425 528 {
426   - dma_init2(&dma_controllers[0], 0x00, 0, 0x80,
  529 + dma_init2(&dma_controllers[0], 0x00, 0, 0x80,
427 530 high_page_enable ? 0x480 : -1);
428 531 dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
429 532 high_page_enable ? 0x488 : -1);
  533 + register_savevm ("dma", 0, 1, dma_save, dma_load, &dma_controllers[0]);
  534 + register_savevm ("dma", 1, 1, dma_save, dma_load, &dma_controllers[1]);
430 535 }
... ...
hw/fdc.c
... ... @@ -313,7 +313,8 @@ static void fd_reset (fdrive_t *drv)
313 313  
314 314 static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq);
315 315 static void fdctrl_reset_fifo (fdctrl_t *fdctrl);
316   -static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size);
  316 +static int fdctrl_transfer_handler (void *opaque, int nchan,
  317 + int dma_pos, int dma_len);
317 318 static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status);
318 319 static void fdctrl_result_timer(void *opaque);
319 320  
... ... @@ -908,7 +909,8 @@ static void fdctrl_start_transfer_del (fdctrl_t *fdctrl, int direction)
908 909 }
909 910  
910 911 /* handlers for DMA transfers */
911   -static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
  912 +static int fdctrl_transfer_handler (void *opaque, int nchan,
  913 + int dma_pos, int dma_len)
912 914 {
913 915 fdctrl_t *fdctrl;
914 916 fdrive_t *cur_drv;
... ... @@ -924,8 +926,8 @@ static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
924 926 if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
925 927 fdctrl->data_dir == FD_DIR_SCANH)
926 928 status2 = 0x04;
927   - if (size > fdctrl->data_len)
928   - size = fdctrl->data_len;
  929 + if (dma_len > fdctrl->data_len)
  930 + dma_len = fdctrl->data_len;
929 931 if (cur_drv->bs == NULL) {
930 932 if (fdctrl->data_dir == FD_DIR_WRITE)
931 933 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
... ... @@ -935,8 +937,8 @@ static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
935 937 goto transfer_error;
936 938 }
937 939 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
938   - for (start_pos = fdctrl->data_pos; fdctrl->data_pos < size;) {
939   - len = size - fdctrl->data_pos;
  940 + for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) {
  941 + len = dma_len - fdctrl->data_pos;
940 942 if (len + rel_pos > FD_SECTOR_LEN)
941 943 len = FD_SECTOR_LEN - rel_pos;
942 944 FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x %02x "
... ... @@ -958,13 +960,17 @@ static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
958 960 switch (fdctrl->data_dir) {
959 961 case FD_DIR_READ:
960 962 /* READ commands */
961   - cpu_physical_memory_write(addr + fdctrl->data_pos,
962   - fdctrl->fifo + rel_pos, len);
  963 + DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
  964 + fdctrl->data_pos, len);
  965 +/* cpu_physical_memory_write(addr + fdctrl->data_pos, */
  966 +/* fdctrl->fifo + rel_pos, len); */
963 967 break;
964 968 case FD_DIR_WRITE:
965 969 /* WRITE commands */
966   - cpu_physical_memory_read(addr + fdctrl->data_pos,
967   - fdctrl->fifo + rel_pos, len);
  970 + DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
  971 + fdctrl->data_pos, len);
  972 +/* cpu_physical_memory_read(addr + fdctrl->data_pos, */
  973 +/* fdctrl->fifo + rel_pos, len); */
968 974 if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
969 975 fdctrl->fifo, 1) < 0) {
970 976 FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv));
... ... @@ -977,8 +983,9 @@ static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
977 983 {
978 984 uint8_t tmpbuf[FD_SECTOR_LEN];
979 985 int ret;
980   - cpu_physical_memory_read(addr + fdctrl->data_pos,
981   - tmpbuf, len);
  986 + DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
  987 +/* cpu_physical_memory_read(addr + fdctrl->data_pos, */
  988 +/* tmpbuf, len); */
982 989 ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
983 990 if (ret == 0) {
984 991 status2 = 0x08;
... ...
hw/fmopl.c 0 → 100644
  1 +/*
  2 +**
  3 +** File: fmopl.c -- software implementation of FM sound generator
  4 +**
  5 +** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
  6 +**
  7 +** Version 0.37a
  8 +**
  9 +*/
  10 +
  11 +/*
  12 + preliminary :
  13 + Problem :
  14 + note:
  15 +*/
  16 +
  17 +/* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL.
  18 + *
  19 + * This library is free software; you can redistribute it and/or
  20 + * modify it under the terms of the GNU Lesser General Public
  21 + * License as published by the Free Software Foundation; either
  22 + * version 2.1 of the License, or (at your option) any later version.
  23 + *
  24 + * This library is distributed in the hope that it will be useful,
  25 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  27 + * Lesser General Public License for more details.
  28 + *
  29 + * You should have received a copy of the GNU Lesser General Public
  30 + * License along with this library; if not, write to the Free Software
  31 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  32 + */
  33 +
  34 +#define INLINE __inline
  35 +#define HAS_YM3812 1
  36 +
  37 +#include <stdio.h>
  38 +#include <stdlib.h>
  39 +#include <string.h>
  40 +#include <stdarg.h>
  41 +#include <math.h>
  42 +//#include "driver.h" /* use M.A.M.E. */
  43 +#include "fmopl.h"
  44 +
  45 +#ifndef PI
  46 +#define PI 3.14159265358979323846
  47 +#endif
  48 +
  49 +/* -------------------- for debug --------------------- */
  50 +/* #define OPL_OUTPUT_LOG */
  51 +#ifdef OPL_OUTPUT_LOG
  52 +static FILE *opl_dbg_fp = NULL;
  53 +static FM_OPL *opl_dbg_opl[16];
  54 +static int opl_dbg_maxchip,opl_dbg_chip;
  55 +#endif
  56 +
  57 +/* -------------------- preliminary define section --------------------- */
  58 +/* attack/decay rate time rate */
  59 +#define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */
  60 +#define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */
  61 +
  62 +#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */
  63 +
  64 +#define FREQ_BITS 24 /* frequency turn */
  65 +
  66 +/* counter bits = 20 , octerve 7 */
  67 +#define FREQ_RATE (1<<(FREQ_BITS-20))
  68 +#define TL_BITS (FREQ_BITS+2)
  69 +
  70 +/* final output shift , limit minimum and maximum */
  71 +#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */
  72 +#define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
  73 +#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
  74 +
  75 +/* -------------------- quality selection --------------------- */
  76 +
  77 +/* sinwave entries */
  78 +/* used static memory = SIN_ENT * 4 (byte) */
  79 +#define SIN_ENT 2048
  80 +
  81 +/* output level entries (envelope,sinwave) */
  82 +/* envelope counter lower bits */
  83 +#define ENV_BITS 16
  84 +/* envelope output entries */
  85 +#define EG_ENT 4096
  86 +/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
  87 +/* used static memory = EG_ENT*4 (byte) */
  88 +
  89 +#define EG_OFF ((2*EG_ENT)<<ENV_BITS) /* OFF */
  90 +#define EG_DED EG_OFF
  91 +#define EG_DST (EG_ENT<<ENV_BITS) /* DECAY START */
  92 +#define EG_AED EG_DST
  93 +#define EG_AST 0 /* ATTACK START */
  94 +
  95 +#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step */
  96 +
  97 +/* LFO table entries */
  98 +#define VIB_ENT 512
  99 +#define VIB_SHIFT (32-9)
  100 +#define AMS_ENT 512
  101 +#define AMS_SHIFT (32-9)
  102 +
  103 +#define VIB_RATE 256
  104 +
  105 +/* -------------------- local defines , macros --------------------- */
  106 +
  107 +/* register number to channel number , slot offset */
  108 +#define SLOT1 0
  109 +#define SLOT2 1
  110 +
  111 +/* envelope phase */
  112 +#define ENV_MOD_RR 0x00
  113 +#define ENV_MOD_DR 0x01
  114 +#define ENV_MOD_AR 0x02
  115 +
  116 +/* -------------------- tables --------------------- */
  117 +static const int slot_array[32]=
  118 +{
  119 + 0, 2, 4, 1, 3, 5,-1,-1,
  120 + 6, 8,10, 7, 9,11,-1,-1,
  121 + 12,14,16,13,15,17,-1,-1,
  122 + -1,-1,-1,-1,-1,-1,-1,-1
  123 +};
  124 +
  125 +/* key scale level */
  126 +/* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
  127 +#define DV (EG_STEP/2)
  128 +static const UINT32 KSL_TABLE[8*16]=
  129 +{
  130 + /* OCT 0 */
  131 + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  132 + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  133 + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  134 + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  135 + /* OCT 1 */
  136 + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  137 + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  138 + 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
  139 + 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
  140 + /* OCT 2 */
  141 + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  142 + 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
  143 + 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
  144 + 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
  145 + /* OCT 3 */
  146 + 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
  147 + 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
  148 + 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
  149 + 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
  150 + /* OCT 4 */
  151 + 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
  152 + 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
  153 + 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
  154 + 10.875/DV,11.250/DV,11.625/DV,12.000/DV,
  155 + /* OCT 5 */
  156 + 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
  157 + 9.000/DV,10.125/DV,10.875/DV,11.625/DV,
  158 + 12.000/DV,12.750/DV,13.125/DV,13.500/DV,
  159 + 13.875/DV,14.250/DV,14.625/DV,15.000/DV,
  160 + /* OCT 6 */
  161 + 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
  162 + 12.000/DV,13.125/DV,13.875/DV,14.625/DV,
  163 + 15.000/DV,15.750/DV,16.125/DV,16.500/DV,
  164 + 16.875/DV,17.250/DV,17.625/DV,18.000/DV,
  165 + /* OCT 7 */
  166 + 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
  167 + 15.000/DV,16.125/DV,16.875/DV,17.625/DV,
  168 + 18.000/DV,18.750/DV,19.125/DV,19.500/DV,
  169 + 19.875/DV,20.250/DV,20.625/DV,21.000/DV
  170 +};
  171 +#undef DV
  172 +
  173 +/* sustain lebel table (3db per step) */
  174 +/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
  175 +#define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
  176 +static const INT32 SL_TABLE[16]={
  177 + SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
  178 + SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
  179 +};
  180 +#undef SC
  181 +
  182 +#define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
  183 +/* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
  184 +/* TL_TABLE[ 0 to TL_MAX ] : plus section */
  185 +/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
  186 +static INT32 *TL_TABLE;
  187 +
  188 +/* pointers to TL_TABLE with sinwave output offset */
  189 +static INT32 **SIN_TABLE;
  190 +
  191 +/* LFO table */
  192 +static INT32 *AMS_TABLE;
  193 +static INT32 *VIB_TABLE;
  194 +
  195 +/* envelope output curve table */
  196 +/* attack + decay + OFF */
  197 +static INT32 ENV_CURVE[2*EG_ENT+1];
  198 +
  199 +/* multiple table */
  200 +#define ML 2
  201 +static const UINT32 MUL_TABLE[16]= {
  202 +/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
  203 + 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
  204 + 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 +};
  206 +#undef ML
  207 +
  208 +/* dummy attack / decay rate ( when rate == 0 ) */
  209 +static INT32 RATE_0[16]=
  210 +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  211 +
  212 +/* -------------------- static state --------------------- */
  213 +
  214 +/* lock level of common table */
  215 +static int num_lock = 0;
  216 +
  217 +/* work table */
  218 +static void *cur_chip = NULL; /* current chip point */
  219 +/* currenct chip state */
  220 +/* static OPLSAMPLE *bufL,*bufR; */
  221 +static OPL_CH *S_CH;
  222 +static OPL_CH *E_CH;
  223 +OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
  224 +
  225 +static INT32 outd[1];
  226 +static INT32 ams;
  227 +static INT32 vib;
  228 +INT32 *ams_table;
  229 +INT32 *vib_table;
  230 +static INT32 amsIncr;
  231 +static INT32 vibIncr;
  232 +static INT32 feedback2; /* connect for SLOT 2 */
  233 +
  234 +/* log output level */
  235 +#define LOG_ERR 3 /* ERROR */
  236 +#define LOG_WAR 2 /* WARNING */
  237 +#define LOG_INF 1 /* INFORMATION */
  238 +
  239 +//#define LOG_LEVEL LOG_INF
  240 +#define LOG_LEVEL LOG_ERR
  241 +
  242 +//#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x
  243 +#define LOG(n,x)
  244 +
  245 +/* --------------------- subroutines --------------------- */
  246 +
  247 +INLINE int Limit( int val, int max, int min ) {
  248 + if ( val > max )
  249 + val = max;
  250 + else if ( val < min )
  251 + val = min;
  252 +
  253 + return val;
  254 +}
  255 +
  256 +/* status set and IRQ handling */
  257 +INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
  258 +{
  259 + /* set status flag */
  260 + OPL->status |= flag;
  261 + if(!(OPL->status & 0x80))
  262 + {
  263 + if(OPL->status & OPL->statusmask)
  264 + { /* IRQ on */
  265 + OPL->status |= 0x80;
  266 + /* callback user interrupt handler (IRQ is OFF to ON) */
  267 + if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
  268 + }
  269 + }
  270 +}
  271 +
  272 +/* status reset and IRQ handling */
  273 +INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
  274 +{
  275 + /* reset status flag */
  276 + OPL->status &=~flag;
  277 + if((OPL->status & 0x80))
  278 + {
  279 + if (!(OPL->status & OPL->statusmask) )
  280 + {
  281 + OPL->status &= 0x7f;
  282 + /* callback user interrupt handler (IRQ is ON to OFF) */
  283 + if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
  284 + }
  285 + }
  286 +}
  287 +
  288 +/* IRQ mask set */
  289 +INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
  290 +{
  291 + OPL->statusmask = flag;
  292 + /* IRQ handling check */
  293 + OPL_STATUS_SET(OPL,0);
  294 + OPL_STATUS_RESET(OPL,0);
  295 +}
  296 +
  297 +/* ----- key on ----- */
  298 +INLINE void OPL_KEYON(OPL_SLOT *SLOT)
  299 +{
  300 + /* sin wave restart */
  301 + SLOT->Cnt = 0;
  302 + /* set attack */
  303 + SLOT->evm = ENV_MOD_AR;
  304 + SLOT->evs = SLOT->evsa;
  305 + SLOT->evc = EG_AST;
  306 + SLOT->eve = EG_AED;
  307 +}
  308 +/* ----- key off ----- */
  309 +INLINE void OPL_KEYOFF(OPL_SLOT *SLOT)
  310 +{
  311 + if( SLOT->evm > ENV_MOD_RR)
  312 + {
  313 + /* set envelope counter from envleope output */
  314 + SLOT->evm = ENV_MOD_RR;
  315 + if( !(SLOT->evc&EG_DST) )
  316 + //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
  317 + SLOT->evc = EG_DST;
  318 + SLOT->eve = EG_DED;
  319 + SLOT->evs = SLOT->evsr;
  320 + }
  321 +}
  322 +
  323 +/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
  324 +/* return : envelope output */
  325 +INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
  326 +{
  327 + /* calcrate envelope generator */
  328 + if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
  329 + {
  330 + switch( SLOT->evm ){
  331 + case ENV_MOD_AR: /* ATTACK -> DECAY1 */
  332 + /* next DR */
  333 + SLOT->evm = ENV_MOD_DR;
  334 + SLOT->evc = EG_DST;
  335 + SLOT->eve = SLOT->SL;
  336 + SLOT->evs = SLOT->evsd;
  337 + break;
  338 + case ENV_MOD_DR: /* DECAY -> SL or RR */
  339 + SLOT->evc = SLOT->SL;
  340 + SLOT->eve = EG_DED;
  341 + if(SLOT->eg_typ)
  342 + {
  343 + SLOT->evs = 0;
  344 + }
  345 + else
  346 + {
  347 + SLOT->evm = ENV_MOD_RR;
  348 + SLOT->evs = SLOT->evsr;
  349 + }
  350 + break;
  351 + case ENV_MOD_RR: /* RR -> OFF */
  352 + SLOT->evc = EG_OFF;
  353 + SLOT->eve = EG_OFF+1;
  354 + SLOT->evs = 0;
  355 + break;
  356 + }
  357 + }
  358 + /* calcrate envelope */
  359 + return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);
  360 +}
  361 +
  362 +/* set algorythm connection */
  363 +static void set_algorythm( OPL_CH *CH)
  364 +{
  365 + INT32 *carrier = &outd[0];
  366 + CH->connect1 = CH->CON ? carrier : &feedback2;
  367 + CH->connect2 = carrier;
  368 +}
  369 +
  370 +/* ---------- frequency counter for operater update ---------- */
  371 +INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
  372 +{
  373 + int ksr;
  374 +
  375 + /* frequency step counter */
  376 + SLOT->Incr = CH->fc * SLOT->mul;
  377 + ksr = CH->kcode >> SLOT->KSR;
  378 +
  379 + if( SLOT->ksr != ksr )
  380 + {
  381 + SLOT->ksr = ksr;
  382 + /* attack , decay rate recalcration */
  383 + SLOT->evsa = SLOT->AR[ksr];
  384 + SLOT->evsd = SLOT->DR[ksr];
  385 + SLOT->evsr = SLOT->RR[ksr];
  386 + }
  387 + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
  388 +}
  389 +
  390 +/* set multi,am,vib,EG-TYP,KSR,mul */
  391 +INLINE void set_mul(FM_OPL *OPL,int slot,int v)
  392 +{
  393 + OPL_CH *CH = &OPL->P_CH[slot/2];
  394 + OPL_SLOT *SLOT = &CH->SLOT[slot&1];
  395 +
  396 + SLOT->mul = MUL_TABLE[v&0x0f];
  397 + SLOT->KSR = (v&0x10) ? 0 : 2;
  398 + SLOT->eg_typ = (v&0x20)>>5;
  399 + SLOT->vib = (v&0x40);
  400 + SLOT->ams = (v&0x80);
  401 + CALC_FCSLOT(CH,SLOT);
  402 +}
  403 +
  404 +/* set ksl & tl */
  405 +INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
  406 +{
  407 + OPL_CH *CH = &OPL->P_CH[slot/2];
  408 + OPL_SLOT *SLOT = &CH->SLOT[slot&1];
  409 + int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */
  410 +
  411 + SLOT->ksl = ksl ? 3-ksl : 31;
  412 + SLOT->TL = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */
  413 +
  414 + if( !(OPL->mode&0x80) )
  415 + { /* not CSM latch total level */
  416 + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
  417 + }
  418 +}
  419 +
  420 +/* set attack rate & decay rate */
  421 +INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
  422 +{
  423 + OPL_CH *CH = &OPL->P_CH[slot/2];
  424 + OPL_SLOT *SLOT = &CH->SLOT[slot&1];
  425 + int ar = v>>4;
  426 + int dr = v&0x0f;
  427 +
  428 + SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0;
  429 + SLOT->evsa = SLOT->AR[SLOT->ksr];
  430 + if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;
  431 +
  432 + SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
  433 + SLOT->evsd = SLOT->DR[SLOT->ksr];
  434 + if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;
  435 +}
  436 +
  437 +/* set sustain level & release rate */
  438 +INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)
  439 +{
  440 + OPL_CH *CH = &OPL->P_CH[slot/2];
  441 + OPL_SLOT *SLOT = &CH->SLOT[slot&1];
  442 + int sl = v>>4;
  443 + int rr = v & 0x0f;
  444 +
  445 + SLOT->SL = SL_TABLE[sl];
  446 + if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL;
  447 + SLOT->RR = &OPL->DR_TABLE[rr<<2];
  448 + SLOT->evsr = SLOT->RR[SLOT->ksr];
  449 + if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;
  450 +}
  451 +
  452 +/* operator output calcrator */
  453 +#define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
  454 +/* ---------- calcrate one of channel ---------- */
  455 +INLINE void OPL_CALC_CH( OPL_CH *CH )
  456 +{
  457 + UINT32 env_out;
  458 + OPL_SLOT *SLOT;
  459 +
  460 + feedback2 = 0;
  461 + /* SLOT 1 */
  462 + SLOT = &CH->SLOT[SLOT1];
  463 + env_out=OPL_CALC_SLOT(SLOT);
  464 + if( env_out < EG_ENT-1 )
  465 + {
  466 + /* PG */
  467 + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
  468 + else SLOT->Cnt += SLOT->Incr;
  469 + /* connectoion */
  470 + if(CH->FB)
  471 + {
  472 + int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;
  473 + CH->op1_out[1] = CH->op1_out[0];
  474 + *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
  475 + }
  476 + else
  477 + {
  478 + *CH->connect1 += OP_OUT(SLOT,env_out,0);
  479 + }
  480 + }else
  481 + {
  482 + CH->op1_out[1] = CH->op1_out[0];
  483 + CH->op1_out[0] = 0;
  484 + }
  485 + /* SLOT 2 */
  486 + SLOT = &CH->SLOT[SLOT2];
  487 + env_out=OPL_CALC_SLOT(SLOT);
  488 + if( env_out < EG_ENT-1 )
  489 + {
  490 + /* PG */
  491 + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
  492 + else SLOT->Cnt += SLOT->Incr;
  493 + /* connectoion */
  494 + outd[0] += OP_OUT(SLOT,env_out, feedback2);
  495 + }
  496 +}
  497 +
  498 +/* ---------- calcrate rythm block ---------- */
  499 +#define WHITE_NOISE_db 6.0
  500 +INLINE void OPL_CALC_RH( OPL_CH *CH )
  501 +{
  502 + UINT32 env_tam,env_sd,env_top,env_hh;
  503 + int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP);
  504 + INT32 tone8;
  505 +
  506 + OPL_SLOT *SLOT;
  507 + int env_out;
  508 +
  509 + /* BD : same as FM serial mode and output level is large */
  510 + feedback2 = 0;
  511 + /* SLOT 1 */
  512 + SLOT = &CH[6].SLOT[SLOT1];
  513 + env_out=OPL_CALC_SLOT(SLOT);
  514 + if( env_out < EG_ENT-1 )
  515 + {
  516 + /* PG */
  517 + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
  518 + else SLOT->Cnt += SLOT->Incr;
  519 + /* connectoion */
  520 + if(CH[6].FB)
  521 + {
  522 + int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB;
  523 + CH[6].op1_out[1] = CH[6].op1_out[0];
  524 + feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
  525 + }
  526 + else
  527 + {
  528 + feedback2 = OP_OUT(SLOT,env_out,0);
  529 + }
  530 + }else
  531 + {
  532 + feedback2 = 0;
  533 + CH[6].op1_out[1] = CH[6].op1_out[0];
  534 + CH[6].op1_out[0] = 0;
  535 + }
  536 + /* SLOT 2 */
  537 + SLOT = &CH[6].SLOT[SLOT2];
  538 + env_out=OPL_CALC_SLOT(SLOT);
  539 + if( env_out < EG_ENT-1 )
  540 + {
  541 + /* PG */
  542 + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
  543 + else SLOT->Cnt += SLOT->Incr;
  544 + /* connectoion */
  545 + outd[0] += OP_OUT(SLOT,env_out, feedback2)*2;
  546 + }
  547 +
  548 + // SD (17) = mul14[fnum7] + white noise
  549 + // TAM (15) = mul15[fnum8]
  550 + // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
  551 + // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
  552 + env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise;
  553 + env_tam=OPL_CALC_SLOT(SLOT8_1);
  554 + env_top=OPL_CALC_SLOT(SLOT8_2);
  555 + env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise;
  556 +
  557 + /* PG */
  558 + if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE);
  559 + else SLOT7_1->Cnt += 2*SLOT7_1->Incr;
  560 + if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE);
  561 + else SLOT7_2->Cnt += (CH[7].fc*8);
  562 + if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE);
  563 + else SLOT8_1->Cnt += SLOT8_1->Incr;
  564 + if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE);
  565 + else SLOT8_2->Cnt += (CH[8].fc*48);
  566 +
  567 + tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
  568 +
  569 + /* SD */
  570 + if( env_sd < EG_ENT-1 )
  571 + outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8;
  572 + /* TAM */
  573 + if( env_tam < EG_ENT-1 )
  574 + outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2;
  575 + /* TOP-CY */
  576 + if( env_top < EG_ENT-1 )
  577 + outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2;
  578 + /* HH */
  579 + if( env_hh < EG_ENT-1 )
  580 + outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2;
  581 +}
  582 +
  583 +/* ----------- initialize time tabls ----------- */
  584 +static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
  585 +{
  586 + int i;
  587 + double rate;
  588 +
  589 + /* make attack rate & decay rate tables */
  590 + for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
  591 + for (i = 4;i <= 60;i++){
  592 + rate = OPL->freqbase; /* frequency rate */
  593 + if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
  594 + rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */
  595 + rate *= (double)(EG_ENT<<ENV_BITS);
  596 + OPL->AR_TABLE[i] = rate / ARRATE;
  597 + OPL->DR_TABLE[i] = rate / DRRATE;
  598 + }
  599 + for (i = 60;i < 76;i++)
  600 + {
  601 + OPL->AR_TABLE[i] = EG_AED-1;
  602 + OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
  603 + }
  604 +#if 0
  605 + for (i = 0;i < 64 ;i++){ /* make for overflow area */
  606 + LOG(LOG_WAR,("rate %2d , ar %f ms , dr %f ms \n",i,
  607 + ((double)(EG_ENT<<ENV_BITS) / OPL->AR_TABLE[i]) * (1000.0 / OPL->rate),
  608 + ((double)(EG_ENT<<ENV_BITS) / OPL->DR_TABLE[i]) * (1000.0 / OPL->rate) ));
  609 + }
  610 +#endif
  611 +}
  612 +
  613 +/* ---------- generic table initialize ---------- */
  614 +static int OPLOpenTable( void )
  615 +{
  616 + int s,t;
  617 + double rate;
  618 + int i,j;
  619 + double pom;
  620 +
  621 + /* allocate dynamic tables */
  622 + if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL)
  623 + return 0;
  624 + if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)
  625 + {
  626 + free(TL_TABLE);
  627 + return 0;
  628 + }
  629 + if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)
  630 + {
  631 + free(TL_TABLE);
  632 + free(SIN_TABLE);
  633 + return 0;
  634 + }
  635 + if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)
  636 + {
  637 + free(TL_TABLE);
  638 + free(SIN_TABLE);
  639 + free(AMS_TABLE);
  640 + return 0;
  641 + }
  642 + /* make total level table */
  643 + for (t = 0;t < EG_ENT-1 ;t++){
  644 + rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20); /* dB -> voltage */
  645 + TL_TABLE[ t] = (int)rate;
  646 + TL_TABLE[TL_MAX+t] = -TL_TABLE[t];
  647 +/* LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/
  648 + }
  649 + /* fill volume off area */
  650 + for ( t = EG_ENT-1; t < TL_MAX ;t++){
  651 + TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;
  652 + }
  653 +
  654 + /* make sinwave table (total level offet) */
  655 + /* degree 0 = degree 180 = off */
  656 + SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1];
  657 + for (s = 1;s <= SIN_ENT/4;s++){
  658 + pom = sin(2*PI*s/SIN_ENT); /* sin */
  659 + pom = 20*log10(1/pom); /* decibel */
  660 + j = pom / EG_STEP; /* TL_TABLE steps */
  661 +
  662 + /* degree 0 - 90 , degree 180 - 90 : plus section */
  663 + SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];
  664 + /* degree 180 - 270 , degree 360 - 270 : minus section */
  665 + SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j];
  666 +/* LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/
  667 + }
  668 + for (s = 0;s < SIN_ENT;s++)
  669 + {
  670 + SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
  671 + SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)];
  672 + SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s];
  673 + }
  674 +
  675 + /* envelope counter -> envelope output table */
  676 + for (i=0; i<EG_ENT; i++)
  677 + {
  678 + /* ATTACK curve */
  679 + pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;
  680 + /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
  681 + ENV_CURVE[i] = (int)pom;
  682 + /* DECAY ,RELEASE curve */
  683 + ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;
  684 + }
  685 + /* off */
  686 + ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
  687 + /* make LFO ams table */
  688 + for (i=0; i<AMS_ENT; i++)
  689 + {
  690 + pom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */
  691 + AMS_TABLE[i] = (1.0/EG_STEP)*pom; /* 1dB */
  692 + AMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */
  693 + }
  694 + /* make LFO vibrate table */
  695 + for (i=0; i<VIB_ENT; i++)
  696 + {
  697 + /* 100cent = 1seminote = 6% ?? */
  698 + pom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */
  699 + VIB_TABLE[i] = VIB_RATE + (pom*0.07); /* +- 7cent */
  700 + VIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */
  701 + /* LOG(LOG_INF,("vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i])); */
  702 + }
  703 + return 1;
  704 +}
  705 +
  706 +
  707 +static void OPLCloseTable( void )
  708 +{
  709 + free(TL_TABLE);
  710 + free(SIN_TABLE);
  711 + free(AMS_TABLE);
  712 + free(VIB_TABLE);
  713 +}
  714 +
  715 +/* CSM Key Controll */
  716 +INLINE void CSMKeyControll(OPL_CH *CH)
  717 +{
  718 + OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
  719 + OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
  720 + /* all key off */
  721 + OPL_KEYOFF(slot1);
  722 + OPL_KEYOFF(slot2);
  723 + /* total level latch */
  724 + slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
  725 + slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
  726 + /* key on */
  727 + CH->op1_out[0] = CH->op1_out[1] = 0;
  728 + OPL_KEYON(slot1);
  729 + OPL_KEYON(slot2);
  730 +}
  731 +
  732 +/* ---------- opl initialize ---------- */
  733 +static void OPL_initalize(FM_OPL *OPL)
  734 +{
  735 + int fn;
  736 +
  737 + /* frequency base */
  738 + OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
  739 + /* Timer base time */
  740 + OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
  741 + /* make time tables */
  742 + init_timetables( OPL , OPL_ARRATE , OPL_DRRATE );
  743 + /* make fnumber -> increment counter table */
  744 + for( fn=0 ; fn < 1024 ; fn++ )
  745 + {
  746 + OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2;
  747 + }
  748 + /* LFO freq.table */
  749 + OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0;
  750 + OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0;
  751 +}
  752 +
  753 +/* ---------- write a OPL registers ---------- */
  754 +static void OPLWriteReg(FM_OPL *OPL, int r, int v)
  755 +{
  756 + OPL_CH *CH;
  757 + int slot;
  758 + int block_fnum;
  759 +
  760 + switch(r&0xe0)
  761 + {
  762 + case 0x00: /* 00-1f:controll */
  763 + switch(r&0x1f)
  764 + {
  765 + case 0x01:
  766 + /* wave selector enable */
  767 + if(OPL->type&OPL_TYPE_WAVESEL)
  768 + {
  769 + OPL->wavesel = v&0x20;
  770 + if(!OPL->wavesel)
  771 + {
  772 + /* preset compatible mode */
  773 + int c;
  774 + for(c=0;c<OPL->max_ch;c++)
  775 + {
  776 + OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
  777 + OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
  778 + }
  779 + }
  780 + }
  781 + return;
  782 + case 0x02: /* Timer 1 */
  783 + OPL->T[0] = (256-v)*4;
  784 + break;
  785 + case 0x03: /* Timer 2 */
  786 + OPL->T[1] = (256-v)*16;
  787 + return;
  788 + case 0x04: /* IRQ clear / mask and Timer enable */
  789 + if(v&0x80)
  790 + { /* IRQ flag clear */
  791 + OPL_STATUS_RESET(OPL,0x7f);
  792 + }
  793 + else
  794 + { /* set IRQ mask ,timer enable*/
  795 + UINT8 st1 = v&1;
  796 + UINT8 st2 = (v>>1)&1;
  797 + /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
  798 + OPL_STATUS_RESET(OPL,v&0x78);
  799 + OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);
  800 + /* timer 2 */
  801 + if(OPL->st[1] != st2)
  802 + {
  803 + double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0;
  804 + OPL->st[1] = st2;
  805 + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval);
  806 + }
  807 + /* timer 1 */
  808 + if(OPL->st[0] != st1)
  809 + {
  810 + double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0;
  811 + OPL->st[0] = st1;
  812 + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval);
  813 + }
  814 + }
  815 + return;
  816 +#if BUILD_Y8950
  817 + case 0x06: /* Key Board OUT */
  818 + if(OPL->type&OPL_TYPE_KEYBOARD)
  819 + {
  820 + if(OPL->keyboardhandler_w)
  821 + OPL->keyboardhandler_w(OPL->keyboard_param,v);
  822 + else
  823 + LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n"));
  824 + }
  825 + return;
  826 + case 0x07: /* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
  827 + if(OPL->type&OPL_TYPE_ADPCM)
  828 + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
  829 + return;
  830 + case 0x08: /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
  831 + OPL->mode = v;
  832 + v&=0x1f; /* for DELTA-T unit */
  833 + case 0x09: /* START ADD */
  834 + case 0x0a:
  835 + case 0x0b: /* STOP ADD */
  836 + case 0x0c:
  837 + case 0x0d: /* PRESCALE */
  838 + case 0x0e:
  839 + case 0x0f: /* ADPCM data */
  840 + case 0x10: /* DELTA-N */
  841 + case 0x11: /* DELTA-N */
  842 + case 0x12: /* EG-CTRL */
  843 + if(OPL->type&OPL_TYPE_ADPCM)
  844 + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
  845 + return;
  846 +#if 0
  847 + case 0x15: /* DAC data */
  848 + case 0x16:
  849 + case 0x17: /* SHIFT */
  850 + return;
  851 + case 0x18: /* I/O CTRL (Direction) */
  852 + if(OPL->type&OPL_TYPE_IO)
  853 + OPL->portDirection = v&0x0f;
  854 + return;
  855 + case 0x19: /* I/O DATA */
  856 + if(OPL->type&OPL_TYPE_IO)
  857 + {
  858 + OPL->portLatch = v;
  859 + if(OPL->porthandler_w)
  860 + OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
  861 + }
  862 + return;
  863 + case 0x1a: /* PCM data */
  864 + return;
  865 +#endif
  866 +#endif
  867 + }
  868 + break;
  869 + case 0x20: /* am,vib,ksr,eg type,mul */
  870 + slot = slot_array[r&0x1f];
  871 + if(slot == -1) return;
  872 + set_mul(OPL,slot,v);
  873 + return;
  874 + case 0x40:
  875 + slot = slot_array[r&0x1f];
  876 + if(slot == -1) return;
  877 + set_ksl_tl(OPL,slot,v);
  878 + return;
  879 + case 0x60:
  880 + slot = slot_array[r&0x1f];
  881 + if(slot == -1) return;
  882 + set_ar_dr(OPL,slot,v);
  883 + return;
  884 + case 0x80:
  885 + slot = slot_array[r&0x1f];
  886 + if(slot == -1) return;
  887 + set_sl_rr(OPL,slot,v);
  888 + return;
  889 + case 0xa0:
  890 + switch(r)
  891 + {
  892 + case 0xbd:
  893 + /* amsep,vibdep,r,bd,sd,tom,tc,hh */
  894 + {
  895 + UINT8 rkey = OPL->rythm^v;
  896 + OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
  897 + OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
  898 + OPL->rythm = v&0x3f;
  899 + if(OPL->rythm&0x20)
  900 + {
  901 +#if 0
  902 + usrintf_showmessage("OPL Rythm mode select");
  903 +#endif
  904 + /* BD key on/off */
  905 + if(rkey&0x10)
  906 + {
  907 + if(v&0x10)
  908 + {
  909 + OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
  910 + OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
  911 + OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
  912 + }
  913 + else
  914 + {
  915 + OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
  916 + OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
  917 + }
  918 + }
  919 + /* SD key on/off */
  920 + if(rkey&0x08)
  921 + {
  922 + if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
  923 + else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
  924 + }/* TAM key on/off */
  925 + if(rkey&0x04)
  926 + {
  927 + if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
  928 + else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
  929 + }
  930 + /* TOP-CY key on/off */
  931 + if(rkey&0x02)
  932 + {
  933 + if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
  934 + else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
  935 + }
  936 + /* HH key on/off */
  937 + if(rkey&0x01)
  938 + {
  939 + if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
  940 + else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
  941 + }
  942 + }
  943 + }
  944 + return;
  945 + }
  946 + /* keyon,block,fnum */
  947 + if( (r&0x0f) > 8) return;
  948 + CH = &OPL->P_CH[r&0x0f];
  949 + if(!(r&0x10))
  950 + { /* a0-a8 */
  951 + block_fnum = (CH->block_fnum&0x1f00) | v;
  952 + }
  953 + else
  954 + { /* b0-b8 */
  955 + int keyon = (v>>5)&1;
  956 + block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
  957 + if(CH->keyon != keyon)
  958 + {
  959 + if( (CH->keyon=keyon) )
  960 + {
  961 + CH->op1_out[0] = CH->op1_out[1] = 0;
  962 + OPL_KEYON(&CH->SLOT[SLOT1]);
  963 + OPL_KEYON(&CH->SLOT[SLOT2]);
  964 + }
  965 + else
  966 + {
  967 + OPL_KEYOFF(&CH->SLOT[SLOT1]);
  968 + OPL_KEYOFF(&CH->SLOT[SLOT2]);
  969 + }
  970 + }
  971 + }
  972 + /* update */
  973 + if(CH->block_fnum != block_fnum)
  974 + {
  975 + int blockRv = 7-(block_fnum>>10);
  976 + int fnum = block_fnum&0x3ff;
  977 + CH->block_fnum = block_fnum;
  978 +
  979 + CH->ksl_base = KSL_TABLE[block_fnum>>6];
  980 + CH->fc = OPL->FN_TABLE[fnum]>>blockRv;
  981 + CH->kcode = CH->block_fnum>>9;
  982 + if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;
  983 + CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
  984 + CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
  985 + }
  986 + return;
  987 + case 0xc0:
  988 + /* FB,C */
  989 + if( (r&0x0f) > 8) return;
  990 + CH = &OPL->P_CH[r&0x0f];
  991 + {
  992 + int feedback = (v>>1)&7;
  993 + CH->FB = feedback ? (8+1) - feedback : 0;
  994 + CH->CON = v&1;
  995 + set_algorythm(CH);
  996 + }
  997 + return;
  998 + case 0xe0: /* wave type */
  999 + slot = slot_array[r&0x1f];
  1000 + if(slot == -1) return;
  1001 + CH = &OPL->P_CH[slot/2];
  1002 + if(OPL->wavesel)
  1003 + {
  1004 + /* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */
  1005 + CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];
  1006 + }
  1007 + return;
  1008 + }
  1009 +}
  1010 +
  1011 +/* lock/unlock for common table */
  1012 +static int OPL_LockTable(void)
  1013 +{
  1014 + num_lock++;
  1015 + if(num_lock>1) return 0;
  1016 + /* first time */
  1017 + cur_chip = NULL;
  1018 + /* allocate total level table (128kb space) */
  1019 + if( !OPLOpenTable() )
  1020 + {
  1021 + num_lock--;
  1022 + return -1;
  1023 + }
  1024 + return 0;
  1025 +}
  1026 +
  1027 +static void OPL_UnLockTable(void)
  1028 +{
  1029 + if(num_lock) num_lock--;
  1030 + if(num_lock) return;
  1031 + /* last time */
  1032 + cur_chip = NULL;
  1033 + OPLCloseTable();
  1034 +}
  1035 +
  1036 +#if (BUILD_YM3812 || BUILD_YM3526)
  1037 +/*******************************************************************************/
  1038 +/* YM3812 local section */
  1039 +/*******************************************************************************/
  1040 +
  1041 +/* ---------- update one of chip ----------- */
  1042 +void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
  1043 +{
  1044 + int i;
  1045 + int data;
  1046 + OPLSAMPLE *buf = buffer;
  1047 + UINT32 amsCnt = OPL->amsCnt;
  1048 + UINT32 vibCnt = OPL->vibCnt;
  1049 + UINT8 rythm = OPL->rythm&0x20;
  1050 + OPL_CH *CH,*R_CH;
  1051 +
  1052 + if( (void *)OPL != cur_chip ){
  1053 + cur_chip = (void *)OPL;
  1054 + /* channel pointers */
  1055 + S_CH = OPL->P_CH;
  1056 + E_CH = &S_CH[9];
  1057 + /* rythm slot */
  1058 + SLOT7_1 = &S_CH[7].SLOT[SLOT1];
  1059 + SLOT7_2 = &S_CH[7].SLOT[SLOT2];
  1060 + SLOT8_1 = &S_CH[8].SLOT[SLOT1];
  1061 + SLOT8_2 = &S_CH[8].SLOT[SLOT2];
  1062 + /* LFO state */
  1063 + amsIncr = OPL->amsIncr;
  1064 + vibIncr = OPL->vibIncr;
  1065 + ams_table = OPL->ams_table;
  1066 + vib_table = OPL->vib_table;
  1067 + }
  1068 + R_CH = rythm ? &S_CH[6] : E_CH;
  1069 + for( i=0; i < length ; i++ )
  1070 + {
  1071 + /* channel A channel B channel C */
  1072 + /* LFO */
  1073 + ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
  1074 + vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
  1075 + outd[0] = 0;
  1076 + /* FM part */
  1077 + for(CH=S_CH ; CH < R_CH ; CH++)
  1078 + OPL_CALC_CH(CH);
  1079 + /* Rythn part */
  1080 + if(rythm)
  1081 + OPL_CALC_RH(S_CH);
  1082 + /* limit check */
  1083 + data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
  1084 + /* store to sound buffer */
  1085 + buf[i] = data >> OPL_OUTSB;
  1086 + }
  1087 +
  1088 + OPL->amsCnt = amsCnt;
  1089 + OPL->vibCnt = vibCnt;
  1090 +#ifdef OPL_OUTPUT_LOG
  1091 + if(opl_dbg_fp)
  1092 + {
  1093 + for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
  1094 + if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
  1095 + fprintf(opl_dbg_fp,"%c%c%c",0x20+opl_dbg_chip,length&0xff,length/256);
  1096 + }
  1097 +#endif
  1098 +}
  1099 +#endif /* (BUILD_YM3812 || BUILD_YM3526) */
  1100 +
  1101 +#if BUILD_Y8950
  1102 +
  1103 +void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
  1104 +{
  1105 + int i;
  1106 + int data;
  1107 + OPLSAMPLE *buf = buffer;
  1108 + UINT32 amsCnt = OPL->amsCnt;
  1109 + UINT32 vibCnt = OPL->vibCnt;
  1110 + UINT8 rythm = OPL->rythm&0x20;
  1111 + OPL_CH *CH,*R_CH;
  1112 + YM_DELTAT *DELTAT = OPL->deltat;
  1113 +
  1114 + /* setup DELTA-T unit */
  1115 + YM_DELTAT_DECODE_PRESET(DELTAT);
  1116 +
  1117 + if( (void *)OPL != cur_chip ){
  1118 + cur_chip = (void *)OPL;
  1119 + /* channel pointers */
  1120 + S_CH = OPL->P_CH;
  1121 + E_CH = &S_CH[9];
  1122 + /* rythm slot */
  1123 + SLOT7_1 = &S_CH[7].SLOT[SLOT1];
  1124 + SLOT7_2 = &S_CH[7].SLOT[SLOT2];
  1125 + SLOT8_1 = &S_CH[8].SLOT[SLOT1];
  1126 + SLOT8_2 = &S_CH[8].SLOT[SLOT2];
  1127 + /* LFO state */
  1128 + amsIncr = OPL->amsIncr;
  1129 + vibIncr = OPL->vibIncr;
  1130 + ams_table = OPL->ams_table;
  1131 + vib_table = OPL->vib_table;
  1132 + }
  1133 + R_CH = rythm ? &S_CH[6] : E_CH;
  1134 + for( i=0; i < length ; i++ )
  1135 + {
  1136 + /* channel A channel B channel C */
  1137 + /* LFO */
  1138 + ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
  1139 + vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
  1140 + outd[0] = 0;
  1141 + /* deltaT ADPCM */
  1142 + if( DELTAT->portstate )
  1143 + YM_DELTAT_ADPCM_CALC(DELTAT);
  1144 + /* FM part */
  1145 + for(CH=S_CH ; CH < R_CH ; CH++)
  1146 + OPL_CALC_CH(CH);
  1147 + /* Rythn part */
  1148 + if(rythm)
  1149 + OPL_CALC_RH(S_CH);
  1150 + /* limit check */
  1151 + data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
  1152 + /* store to sound buffer */
  1153 + buf[i] = data >> OPL_OUTSB;
  1154 + }
  1155 + OPL->amsCnt = amsCnt;
  1156 + OPL->vibCnt = vibCnt;
  1157 + /* deltaT START flag */
  1158 + if( !DELTAT->portstate )
  1159 + OPL->status &= 0xfe;
  1160 +}
  1161 +#endif
  1162 +
  1163 +/* ---------- reset one of chip ---------- */
  1164 +void OPLResetChip(FM_OPL *OPL)
  1165 +{
  1166 + int c,s;
  1167 + int i;
  1168 +
  1169 + /* reset chip */
  1170 + OPL->mode = 0; /* normal mode */
  1171 + OPL_STATUS_RESET(OPL,0x7f);
  1172 + /* reset with register write */
  1173 + OPLWriteReg(OPL,0x01,0); /* wabesel disable */
  1174 + OPLWriteReg(OPL,0x02,0); /* Timer1 */
  1175 + OPLWriteReg(OPL,0x03,0); /* Timer2 */
  1176 + OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
  1177 + for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
  1178 + /* reset OPerator paramater */
  1179 + for( c = 0 ; c < OPL->max_ch ; c++ )
  1180 + {
  1181 + OPL_CH *CH = &OPL->P_CH[c];
  1182 + /* OPL->P_CH[c].PAN = OPN_CENTER; */
  1183 + for(s = 0 ; s < 2 ; s++ )
  1184 + {
  1185 + /* wave table */
  1186 + CH->SLOT[s].wavetable = &SIN_TABLE[0];
  1187 + /* CH->SLOT[s].evm = ENV_MOD_RR; */
  1188 + CH->SLOT[s].evc = EG_OFF;
  1189 + CH->SLOT[s].eve = EG_OFF+1;
  1190 + CH->SLOT[s].evs = 0;
  1191 + }
  1192 + }
  1193 +#if BUILD_Y8950
  1194 + if(OPL->type&OPL_TYPE_ADPCM)
  1195 + {
  1196 + YM_DELTAT *DELTAT = OPL->deltat;
  1197 +
  1198 + DELTAT->freqbase = OPL->freqbase;
  1199 + DELTAT->output_pointer = outd;
  1200 + DELTAT->portshift = 5;
  1201 + DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;
  1202 + YM_DELTAT_ADPCM_Reset(DELTAT,0);
  1203 + }
  1204 +#endif
  1205 +}
  1206 +
  1207 +/* ---------- Create one of vietual YM3812 ---------- */
  1208 +/* 'rate' is sampling rate and 'bufsiz' is the size of the */
  1209 +FM_OPL *OPLCreate(int type, int clock, int rate)
  1210 +{
  1211 + char *ptr;
  1212 + FM_OPL *OPL;
  1213 + int state_size;
  1214 + int max_ch = 9; /* normaly 9 channels */
  1215 +
  1216 + if( OPL_LockTable() ==-1) return NULL;
  1217 + /* allocate OPL state space */
  1218 + state_size = sizeof(FM_OPL);
  1219 + state_size += sizeof(OPL_CH)*max_ch;
  1220 +#if BUILD_Y8950
  1221 + if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
  1222 +#endif
  1223 + /* allocate memory block */
  1224 + ptr = malloc(state_size);
  1225 + if(ptr==NULL) return NULL;
  1226 + /* clear */
  1227 + memset(ptr,0,state_size);
  1228 + OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
  1229 + OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
  1230 +#if BUILD_Y8950
  1231 + if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);
  1232 +#endif
  1233 + /* set channel state pointer */
  1234 + OPL->type = type;
  1235 + OPL->clock = clock;
  1236 + OPL->rate = rate;
  1237 + OPL->max_ch = max_ch;
  1238 + /* init grobal tables */
  1239 + OPL_initalize(OPL);
  1240 + /* reset chip */
  1241 + OPLResetChip(OPL);
  1242 +#ifdef OPL_OUTPUT_LOG
  1243 + if(!opl_dbg_fp)
  1244 + {
  1245 + opl_dbg_fp = fopen("opllog.opl","wb");
  1246 + opl_dbg_maxchip = 0;
  1247 + }
  1248 + if(opl_dbg_fp)
  1249 + {
  1250 + opl_dbg_opl[opl_dbg_maxchip] = OPL;
  1251 + fprintf(opl_dbg_fp,"%c%c%c%c%c%c",0x00+opl_dbg_maxchip,
  1252 + type,
  1253 + clock&0xff,
  1254 + (clock/0x100)&0xff,
  1255 + (clock/0x10000)&0xff,
  1256 + (clock/0x1000000)&0xff);
  1257 + opl_dbg_maxchip++;
  1258 + }
  1259 +#endif
  1260 + return OPL;
  1261 +}
  1262 +
  1263 +/* ---------- Destroy one of vietual YM3812 ---------- */
  1264 +void OPLDestroy(FM_OPL *OPL)
  1265 +{
  1266 +#ifdef OPL_OUTPUT_LOG
  1267 + if(opl_dbg_fp)
  1268 + {
  1269 + fclose(opl_dbg_fp);
  1270 + opl_dbg_fp = NULL;
  1271 + }
  1272 +#endif
  1273 + OPL_UnLockTable();
  1274 + free(OPL);
  1275 +}
  1276 +
  1277 +/* ---------- Option handlers ---------- */
  1278 +
  1279 +void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)
  1280 +{
  1281 + OPL->TimerHandler = TimerHandler;
  1282 + OPL->TimerParam = channelOffset;
  1283 +}
  1284 +void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
  1285 +{
  1286 + OPL->IRQHandler = IRQHandler;
  1287 + OPL->IRQParam = param;
  1288 +}
  1289 +void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param)
  1290 +{
  1291 + OPL->UpdateHandler = UpdateHandler;
  1292 + OPL->UpdateParam = param;
  1293 +}
  1294 +#if BUILD_Y8950
  1295 +void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param)
  1296 +{
  1297 + OPL->porthandler_w = PortHandler_w;
  1298 + OPL->porthandler_r = PortHandler_r;
  1299 + OPL->port_param = param;
  1300 +}
  1301 +
  1302 +void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param)
  1303 +{
  1304 + OPL->keyboardhandler_w = KeyboardHandler_w;
  1305 + OPL->keyboardhandler_r = KeyboardHandler_r;
  1306 + OPL->keyboard_param = param;
  1307 +}
  1308 +#endif
  1309 +/* ---------- YM3812 I/O interface ---------- */
  1310 +int OPLWrite(FM_OPL *OPL,int a,int v)
  1311 +{
  1312 + if( !(a&1) )
  1313 + { /* address port */
  1314 + OPL->address = v & 0xff;
  1315 + }
  1316 + else
  1317 + { /* data port */
  1318 + if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
  1319 +#ifdef OPL_OUTPUT_LOG
  1320 + if(opl_dbg_fp)
  1321 + {
  1322 + for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
  1323 + if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
  1324 + fprintf(opl_dbg_fp,"%c%c%c",0x10+opl_dbg_chip,OPL->address,v);
  1325 + }
  1326 +#endif
  1327 + OPLWriteReg(OPL,OPL->address,v);
  1328 + }
  1329 + return OPL->status>>7;
  1330 +}
  1331 +
  1332 +unsigned char OPLRead(FM_OPL *OPL,int a)
  1333 +{
  1334 + if( !(a&1) )
  1335 + { /* status port */
  1336 + return OPL->status & (OPL->statusmask|0x80);
  1337 + }
  1338 + /* data port */
  1339 + switch(OPL->address)
  1340 + {
  1341 + case 0x05: /* KeyBoard IN */
  1342 + if(OPL->type&OPL_TYPE_KEYBOARD)
  1343 + {
  1344 + if(OPL->keyboardhandler_r)
  1345 + return OPL->keyboardhandler_r(OPL->keyboard_param);
  1346 + else
  1347 + LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n"));
  1348 + }
  1349 + return 0;
  1350 +#if 0
  1351 + case 0x0f: /* ADPCM-DATA */
  1352 + return 0;
  1353 +#endif
  1354 + case 0x19: /* I/O DATA */
  1355 + if(OPL->type&OPL_TYPE_IO)
  1356 + {
  1357 + if(OPL->porthandler_r)
  1358 + return OPL->porthandler_r(OPL->port_param);
  1359 + else
  1360 + LOG(LOG_WAR,("OPL:read unmapped I/O port\n"));
  1361 + }
  1362 + return 0;
  1363 + case 0x1a: /* PCM-DATA */
  1364 + return 0;
  1365 + }
  1366 + return 0;
  1367 +}
  1368 +
  1369 +int OPLTimerOver(FM_OPL *OPL,int c)
  1370 +{
  1371 + if( c )
  1372 + { /* Timer B */
  1373 + OPL_STATUS_SET(OPL,0x20);
  1374 + }
  1375 + else
  1376 + { /* Timer A */
  1377 + OPL_STATUS_SET(OPL,0x40);
  1378 + /* CSM mode key,TL controll */
  1379 + if( OPL->mode & 0x80 )
  1380 + { /* CSM mode total level latch and auto key on */
  1381 + int ch;
  1382 + if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
  1383 + for(ch=0;ch<9;ch++)
  1384 + CSMKeyControll( &OPL->P_CH[ch] );
  1385 + }
  1386 + }
  1387 + /* reload timer */
  1388 + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase);
  1389 + return OPL->status>>7;
  1390 +}
... ...
hw/fmopl.h 0 → 100644
  1 +#ifndef __FMOPL_H_
  2 +#define __FMOPL_H_
  3 +
  4 +/* --- select emulation chips --- */
  5 +#define BUILD_YM3812 (HAS_YM3812)
  6 +//#define BUILD_YM3526 (HAS_YM3526)
  7 +//#define BUILD_Y8950 (HAS_Y8950)
  8 +
  9 +/* --- system optimize --- */
  10 +/* select bit size of output : 8 or 16 */
  11 +#define OPL_OUTPUT_BIT 16
  12 +
  13 +/* compiler dependence */
  14 +#ifndef OSD_CPU_H
  15 +#define OSD_CPU_H
  16 +typedef unsigned char UINT8; /* unsigned 8bit */
  17 +typedef unsigned short UINT16; /* unsigned 16bit */
  18 +typedef unsigned int UINT32; /* unsigned 32bit */
  19 +typedef signed char INT8; /* signed 8bit */
  20 +typedef signed short INT16; /* signed 16bit */
  21 +typedef signed int INT32; /* signed 32bit */
  22 +#endif
  23 +
  24 +#if (OPL_OUTPUT_BIT==16)
  25 +typedef INT16 OPLSAMPLE;
  26 +#endif
  27 +#if (OPL_OUTPUT_BIT==8)
  28 +typedef unsigned char OPLSAMPLE;
  29 +#endif
  30 +
  31 +
  32 +#if BUILD_Y8950
  33 +#include "ymdeltat.h"
  34 +#endif
  35 +
  36 +typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
  37 +typedef void (*OPL_IRQHANDLER)(int param,int irq);
  38 +typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
  39 +typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
  40 +typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
  41 +
  42 +/* !!!!! here is private section , do not access there member direct !!!!! */
  43 +
  44 +#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
  45 +#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */
  46 +#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */
  47 +#define OPL_TYPE_IO 0x08 /* I/O port */
  48 +
  49 +/* Saving is necessary for member of the 'R' mark for suspend/resume */
  50 +/* ---------- OPL one of slot ---------- */
  51 +typedef struct fm_opl_slot {
  52 + INT32 TL; /* total level :TL << 8 */
  53 + INT32 TLL; /* adjusted now TL */
  54 + UINT8 KSR; /* key scale rate :(shift down bit) */
  55 + INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */
  56 + INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */
  57 + INT32 SL; /* sustin level :SL_TALBE[SL] */
  58 + INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */
  59 + UINT8 ksl; /* keyscale level :(shift down bits) */
  60 + UINT8 ksr; /* key scale rate :kcode>>KSR */
  61 + UINT32 mul; /* multiple :ML_TABLE[ML] */
  62 + UINT32 Cnt; /* frequency count : */
  63 + UINT32 Incr; /* frequency step : */
  64 + /* envelope generator state */
  65 + UINT8 eg_typ; /* envelope type flag */
  66 + UINT8 evm; /* envelope phase */
  67 + INT32 evc; /* envelope counter */
  68 + INT32 eve; /* envelope counter end point */
  69 + INT32 evs; /* envelope counter step */
  70 + INT32 evsa; /* envelope step for AR :AR[ksr] */
  71 + INT32 evsd; /* envelope step for DR :DR[ksr] */
  72 + INT32 evsr; /* envelope step for RR :RR[ksr] */
  73 + /* LFO */
  74 + UINT8 ams; /* ams flag */
  75 + UINT8 vib; /* vibrate flag */
  76 + /* wave selector */
  77 + INT32 **wavetable;
  78 +}OPL_SLOT;
  79 +
  80 +/* ---------- OPL one of channel ---------- */
  81 +typedef struct fm_opl_channel {
  82 + OPL_SLOT SLOT[2];
  83 + UINT8 CON; /* connection type */
  84 + UINT8 FB; /* feed back :(shift down bit) */
  85 + INT32 *connect1; /* slot1 output pointer */
  86 + INT32 *connect2; /* slot2 output pointer */
  87 + INT32 op1_out[2]; /* slot1 output for selfeedback */
  88 + /* phase generator state */
  89 + UINT32 block_fnum; /* block+fnum : */
  90 + UINT8 kcode; /* key code : KeyScaleCode */
  91 + UINT32 fc; /* Freq. Increment base */
  92 + UINT32 ksl_base; /* KeyScaleLevel Base step */
  93 + UINT8 keyon; /* key on/off flag */
  94 +} OPL_CH;
  95 +
  96 +/* OPL state */
  97 +typedef struct fm_opl_f {
  98 + UINT8 type; /* chip type */
  99 + int clock; /* master clock (Hz) */
  100 + int rate; /* sampling rate (Hz) */
  101 + double freqbase; /* frequency base */
  102 + double TimerBase; /* Timer base time (==sampling time) */
  103 + UINT8 address; /* address register */
  104 + UINT8 status; /* status flag */
  105 + UINT8 statusmask; /* status mask */
  106 + UINT32 mode; /* Reg.08 : CSM , notesel,etc. */
  107 + /* Timer */
  108 + int T[2]; /* timer counter */
  109 + UINT8 st[2]; /* timer enable */
  110 + /* FM channel slots */
  111 + OPL_CH *P_CH; /* pointer of CH */
  112 + int max_ch; /* maximum channel */
  113 + /* Rythm sention */
  114 + UINT8 rythm; /* Rythm mode , key flag */
  115 +#if BUILD_Y8950
  116 + /* Delta-T ADPCM unit (Y8950) */
  117 + YM_DELTAT *deltat; /* DELTA-T ADPCM */
  118 +#endif
  119 + /* Keyboard / I/O interface unit (Y8950) */
  120 + UINT8 portDirection;
  121 + UINT8 portLatch;
  122 + OPL_PORTHANDLER_R porthandler_r;
  123 + OPL_PORTHANDLER_W porthandler_w;
  124 + int port_param;
  125 + OPL_PORTHANDLER_R keyboardhandler_r;
  126 + OPL_PORTHANDLER_W keyboardhandler_w;
  127 + int keyboard_param;
  128 + /* time tables */
  129 + INT32 AR_TABLE[75]; /* atttack rate tables */
  130 + INT32 DR_TABLE[75]; /* decay rate tables */
  131 + UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */
  132 + /* LFO */
  133 + INT32 *ams_table;
  134 + INT32 *vib_table;
  135 + INT32 amsCnt;
  136 + INT32 amsIncr;
  137 + INT32 vibCnt;
  138 + INT32 vibIncr;
  139 + /* wave selector enable flag */
  140 + UINT8 wavesel;
  141 + /* external event callback handler */
  142 + OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
  143 + int TimerParam; /* TIMER parameter */
  144 + OPL_IRQHANDLER IRQHandler; /* IRQ handler */
  145 + int IRQParam; /* IRQ parameter */
  146 + OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */
  147 + int UpdateParam; /* stream update parameter */
  148 +} FM_OPL;
  149 +
  150 +/* ---------- Generic interface section ---------- */
  151 +#define OPL_TYPE_YM3526 (0)
  152 +#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
  153 +#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
  154 +
  155 +FM_OPL *OPLCreate(int type, int clock, int rate);
  156 +void OPLDestroy(FM_OPL *OPL);
  157 +void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset);
  158 +void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param);
  159 +void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param);
  160 +/* Y8950 port handlers */
  161 +void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param);
  162 +void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param);
  163 +
  164 +void OPLResetChip(FM_OPL *OPL);
  165 +int OPLWrite(FM_OPL *OPL,int a,int v);
  166 +unsigned char OPLRead(FM_OPL *OPL,int a);
  167 +int OPLTimerOver(FM_OPL *OPL,int c);
  168 +
  169 +/* YM3626/YM3812 local section */
  170 +void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
  171 +
  172 +void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
  173 +
  174 +#endif
... ...
... ... @@ -554,13 +554,10 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device,
554 554 kbd_init();
555 555 DMA_init(0);
556 556  
557   -#ifndef _WIN32
558 557 if (audio_enabled) {
559 558 /* no audio supported yet for win32 */
560 559 AUD_init();
561   - SB16_init();
562 560 }
563   -#endif
564 561  
565 562 floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
566 563  
... ...
hw/sb16.c
1 1 /*
2 2 * QEMU Soundblaster 16 emulation
3 3 *
4   - * Copyright (c) 2003 Vassili Karpov (malc)
  4 + * Copyright (c) 2003-2004 Vassili Karpov (malc)
5 5 *
6 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 7 * of this software and associated documentation files (the "Software"), to deal
... ... @@ -23,32 +23,20 @@
23 23 */
24 24 #include "vl.h"
25 25  
26   -#define MIN(a, b) ((a)>(b)?(b):(a))
27   -#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
28   -
29   -#define dolog(...) fprintf (stderr, "sb16: " __VA_ARGS__);
  26 +/* #define DEBUG */
  27 +#define AUDIO_CAP "sb16"
  28 +#include "audio/audio.h"
30 29  
31   -/* #define DEBUG_SB16 */
  30 +#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
32 31  
33   -#ifdef DEBUG_SB16
34   -#define lwarn(...) fprintf (stderr, "sb16: " __VA_ARGS__)
35   -#define linfo(...) fprintf (stderr, "sb16: " __VA_ARGS__)
36   -#define ldebug(...) fprintf (stderr, "sb16: " __VA_ARGS__)
37   -#else
38   -#define lwarn(...)
39   -#define linfo(...)
40   -#define ldebug(...)
41   -#endif
  32 +/* #define DEBUG_SB16_MOST */
42 33  
43   -#define IO_READ_PROTO(name) \
  34 +#define IO_READ_PROTO(name) \
44 35 uint32_t name (void *opaque, uint32_t nport)
45   -#define IO_WRITE_PROTO(name) \
  36 +#define IO_WRITE_PROTO(name) \
46 37 void name (void *opaque, uint32_t nport, uint32_t val)
47 38  
48   -static const char e3[] =
49   - "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992\0"
50   - "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1994-1997";
51   - /* "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1994."; */
  39 +static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
52 40  
53 41 static struct {
54 42 int ver_lo;
... ... @@ -57,38 +45,58 @@ static struct {
57 45 int dma;
58 46 int hdma;
59 47 int port;
60   - int mix_block;
61   -} sb = {5, 4, 5, 1, 5, 0x220, -1};
62   -
63   -static int mix_block, noirq;
  48 +} conf = {5, 4, 5, 1, 5, 0x220};
64 49  
65 50 typedef struct SB16State {
  51 + int irq;
  52 + int dma;
  53 + int hdma;
  54 + int port;
  55 + int ver;
  56 +
66 57 int in_index;
67 58 int out_data_len;
68 59 int fmt_stereo;
69 60 int fmt_signed;
70 61 int fmt_bits;
  62 + audfmt_e fmt;
71 63 int dma_auto;
72   - int dma_buffer_size;
  64 + int block_size;
73 65 int fifo;
74 66 int freq;
75 67 int time_const;
76 68 int speaker;
77 69 int needed_bytes;
78 70 int cmd;
79   - int dma_pos;
80 71 int use_hdma;
  72 + int highspeed;
  73 + int can_write;
81 74  
82 75 int v2x6;
83 76  
  77 + uint8_t csp_param;
  78 + uint8_t csp_value;
  79 + uint8_t csp_mode;
  80 + uint8_t csp_regs[256];
  81 + uint8_t csp_index;
  82 + uint8_t csp_reg83[4];
  83 + int csp_reg83r;
  84 + int csp_reg83w;
  85 +
84 86 uint8_t in2_data[10];
85   - uint8_t out_data[1024];
  87 + uint8_t out_data[50];
  88 + uint8_t test_reg;
  89 + uint8_t last_read_byte;
  90 + int nzero;
86 91  
87 92 int left_till_irq;
88   - uint64_t nzero;
89   - uint8_t last_read_byte;
90   - uint8_t test_reg;
91 93  
  94 + int dma_running;
  95 + int bytes_per_second;
  96 + int align;
  97 + SWVoice *voice;
  98 +
  99 + QEMUTimer *ts, *aux_ts;
92 100 /* mixer state */
93 101 int mixer_nreg;
94 102 uint8_t mixer_regs[256];
... ... @@ -97,664 +105,853 @@ typedef struct SB16State {
97 105 /* XXX: suppress that and use a context */
98 106 static struct SB16State dsp;
99 107  
  108 +static int magic_of_irq (int irq)
  109 +{
  110 + switch (irq) {
  111 + case 5:
  112 + return 2;
  113 + case 7:
  114 + return 4;
  115 + case 9:
  116 + return 1;
  117 + case 10:
  118 + return 8;
  119 + default:
  120 + dolog ("bad irq %d\n", irq);
  121 + return 2;
  122 + }
  123 +}
  124 +
  125 +static int irq_of_magic (int magic)
  126 +{
  127 + switch (magic) {
  128 + case 1:
  129 + return 9;
  130 + case 2:
  131 + return 5;
  132 + case 4:
  133 + return 7;
  134 + case 8:
  135 + return 10;
  136 + default:
  137 + dolog ("bad irq magic %d\n", magic);
  138 + return -1;
  139 + }
  140 +}
  141 +
  142 +#if 0
100 143 static void log_dsp (SB16State *dsp)
101 144 {
102   - ldebug ("%c:%c:%d:%c:dmabuf=%d:pos=%d:freq=%d:timeconst=%d:speaker=%d\n",
103   - dsp->fmt_stereo ? 'S' : 'M',
104   - dsp->fmt_signed ? 'S' : 'U',
105   - dsp->fmt_bits,
106   - dsp->dma_auto ? 'a' : 's',
107   - dsp->dma_buffer_size,
108   - dsp->dma_pos,
109   - dsp->freq,
110   - dsp->time_const,
111   - dsp->speaker);
  145 + ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
  146 + dsp->fmt_stereo ? "Stereo" : "Mono",
  147 + dsp->fmt_signed ? "Signed" : "Unsigned",
  148 + dsp->fmt_bits,
  149 + dsp->dma_auto ? "Auto" : "Single",
  150 + dsp->block_size,
  151 + dsp->freq,
  152 + dsp->time_const,
  153 + dsp->speaker);
  154 +}
  155 +#endif
  156 +
  157 +static void speaker (SB16State *s, int on)
  158 +{
  159 + s->speaker = on;
  160 + /* AUD_enable (s->voice, on); */
112 161 }
113 162  
114   -static void control (int hold)
  163 +static void control (SB16State *s, int hold)
115 164 {
116   - linfo ("%d high %d\n", hold, dsp.use_hdma);
  165 + int dma = s->use_hdma ? s->hdma : s->dma;
  166 + s->dma_running = hold;
  167 +
  168 + ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
  169 +
117 170 if (hold) {
118   - if (dsp.use_hdma)
119   - DMA_hold_DREQ (sb.hdma);
120   - else
121   - DMA_hold_DREQ (sb.dma);
  171 + DMA_hold_DREQ (dma);
  172 + AUD_enable (s->voice, 1);
122 173 }
123 174 else {
124   - if (dsp.use_hdma)
125   - DMA_release_DREQ (sb.hdma);
126   - else
127   - DMA_release_DREQ (sb.dma);
  175 + DMA_release_DREQ (dma);
  176 + AUD_enable (s->voice, 0);
128 177 }
129 178 }
130 179  
131   -static void dma_cmd (uint8_t cmd, uint8_t d0, int dma_len)
  180 +static void aux_timer (void *opaque)
132 181 {
133   - int bps;
134   - audfmt_e fmt;
  182 + SB16State *s = opaque;
  183 + s->can_write = 1;
  184 + pic_set_irq (s->irq, 1);
  185 +}
  186 +
  187 +#define DMA8_AUTO 1
  188 +#define DMA8_HIGH 2
  189 +
  190 +static void dma_cmd8 (SB16State *s, int mask, int dma_len)
  191 +{
  192 + s->fmt = AUD_FMT_U8;
  193 + s->use_hdma = 0;
  194 + s->fmt_bits = 8;
  195 + s->fmt_signed = 0;
  196 + s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
  197 + if (-1 == s->time_const) {
  198 + s->freq = 11025;
  199 + }
  200 + else {
  201 + int tmp = (256 - s->time_const);
  202 + s->freq = (1000000 + (tmp / 2)) / tmp;
  203 + }
  204 +
  205 + if (-1 != dma_len)
  206 + s->block_size = dma_len + 1;
  207 +
  208 + s->freq >>= s->fmt_stereo;
  209 + s->left_till_irq = s->block_size;
  210 + s->bytes_per_second = (s->freq << s->fmt_stereo);
  211 + /* s->highspeed = (mask & DMA8_HIGH) != 0; */
  212 + s->dma_auto = (mask & DMA8_AUTO) != 0;
  213 + s->align = (1 << s->fmt_stereo) - 1;
  214 +
  215 + ldebug ("freq %d, stereo %d, sign %d, bits %d, "
  216 + "dma %d, auto %d, fifo %d, high %d\n",
  217 + s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
  218 + s->block_size, s->dma_auto, s->fifo, s->highspeed);
  219 +
  220 + if (s->freq)
  221 + s->voice = AUD_open (s->voice, "sb16", s->freq,
  222 + 1 << s->fmt_stereo, s->fmt);
  223 +
  224 + control (s, 1);
  225 + speaker (s, 1);
  226 +}
135 227  
136   - dsp.use_hdma = cmd < 0xc0;
137   - dsp.fifo = (cmd >> 1) & 1;
138   - dsp.dma_auto = (cmd >> 2) & 1;
  228 +static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
  229 +{
  230 + s->use_hdma = cmd < 0xc0;
  231 + s->fifo = (cmd >> 1) & 1;
  232 + s->dma_auto = (cmd >> 2) & 1;
  233 + s->fmt_signed = (d0 >> 4) & 1;
  234 + s->fmt_stereo = (d0 >> 5) & 1;
139 235  
140 236 switch (cmd >> 4) {
141 237 case 11:
142   - dsp.fmt_bits = 16;
  238 + s->fmt_bits = 16;
143 239 break;
144 240  
145 241 case 12:
146   - dsp.fmt_bits = 8;
  242 + s->fmt_bits = 8;
147 243 break;
148 244 }
149 245  
150   - dsp.fmt_signed = (d0 >> 4) & 1;
151   - dsp.fmt_stereo = (d0 >> 5) & 1;
152   -
153   - if (-1 != dsp.time_const) {
154   - int tmp;
155   -
156   - tmp = 256 - dsp.time_const;
157   - dsp.freq = (1000000 + (tmp / 2)) / tmp;
  246 + if (-1 != s->time_const) {
  247 +#if 1
  248 + int tmp = 256 - s->time_const;
  249 + s->freq = (1000000 + (tmp / 2)) / tmp;
  250 +#else
  251 + /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
  252 + s->freq = 1000000 / ((255 - s->time_const));
  253 +#endif
  254 + s->time_const = -1;
158 255 }
159   - bps = 1 << (16 == dsp.fmt_bits);
160 256  
161   - if (-1 != dma_len)
162   - dsp.dma_buffer_size = (dma_len + 1) * bps;
  257 + s->block_size = dma_len + 1;
  258 + s->block_size <<= (s->fmt_bits == 16);
  259 + if (!s->dma_auto) /* Miles Sound System ? */
  260 + s->block_size <<= s->fmt_stereo;
163 261  
164   - linfo ("frequency %d, stereo %d, signed %d, bits %d, size %d, auto %d\n",
165   - dsp.freq, dsp.fmt_stereo, dsp.fmt_signed, dsp.fmt_bits,
166   - dsp.dma_buffer_size, dsp.dma_auto);
  262 + ldebug ("freq %d, stereo %d, sign %d, bits %d, "
  263 + "dma %d, auto %d, fifo %d, high %d\n",
  264 + s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
  265 + s->block_size, s->dma_auto, s->fifo, s->highspeed);
167 266  
168   - if (16 == dsp.fmt_bits) {
169   - if (dsp.fmt_signed) {
170   - fmt = AUD_FMT_S16;
  267 + if (16 == s->fmt_bits) {
  268 + if (s->fmt_signed) {
  269 + s->fmt = AUD_FMT_S16;
171 270 }
172 271 else {
173   - fmt = AUD_FMT_U16;
  272 + s->fmt = AUD_FMT_U16;
174 273 }
175 274 }
176 275 else {
177   - if (dsp.fmt_signed) {
178   - fmt = AUD_FMT_S8;
  276 + if (s->fmt_signed) {
  277 + s->fmt = AUD_FMT_S8;
179 278 }
180 279 else {
181   - fmt = AUD_FMT_U8;
  280 + s->fmt = AUD_FMT_U8;
182 281 }
183 282 }
184 283  
185   - dsp.dma_pos = 0;
186   - dsp.left_till_irq = dsp.dma_buffer_size;
  284 + s->left_till_irq = s->block_size;
187 285  
188   - if (sb.mix_block) {
189   - mix_block = sb.mix_block;
190   - }
191   - else {
192   - int align;
  286 + s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
  287 + s->highspeed = 0;
  288 + s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
193 289  
194   - align = bps << dsp.fmt_stereo;
195   - mix_block = ((dsp.freq * align) / 100) & ~(align - 1);
196   - }
  290 + if (s->freq)
  291 + s->voice = AUD_open (s->voice, "sb16", s->freq,
  292 + 1 << s->fmt_stereo, s->fmt);
197 293  
198   - if (dsp.freq)
199   - AUD_reset (dsp.freq, 1 << dsp.fmt_stereo, fmt);
200   - control (1);
201   - dsp.speaker = 1;
  294 + control (s, 1);
  295 + speaker (s, 1);
202 296 }
203 297  
204   -static inline void dsp_out_data(SB16State *dsp, int val)
  298 +static inline void dsp_out_data (SB16State *s, uint8_t val)
205 299 {
206   - if (dsp->out_data_len < sizeof(dsp->out_data))
207   - dsp->out_data[dsp->out_data_len++] = val;
  300 + ldebug ("outdata %#x\n", val);
  301 + if (s->out_data_len < sizeof (s->out_data))
  302 + s->out_data[s->out_data_len++] = val;
208 303 }
209 304  
210   -static inline uint8_t dsp_get_data(SB16State *dsp)
  305 +static inline uint8_t dsp_get_data (SB16State *s)
211 306 {
212   - if (dsp->in_index)
213   - return dsp->in2_data[--dsp->in_index];
214   - else
  307 + if (s->in_index)
  308 + return s->in2_data[--s->in_index];
  309 + else {
  310 + dolog ("buffer underflow\n");
215 311 return 0;
  312 + }
216 313 }
217 314  
218   -static void command (SB16State *dsp, uint8_t cmd)
  315 +static void command (SB16State *s, uint8_t cmd)
219 316 {
220   - linfo ("command: %#x\n", cmd);
  317 + ldebug ("command %#x\n", cmd);
221 318  
222 319 if (cmd > 0xaf && cmd < 0xd0) {
223   - if (cmd & 8)
224   - goto error;
  320 + if (cmd & 8) {
  321 + dolog ("ADC not yet supported (command %#x)\n", cmd);
  322 + }
225 323  
226 324 switch (cmd >> 4) {
227 325 case 11:
228 326 case 12:
229 327 break;
230 328 default:
231   - dolog ("command: %#x wrong bits specification\n", cmd);
232   - goto error;
  329 + dolog ("%#x wrong bits\n", cmd);
233 330 }
234   - dsp->needed_bytes = 3;
  331 + s->needed_bytes = 3;
235 332 }
236 333 else {
237 334 switch (cmd) {
238   - case 0x00:
239   - case 0xe7:
240   - /* IMS uses those when probing for sound devices */
241   - return;
242   -
243 335 case 0x03:
  336 + dsp_out_data (s, 0x10); /* s->csp_param); */
  337 + goto warn;
  338 +
244 339 case 0x04:
245   - dsp_out_data (dsp, 0);
246   - return;
  340 + s->needed_bytes = 1;
  341 + goto warn;
247 342  
248 343 case 0x05:
249   - dsp->needed_bytes = 2;
250   - break;
  344 + s->needed_bytes = 2;
  345 + goto warn;
  346 +
  347 + case 0x08:
  348 + /* __asm__ ("int3"); */
  349 + goto warn;
251 350  
252 351 case 0x0e:
253   - dsp->needed_bytes = 2;
254   - break;
  352 + s->needed_bytes = 2;
  353 + goto warn;
  354 +
  355 + case 0x09:
  356 + dsp_out_data (s, 0xf8);
  357 + goto warn;
255 358  
256 359 case 0x0f:
257   - dsp->needed_bytes = 1;
258   - break;
  360 + s->needed_bytes = 1;
  361 + goto warn;
259 362  
260 363 case 0x10:
261   - dsp->needed_bytes = 1;
262   - break;
  364 + s->needed_bytes = 1;
  365 + goto warn;
263 366  
264 367 case 0x14:
265   - dsp->needed_bytes = 2;
266   - dsp->dma_buffer_size = 0;
  368 + s->needed_bytes = 2;
  369 + s->block_size = 0;
267 370 break;
268 371  
269   - case 0x20:
270   - dsp_out_data(dsp, 0xff);
271   - break;
  372 + case 0x20: /* Direct ADC, Juice/PL */
  373 + dsp_out_data (s, 0xff);
  374 + goto warn;
272 375  
273 376 case 0x35:
274   - lwarn ("MIDI commands not implemented\n");
  377 + dolog ("MIDI command(0x35) not implemented\n");
275 378 break;
276 379  
277 380 case 0x40:
278   - dsp->freq = -1;
279   - dsp->time_const = -1;
280   - dsp->needed_bytes = 1;
  381 + s->freq = -1;
  382 + s->time_const = -1;
  383 + s->needed_bytes = 1;
281 384 break;
282 385  
283 386 case 0x41:
284   - case 0x42:
285   - dsp->freq = -1;
286   - dsp->time_const = -1;
287   - dsp->needed_bytes = 2;
  387 + s->freq = -1;
  388 + s->time_const = -1;
  389 + s->needed_bytes = 2;
288 390 break;
289 391  
  392 + case 0x42:
  393 + s->freq = -1;
  394 + s->time_const = -1;
  395 + s->needed_bytes = 2;
  396 + goto warn;
  397 +
290 398 case 0x45:
291   - dsp_out_data (dsp, 0xaa);
  399 + dsp_out_data (s, 0xaa);
  400 + goto warn;
  401 +
292 402 case 0x47: /* Continue Auto-Initialize DMA 16bit */
293 403 break;
294 404  
295 405 case 0x48:
296   - dsp->needed_bytes = 2;
  406 + s->needed_bytes = 2;
297 407 break;
298 408  
299   - case 0x27: /* ????????? */
300   - case 0x4e:
301   - return;
302   -
303 409 case 0x80:
304   - cmd = -1;
  410 + s->needed_bytes = 2;
305 411 break;
306 412  
307 413 case 0x90:
308 414 case 0x91:
309   - {
310   - uint8_t d0;
311   -
312   - d0 = 4;
313   - /* if (dsp->fmt_signed) d0 |= 16; */
314   - /* if (dsp->fmt_stereo) d0 |= 32; */
315   - dma_cmd (cmd == 0x90 ? 0xc4 : 0xc0, d0, -1);
316   - cmd = -1;
317   - break;
318   - }
  415 + dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
  416 + break;
319 417  
320   - case 0xd0: /* XXX */
321   - control (0);
322   - return;
  418 + case 0xd0: /* halt DMA operation. 8bit */
  419 + control (s, 0);
  420 + break;
323 421  
324   - case 0xd1:
325   - dsp->speaker = 1;
  422 + case 0xd1: /* speaker on */
  423 + speaker (s, 1);
326 424 break;
327 425  
328   - case 0xd3:
329   - dsp->speaker = 0;
330   - return;
  426 + case 0xd3: /* speaker off */
  427 + speaker (s, 0);
  428 + break;
331 429  
332   - case 0xd4:
333   - control (1);
  430 + case 0xd4: /* continue DMA operation. 8bit */
  431 + control (s, 1);
334 432 break;
335 433  
336   - case 0xd5:
337   - control (0);
  434 + case 0xd5: /* halt DMA operation. 16bit */
  435 + control (s, 0);
338 436 break;
339 437  
340   - case 0xd6:
341   - control (1);
  438 + case 0xd6: /* continue DMA operation. 16bit */
  439 + control (s, 1);
342 440 break;
343 441  
344   - case 0xd9:
345   - control (0);
346   - dsp->dma_auto = 0;
347   - return;
  442 + case 0xd9: /* exit auto-init DMA after this block. 16bit */
  443 + s->dma_auto = 0;
  444 + break;
348 445  
349   - case 0xda:
350   - control (0);
351   - dsp->dma_auto = 0;
  446 + case 0xda: /* exit auto-init DMA after this block. 8bit */
  447 + s->dma_auto = 0;
352 448 break;
353 449  
354 450 case 0xe0:
355   - dsp->needed_bytes = 1;
356   - break;
  451 + s->needed_bytes = 1;
  452 + goto warn;
357 453  
358 454 case 0xe1:
359   - dsp_out_data(dsp, sb.ver_lo);
360   - dsp_out_data(dsp, sb.ver_hi);
361   - return;
  455 + dsp_out_data (s, s->ver & 0xff);
  456 + dsp_out_data (s, s->ver >> 8);
  457 + break;
  458 +
  459 + case 0xe2:
  460 + s->needed_bytes = 1;
  461 + goto warn;
362 462  
363 463 case 0xe3:
364 464 {
365 465 int i;
366   - for (i = sizeof (e3) - 1; i >= 0; i--)
367   - dsp_out_data (dsp, e3[i]);
368   - return;
  466 + for (i = sizeof (e3) - 1; i >= 0; --i)
  467 + dsp_out_data (s, e3[i]);
369 468 }
  469 + break;
370 470  
371 471 case 0xe4: /* write test reg */
372   - dsp->needed_bytes = 1;
  472 + s->needed_bytes = 1;
373 473 break;
374 474  
  475 + case 0xe7:
  476 + dolog ("Attempt to probe for ESS (0xe7)?\n");
  477 + return;
  478 +
375 479 case 0xe8: /* read test reg */
376   - dsp_out_data (dsp, dsp->test_reg);
  480 + dsp_out_data (s, s->test_reg);
377 481 break;
378 482  
379 483 case 0xf2:
380   - dsp_out_data (dsp, 0xaa);
381   - dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
382   - pic_set_irq (sb.irq, 1);
383   - return;
  484 + case 0xf3:
  485 + dsp_out_data (s, 0xaa);
  486 + s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
  487 + pic_set_irq (s->irq, 1);
  488 + break;
384 489  
385 490 case 0xf9:
386   - dsp->needed_bytes = 1;
387   - break;
  491 + s->needed_bytes = 1;
  492 + goto warn;
388 493  
389 494 case 0xfa:
390   - dsp_out_data (dsp, 0);
391   - break;
  495 + dsp_out_data (s, 0);
  496 + goto warn;
392 497  
393 498 case 0xfc: /* FIXME */
394   - dsp_out_data (dsp, 0);
395   - break;
  499 + dsp_out_data (s, 0);
  500 + goto warn;
396 501  
397 502 default:
398 503 dolog ("unrecognized command %#x\n", cmd);
399   - goto error;
  504 + return;
400 505 }
401 506 }
402   - dsp->cmd = cmd;
  507 +
  508 + s->cmd = cmd;
  509 + if (!s->needed_bytes)
  510 + ldebug ("\n");
403 511 return;
404 512  
405   - error:
  513 + warn:
  514 + dolog ("warning command %#x,%d is not trully understood yet\n",
  515 + cmd, s->needed_bytes);
  516 + s->cmd = cmd;
406 517 return;
407 518 }
408 519  
409   -static void complete (SB16State *dsp)
  520 +static uint16_t dsp_get_lohi (SB16State *s)
  521 +{
  522 + uint8_t hi = dsp_get_data (s);
  523 + uint8_t lo = dsp_get_data (s);
  524 + return (hi << 8) | lo;
  525 +}
  526 +
  527 +static uint16_t dsp_get_hilo (SB16State *s)
  528 +{
  529 + uint8_t lo = dsp_get_data (s);
  530 + uint8_t hi = dsp_get_data (s);
  531 + return (hi << 8) | lo;
  532 +}
  533 +
  534 +static void complete (SB16State *s)
410 535 {
411 536 int d0, d1, d2;
412   - linfo ("complete command %#x, in_index %d, needed_bytes %d\n",
413   - dsp->cmd, dsp->in_index, dsp->needed_bytes);
  537 + ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
  538 + s->cmd, s->in_index, s->needed_bytes);
414 539  
415   - if (dsp->cmd > 0xaf && dsp->cmd < 0xd0) {
416   - d2 = dsp_get_data (dsp);
417   - d1 = dsp_get_data (dsp);
418   - d0 = dsp_get_data (dsp);
  540 + if (s->cmd > 0xaf && s->cmd < 0xd0) {
  541 + d2 = dsp_get_data (s);
  542 + d1 = dsp_get_data (s);
  543 + d0 = dsp_get_data (s);
419 544  
420   - ldebug ("d0 = %d, d1 = %d, d2 = %d\n",
421   - d0, d1, d2);
422   - dma_cmd (dsp->cmd, d0, d1 + (d2 << 8));
  545 + if (s->cmd & 8) {
  546 + dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
  547 + s->cmd, d0, d1, d2);
  548 + }
  549 + else {
  550 + ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
  551 + s->cmd, d0, d1, d2);
  552 + dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
  553 + }
423 554 }
424 555 else {
425   - switch (dsp->cmd) {
  556 + switch (s->cmd) {
426 557 case 0x04:
427   - case 0x10:
428   - dsp_get_data (dsp);
  558 + s->csp_mode = dsp_get_data (s);
  559 + s->csp_reg83r = 0;
  560 + s->csp_reg83w = 0;
  561 + ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
429 562 break;
430 563  
431   - case 0x0f:
432   - d0 = dsp_get_data (dsp);
433   - dsp_out_data (dsp, 0xf8);
  564 + case 0x05:
  565 + s->csp_param = dsp_get_data (s);
  566 + s->csp_value = dsp_get_data (s);
  567 + ldebug ("CSP command 0x05: param=%#x value=%#x\n",
  568 + s->csp_param,
  569 + s->csp_value);
434 570 break;
435 571  
436   - case 0x05:
437 572 case 0x0e:
438   - dsp_get_data (dsp);
439   - dsp_get_data (dsp);
  573 + d0 = dsp_get_data (s);
  574 + d1 = dsp_get_data (s);
  575 + ldebug ("write CSP register %d <- %#x\n", d1, d0);
  576 + if (d1 == 0x83) {
  577 + ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
  578 + s->csp_reg83[s->csp_reg83r % 4] = d0;
  579 + s->csp_reg83r += 1;
  580 + }
  581 + else
  582 + s->csp_regs[d1] = d0;
440 583 break;
441 584  
442   - case 0x14:
443   - {
444   - int save_left;
445   - int save_pos;
446   -
447   - d1 = dsp_get_data (dsp);
448   - d0 = dsp_get_data (dsp);
  585 + case 0x0f:
  586 + d0 = dsp_get_data (s);
  587 + ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
  588 + d0, s->csp_regs[d0], s->csp_mode);
  589 + if (d0 == 0x83) {
  590 + ldebug ("0x83[%d] -> %#x\n",
  591 + s->csp_reg83w,
  592 + s->csp_reg83[s->csp_reg83w % 4]);
  593 + dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
  594 + s->csp_reg83w += 1;
  595 + }
  596 + else
  597 + dsp_out_data (s, s->csp_regs[d0]);
  598 + break;
449 599  
450   - save_left = dsp->left_till_irq;
451   - save_pos = dsp->dma_pos;
452   - dma_cmd (0xc0, 0, d0 + (d1 << 8));
453   - dsp->left_till_irq = save_left;
454   - dsp->dma_pos = save_pos;
  600 + case 0x10:
  601 + d0 = dsp_get_data (s);
  602 + dolog ("cmd 0x10 d0=%#x\n", d0);
  603 + break;
455 604  
456   - linfo ("set buffer size data[%d, %d] %d pos %d\n",
457   - d0, d1, dsp->dma_buffer_size, dsp->dma_pos);
458   - break;
459   - }
  605 + case 0x14:
  606 + dma_cmd8 (s, 0, dsp_get_lohi (s));
  607 + /* s->can_write = 0; */
  608 + /* qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + (ticks_per_sec * 320) / 1000000); */
  609 + break;
460 610  
461 611 case 0x40:
462   - dsp->time_const = dsp_get_data (dsp);
463   - linfo ("set time const %d\n", dsp->time_const);
  612 + s->time_const = dsp_get_data (s);
  613 + ldebug ("set time const %d\n", s->time_const);
464 614 break;
465 615  
466   - case 0x41:
467   - case 0x42:
468   - d1 = dsp_get_data (dsp);
469   - d0 = dsp_get_data (dsp);
  616 + case 0x42: /* FT2 sets output freq with this, go figure */
  617 + dolog ("cmd 0x42 might not do what it think it should\n");
470 618  
471   - dsp->freq = d1 + (d0 << 8);
472   - linfo ("set freq %#x, %#x = %d\n", d1, d0, dsp->freq);
  619 + case 0x41:
  620 + s->freq = dsp_get_hilo (s);
  621 + ldebug ("set freq %d\n", s->freq);
473 622 break;
474 623  
475 624 case 0x48:
476   - d1 = dsp_get_data (dsp);
477   - d0 = dsp_get_data (dsp);
478   - dsp->dma_buffer_size = d1 + (d0 << 8);
479   - linfo ("set dma len %#x, %#x = %d\n",
480   - d1, d0, dsp->dma_buffer_size);
  625 + s->block_size = dsp_get_lohi (s);
  626 + /* s->highspeed = 1; */
  627 + ldebug ("set dma block len %d\n", s->block_size);
  628 + break;
  629 +
  630 + case 0x80:
  631 + {
  632 + int samples, bytes;
  633 + int64_t ticks;
  634 +
  635 + if (-1 == s->freq)
  636 + s->freq = 11025;
  637 + samples = dsp_get_lohi (s);
  638 + bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
  639 + ticks = ticks_per_sec / (s->freq / bytes);
  640 + if (ticks < ticks_per_sec / 1024)
  641 + pic_set_irq (s->irq, 1);
  642 + else
  643 + qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks);
  644 + ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
  645 + }
481 646 break;
482 647  
483 648 case 0xe0:
484   - d0 = dsp_get_data (dsp);
485   - dsp->out_data_len = 0;
486   - linfo ("data = %#x\n", d0);
487   - dsp_out_data (dsp, d0 ^ 0xff);
  649 + d0 = dsp_get_data (s);
  650 + s->out_data_len = 0;
  651 + ldebug ("E0 data = %#x\n", d0);
  652 + dsp_out_data(s, ~d0);
488 653 break;
489 654  
490   - case 0xe4:
491   - dsp->test_reg = dsp_get_data (dsp);
  655 + case 0xe2:
  656 + d0 = dsp_get_data (s);
  657 + dolog ("E2 = %#x\n", d0);
492 658 break;
493 659  
  660 + case 0xe4:
  661 + s->test_reg = dsp_get_data (s);
  662 + break;
494 663  
495 664 case 0xf9:
496   - d0 = dsp_get_data (dsp);
497   - ldebug ("f9 <- %#x\n", d0);
  665 + d0 = dsp_get_data (s);
  666 + ldebug ("command 0xf9 with %#x\n", d0);
498 667 switch (d0) {
499   - case 0x0e: dsp_out_data (dsp, 0xff); break;
500   - case 0x0f: dsp_out_data (dsp, 0x07); break;
501   - case 0xf9: dsp_out_data (dsp, 0x00); break;
  668 + case 0x0e:
  669 + dsp_out_data (s, 0xff);
  670 + break;
  671 +
  672 + case 0x0f:
  673 + dsp_out_data (s, 0x07);
  674 + break;
  675 +
502 676 case 0x37:
503   - dsp_out_data (dsp, 0x38); break;
  677 + dsp_out_data (s, 0x38);
  678 + break;
  679 +
504 680 default:
505   - dsp_out_data (dsp, 0);
  681 + dsp_out_data (s, 0x00);
  682 + break;
506 683 }
507 684 break;
508 685  
509 686 default:
510   - dolog ("complete: unrecognized command %#x\n", dsp->cmd);
  687 + dolog ("complete: unrecognized command %#x\n", s->cmd);
511 688 return;
512 689 }
513 690 }
514 691  
515   - dsp->needed_bytes = 0;
516   - dsp->cmd = -1;
  692 + ldebug ("\n");
  693 + s->cmd = -1;
517 694 return;
518 695 }
519 696  
  697 +static void reset (SB16State *s)
  698 +{
  699 + pic_set_irq (s->irq, 0);
  700 + if (s->dma_auto) {
  701 + pic_set_irq (s->irq, 1);
  702 + pic_set_irq (s->irq, 0);
  703 + }
  704 +
  705 + s->mixer_regs[0x82] = 0;
  706 + s->dma_auto = 0;
  707 + s->in_index = 0;
  708 + s->out_data_len = 0;
  709 + s->left_till_irq = 0;
  710 + s->needed_bytes = 0;
  711 + s->block_size = -1;
  712 + s->nzero = 0;
  713 + s->highspeed = 0;
  714 + s->v2x6 = 0;
  715 +
  716 + dsp_out_data(s, 0xaa);
  717 + speaker (s, 0);
  718 + control (s, 0);
  719 +}
  720 +
520 721 static IO_WRITE_PROTO (dsp_write)
521 722 {
522   - SB16State *dsp = opaque;
  723 + SB16State *s = opaque;
523 724 int iport;
524 725  
525   - iport = nport - sb.port;
  726 + iport = nport - s->port;
526 727  
527   - ldebug ("dsp_write %#x <- %#x\n", nport, val);
  728 + ldebug ("write %#x <- %#x\n", nport, val);
528 729 switch (iport) {
529   - case 0x6:
530   - control (0);
531   - if (0 == val)
532   - dsp->v2x6 = 0;
533   - else if ((1 == val) && (0 == dsp->v2x6)) {
534   - dsp->v2x6 = 1;
535   - dsp->dma_pos = 0;
536   - dsp->dma_auto = 0;
537   - dsp->in_index = 0;
538   - dsp->out_data_len = 0;
539   - dsp->left_till_irq = 0;
540   - dsp->speaker = 0;
541   - dsp->needed_bytes = 0;
542   - pic_set_irq (sb.irq, 0);
543   - dsp_out_data(dsp, 0xaa);
  730 + case 0x06:
  731 + switch (val) {
  732 + case 0x00:
  733 + if (s->v2x6 == 1) {
  734 + if (0 && s->highspeed) {
  735 + s->highspeed = 0;
  736 + pic_set_irq (s->irq, 0);
  737 + control (s, 0);
  738 + }
  739 + else
  740 + reset (s);
  741 + }
  742 + s->v2x6 = 0;
  743 + break;
  744 +
  745 + case 0x01:
  746 + case 0x03: /* FreeBSD kludge */
  747 + s->v2x6 = 1;
  748 + break;
  749 +
  750 + case 0xc6:
  751 + s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
  752 + break;
  753 +
  754 + case 0xb8: /* Panic */
  755 + reset (s);
  756 + break;
  757 +
  758 + case 0x39:
  759 + dsp_out_data (s, 0x38);
  760 + reset (s);
  761 + s->v2x6 = 0x39;
  762 + break;
  763 +
  764 + default:
  765 + s->v2x6 = val;
  766 + break;
544 767 }
545   - else
546   - dsp->v2x6 = ~0;
547 768 break;
548 769  
549   - case 0xc: /* write data or command | write status */
550   - if (0 == dsp->needed_bytes) {
551   - command (dsp, val);
552   - if (0 == dsp->needed_bytes) {
553   - log_dsp (dsp);
  770 + case 0x0c: /* write data or command | write status */
  771 +/* if (s->highspeed) */
  772 +/* break; */
  773 +
  774 + if (0 == s->needed_bytes) {
  775 + command (s, val);
  776 +#if 0
  777 + if (0 == s->needed_bytes) {
  778 + log_dsp (s);
554 779 }
  780 +#endif
555 781 }
556 782 else {
557   - if (dsp->in_index == sizeof (dsp->in2_data)) {
  783 + if (s->in_index == sizeof (s->in2_data)) {
558 784 dolog ("in data overrun\n");
559 785 }
560 786 else {
561   - dsp->in2_data[dsp->in_index++] = val;
562   - if (dsp->in_index == dsp->needed_bytes) {
563   - dsp->needed_bytes = 0;
564   - complete (dsp);
565   - log_dsp (dsp);
  787 + s->in2_data[s->in_index++] = val;
  788 + if (s->in_index == s->needed_bytes) {
  789 + s->needed_bytes = 0;
  790 + complete (s);
  791 +#if 0
  792 + log_dsp (s);
  793 +#endif
  794 + }
566 795 }
567 796 }
568   - }
569 797 break;
570 798  
571 799 default:
572   - dolog ("dsp_write (nport=%#x, val=%#x)\n", nport, val);
  800 + ldebug ("(nport=%#x, val=%#x)\n", nport, val);
573 801 break;
574 802 }
575 803 }
576 804  
577 805 static IO_READ_PROTO (dsp_read)
578 806 {
579   - SB16State *dsp = opaque;
580   - int iport, retval;
  807 + SB16State *s = opaque;
  808 + int iport, retval, ack = 0;
581 809  
582   - iport = nport - sb.port;
  810 + iport = nport - s->port;
583 811  
584 812 switch (iport) {
585   - case 0x6: /* reset */
586   - control (0);
587   - retval = 0;
588   - dsp->speaker = 0;
  813 + case 0x06: /* reset */
  814 + retval = 0xff;
589 815 break;
590 816  
591   - case 0xa: /* read data */
592   - if (dsp->out_data_len) {
593   - retval = dsp->out_data[--dsp->out_data_len];
594   - dsp->last_read_byte = retval;
595   - } else {
596   - retval = dsp->last_read_byte;
  817 + case 0x0a: /* read data */
  818 + if (s->out_data_len) {
  819 + retval = s->out_data[--s->out_data_len];
  820 + s->last_read_byte = retval;
  821 + }
  822 + else {
597 823 dolog ("empty output buffer\n");
  824 + retval = s->last_read_byte;
598 825 /* goto error; */
599 826 }
600 827 break;
601 828  
602   - case 0xc: /* 0xxxxxxx can write */
603   - retval = 0;
604   - if (dsp->out_data_len == sizeof (dsp->out_data)) retval |= 0x80;
  829 + case 0x0c: /* 0 can write */
  830 + retval = s->can_write ? 0 : 0x80;
605 831 break;
606 832  
607   - case 0xd: /* timer interrupt clear */
608   - dolog ("timer interrupt clear\n");
609   - goto error;
  833 + case 0x0d: /* timer interrupt clear */
  834 + /* dolog ("timer interrupt clear\n"); */
  835 + retval = 0;
  836 + break;
610 837  
611   - case 0xe: /* data available status | irq 8 ack */
612   - /* XXX drop pic irq line here? */
613   - /* ldebug ("8 ack\n"); */
614   - retval = dsp->out_data_len ? 0x80 : 0;
615   - dsp->mixer_regs[0x82] &= ~dsp->mixer_regs[0x80];
616   - pic_set_irq (sb.irq, 0);
  838 + case 0x0e: /* data available status | irq 8 ack */
  839 + retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
  840 + if (s->mixer_regs[0x82] & 1) {
  841 + ack = 1;
  842 + s->mixer_regs[0x82] &= 1;
  843 + pic_set_irq (s->irq, 0);
  844 + }
617 845 break;
618 846  
619   - case 0xf: /* irq 16 ack */
620   - /* XXX drop pic irq line here? */
621   - ldebug ("16 ack\n");
  847 + case 0x0f: /* irq 16 ack */
622 848 retval = 0xff;
623   - dsp->mixer_regs[0x82] &= ~dsp->mixer_regs[0x80];
624   - pic_set_irq (sb.irq, 0);
  849 + if (s->mixer_regs[0x82] & 2) {
  850 + ack = 1;
  851 + s->mixer_regs[0x82] &= 2;
  852 + pic_set_irq (s->irq, 0);
  853 + }
625 854 break;
626 855  
627 856 default:
628 857 goto error;
629 858 }
630 859  
631   - if (0xe == iport) {
632   - if (0 == retval) {
633   - if (!dsp->nzero) {
634   - ldebug ("dsp_read (nport=%#x iport %#x) = %#x, %lld\n",
635   - nport, iport, retval, dsp->nzero);
636   - }
637   - dsp->nzero += 1;
638   - }
639   - else {
640   - ldebug ("dsp_read (nport=%#x iport %#x) = %#x, %lld\n",
641   - nport, iport, retval, dsp->nzero);
642   - dsp->nzero = 0;
643   - }
644   - }
645   - else {
646   - ldebug ("dsp_read (nport=%#x iport %#x) = %#x\n",
647   - nport, iport, retval);
648   - }
  860 + if (!ack)
  861 + ldebug ("read %#x -> %#x\n", nport, retval);
649 862  
650 863 return retval;
651 864  
652 865 error:
653   - printf ("dsp_read error %#x\n", nport);
  866 + dolog ("WARNING dsp_read %#x error\n", nport);
654 867 return 0xff;
655 868 }
656 869  
  870 +static void reset_mixer (SB16State *s)
  871 +{
  872 + int i;
  873 +
  874 + memset (s->mixer_regs, 0xff, 0x7f);
  875 + memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
  876 +
  877 + s->mixer_regs[0x02] = 4; /* master volume 3bits */
  878 + s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
  879 + s->mixer_regs[0x08] = 0; /* CD volume 3bits */
  880 + s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
  881 +
  882 + /* d5=input filt, d3=lowpass filt, d1,d2=input source */
  883 + s->mixer_regs[0x0c] = 0;
  884 +
  885 + /* d5=output filt, d1=stereo switch */
  886 + s->mixer_regs[0x0e] = 0;
  887 +
  888 + /* voice volume L d5,d7, R d1,d3 */
  889 + s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
  890 + /* master ... */
  891 + s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
  892 + /* MIDI ... */
  893 + s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
  894 +
  895 + for (i = 0x30; i < 0x48; i++) {
  896 + s->mixer_regs[i] = 0x20;
  897 + }
  898 +}
  899 +
657 900 static IO_WRITE_PROTO(mixer_write_indexb)
658 901 {
659   - SB16State *dsp = opaque;
660   - dsp->mixer_nreg = val;
  902 + SB16State *s = opaque;
  903 + s->mixer_nreg = val;
661 904 }
662 905  
663 906 static IO_WRITE_PROTO(mixer_write_datab)
664 907 {
665   - SB16State *dsp = opaque;
666   - int i;
  908 + SB16State *s = opaque;
  909 +
  910 + ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
  911 + if (s->mixer_nreg > sizeof (s->mixer_regs))
  912 + return;
667 913  
668   - linfo ("mixer [%#x] <- %#x\n", dsp->mixer_nreg, val);
669   - switch (dsp->mixer_nreg) {
  914 + switch (s->mixer_nreg) {
670 915 case 0x00:
671   - /* Bochs */
672   - dsp->mixer_regs[0x04] = 0xcc;
673   - dsp->mixer_regs[0x0a] = 0x00;
674   - dsp->mixer_regs[0x22] = 0xcc;
675   - dsp->mixer_regs[0x26] = 0xcc;
676   - dsp->mixer_regs[0x28] = 0x00;
677   - dsp->mixer_regs[0x2e] = 0x00;
678   - dsp->mixer_regs[0x3c] = 0x1f;
679   - dsp->mixer_regs[0x3d] = 0x15;
680   - dsp->mixer_regs[0x3e] = 0x0b;
681   -
682   - for (i = 0x30; i <= 0x35; i++)
683   - dsp->mixer_regs[i] = 0xc0;
684   -
685   - for (i = 0x36; i <= 0x3b; i++)
686   - dsp->mixer_regs[i] = 0x00;
687   -
688   - for (i = 0x3f; i <= 0x43; i++)
689   - dsp->mixer_regs[i] = 0x00;
690   -
691   - for (i = 0x44; i <= 0x47; i++)
692   - dsp->mixer_regs[i] = 0x80;
693   -
694   - for (i = 0x30; i < 0x48; i++) {
695   - dsp->mixer_regs[i] = 0x20;
696   - }
  916 + reset_mixer (s);
697 917 break;
698 918  
699   - case 0x04:
700   - case 0x0a:
701   - case 0x22:
702   - case 0x26:
703   - case 0x28:
704   - case 0x2e:
705   - case 0x30:
706   - case 0x31:
707   - case 0x32:
708   - case 0x33:
709   - case 0x34:
710   - case 0x35:
711   - case 0x36:
712   - case 0x37:
713   - case 0x38:
714   - case 0x39:
715   - case 0x3a:
716   - case 0x3b:
717   - case 0x3c:
718   - case 0x3d:
719   - case 0x3e:
720   - case 0x3f:
721   - case 0x40:
722   - case 0x41:
723   - case 0x42:
724   - case 0x43:
725   - case 0x44:
726   - case 0x45:
727   - case 0x46:
728   - case 0x47:
729 919 case 0x80:
730   - case 0x81:
  920 + {
  921 + int irq = irq_of_magic (val);
  922 + ldebug ("setting irq to %d (val=%#x)\n", irq, val);
  923 + if (irq > 0)
  924 + s->irq = irq;
  925 + }
731 926 break;
732   - default:
733   - return;
734   - }
735   - dsp->mixer_regs[dsp->mixer_nreg] = val;
736   -}
737 927  
738   -static IO_WRITE_PROTO(mpu_write)
739   -{
740   - linfo ("mpu: %#x\n", val);
741   -}
  928 + case 0x81:
  929 + {
  930 + int dma, hdma;
742 931  
743   -static IO_WRITE_PROTO(adlib_write)
744   -{
745   - linfo ("adlib: %#x\n", val);
746   -}
  932 + dma = lsbindex (val & 0xf);
  933 + hdma = lsbindex (val & 0xf0);
  934 + dolog ("attempt to set DMA register 8bit %d, 16bit %d (val=%#x)\n",
  935 + dma, hdma, val);
  936 +#if 0
  937 + s->dma = dma;
  938 + s->hdma = hdma;
  939 +#endif
  940 + }
  941 + break;
747 942  
748   -static IO_READ_PROTO(mpu_read)
749   -{
750   - linfo ("mpu read: %#x\n", nport);
751   - return 0x80;
752   -}
  943 + case 0x82:
  944 + dolog ("attempt to write into IRQ status register (val=%#x)\n",
  945 + val);
  946 + return;
753 947  
754   -static IO_READ_PROTO(adlib_read)
755   -{
756   - linfo ("adlib read: %#x\n", nport);
757   - return 0;
  948 + default:
  949 + if (s->mixer_nreg >= 0x80)
  950 + dolog ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
  951 + break;
  952 + }
  953 +
  954 + s->mixer_regs[s->mixer_nreg] = val;
758 955 }
759 956  
760 957 static IO_WRITE_PROTO(mixer_write_indexw)
... ... @@ -765,194 +962,229 @@ static IO_WRITE_PROTO(mixer_write_indexw)
765 962  
766 963 static IO_READ_PROTO(mixer_read)
767 964 {
768   - SB16State *dsp = opaque;
769   - linfo ("mixer [%#x] -> %#x\n", dsp->mixer_nreg, dsp->mixer_regs[dsp->mixer_nreg]);
770   - return dsp->mixer_regs[dsp->mixer_nreg];
771   -}
772   -
773   -void SB16_run (void)
774   -{
775   - if (0 == dsp.speaker)
776   - return;
777   -
778   - AUD_run ();
  965 + SB16State *s = opaque;
  966 + ldebug ("mixer_read[%#x] -> %#x\n",
  967 + s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
  968 + return s->mixer_regs[s->mixer_nreg];
779 969 }
780 970  
781   -static int write_audio (uint32_t addr, int len, int size)
  971 +static int write_audio (SB16State *s, int nchan, int dma_pos,
  972 + int dma_len, int len)
782 973 {
783 974 int temp, net;
784 975 uint8_t tmpbuf[4096];
785 976  
786   - temp = size;
787   -
  977 + temp = len;
788 978 net = 0;
789 979  
790 980 while (temp) {
791   - int left_till_end;
792   - int to_copy;
793   - int copied;
  981 + int left = dma_len - dma_pos;
  982 + int to_copy, copied;
794 983  
795   - left_till_end = len - dsp.dma_pos;
796   -
797   - to_copy = MIN (temp, left_till_end);
  984 + to_copy = audio_MIN (temp, left);
798 985 if (to_copy > sizeof(tmpbuf))
799 986 to_copy = sizeof(tmpbuf);
800   - cpu_physical_memory_read(addr + dsp.dma_pos, tmpbuf, to_copy);
801   - copied = AUD_write (tmpbuf, to_copy);
802 987  
803   - temp -= copied;
804   - dsp.dma_pos += copied;
805   -
806   - if (dsp.dma_pos == len) {
807   - dsp.dma_pos = 0;
808   - }
  988 + copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
  989 + copied = AUD_write (s->voice, tmpbuf, copied);
809 990  
  991 + temp -= copied;
  992 + dma_pos = (dma_pos + copied) % dma_len;
810 993 net += copied;
811 994  
812   - if (copied != to_copy)
813   - return net;
  995 + if (!copied)
  996 + break;
814 997 }
815 998  
816 999 return net;
817 1000 }
818 1001  
819   -static int SB_read_DMA (void *opaque, target_ulong addr, int size)
  1002 +static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
820 1003 {
821   - SB16State *dsp = opaque;
822   - int free, till, copy, written;
823   -
824   - if (0 == dsp->speaker)
825   - return 0;
  1004 + SB16State *s = opaque;
  1005 + int free, rfree, till, copy, written, elapsed;
826 1006  
827   - if (dsp->left_till_irq < 0) {
828   - ldebug ("left_till_irq < 0, %d, pos %d \n",
829   - dsp->left_till_irq, dsp->dma_buffer_size);
830   - dsp->left_till_irq += dsp->dma_buffer_size;
831   - return dsp->dma_pos;
  1007 + if (s->left_till_irq < 0) {
  1008 + s->left_till_irq = s->block_size;
832 1009 }
833 1010  
834   - free = AUD_get_free ();
835   -
836   - if ((free <= 0) || (0 == size)) {
837   - ldebug ("returning, since free = %d and size = %d\n", free, size);
838   - return dsp->dma_pos;
839   - }
  1011 + elapsed = AUD_calc_elapsed (s->voice);
  1012 + free = elapsed;/* AUD_get_free (s->voice); */
  1013 + rfree = free;
  1014 + free = audio_MIN (free, elapsed) & ~s->align;
840 1015  
841   - if (mix_block > 0) {
842   - copy = MIN (free, mix_block);
843   - }
844   - else {
845   - copy = free;
  1016 + if ((free <= 0) || !dma_len) {
  1017 + return dma_pos;
846 1018 }
847 1019  
848   - till = dsp->left_till_irq;
  1020 + copy = free;
  1021 + till = s->left_till_irq;
849 1022  
850 1023 #ifdef DEBUG_SB16_MOST
851   - ldebug ("addr:%#010x free:%d till:%d size:%d\n",
852   - addr, free, till, size);
  1024 + dolog ("pos:%06d free:%d,%d till:%d len:%d\n",
  1025 + dma_pos, free, AUD_get_free (s->voice), till, dma_len);
853 1026 #endif
854 1027  
855 1028 if (till <= copy) {
856   - if (0 == dsp->dma_auto) {
  1029 + if (0 == s->dma_auto) {
857 1030 copy = till;
858 1031 }
859 1032 }
860 1033  
861   - written = write_audio (addr, size, copy);
862   - dsp->left_till_irq -= written;
863   - AUD_adjust_estimate (free - written);
  1034 + written = write_audio (s, nchan, dma_pos, dma_len, copy);
  1035 + dma_pos = (dma_pos + written) % dma_len;
  1036 + s->left_till_irq -= written;
864 1037  
865   - if (dsp->left_till_irq <= 0) {
866   - dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
867   - if (0 == noirq) {
868   - ldebug ("request irq pos %d, left %d\n",
869   - dsp->dma_pos, dsp->left_till_irq);
870   - pic_set_irq(sb.irq, 1);
871   - }
872   -
873   - if (0 == dsp->dma_auto) {
874   - control (0);
  1038 + if (s->left_till_irq <= 0) {
  1039 + s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
  1040 + pic_set_irq (s->irq, 1);
  1041 + if (0 == s->dma_auto) {
  1042 + control (s, 0);
  1043 + speaker (s, 0);
875 1044 }
876 1045 }
877 1046  
878 1047 #ifdef DEBUG_SB16_MOST
879 1048 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",
880   - dsp->dma_pos, free, size, dsp->left_till_irq, copy,
881   - dsp->dma_buffer_size);
  1049 + dma_pos, free, dma_len, s->left_till_irq, copy, s->block_size);
882 1050 #endif
883 1051  
884   - if (dsp->left_till_irq <= 0) {
885   - dsp->left_till_irq += dsp->dma_buffer_size;
  1052 + while (s->left_till_irq <= 0) {
  1053 + s->left_till_irq = s->block_size + s->left_till_irq;
886 1054 }
887 1055  
888   - return dsp->dma_pos;
889   -}
890   -
891   -static int magic_of_irq (int irq)
892   -{
893   - switch (irq) {
894   - case 2:
895   - return 1;
896   - case 5:
897   - return 2;
898   - case 7:
899   - return 4;
900   - case 10:
901   - return 8;
902   - default:
903   - dolog ("bad irq %d\n", irq);
904   - return 2;
905   - }
  1056 + AUD_adjust (s->voice, written);
  1057 + return dma_pos;
906 1058 }
907 1059  
908   -#if 0
909   -static int irq_of_magic (int magic)
  1060 +void SB_timer (void *opaque)
910 1061 {
911   - switch (magic) {
912   - case 1:
913   - return 2;
914   - case 2:
915   - return 5;
916   - case 4:
917   - return 7;
918   - case 8:
919   - return 10;
920   - default:
921   - dolog ("bad irq magic %d\n", magic);
922   - return 2;
923   - }
  1062 + SB16State *s = opaque;
  1063 + AUD_run ();
  1064 + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
924 1065 }
925   -#endif
926 1066  
927   -#ifdef SB16_TRAP_ALL
928   -static IO_READ_PROTO (trap_read)
  1067 +static void SB_save (QEMUFile *f, void *opaque)
929 1068 {
930   - switch (nport) {
931   - case 0x220:
932   - return 0;
933   - case 0x226:
934   - case 0x22a:
935   - case 0x22c:
936   - case 0x22d:
937   - case 0x22e:
938   - case 0x22f:
939   - return dsp_read (opaque, nport);
940   - }
941   - linfo ("trap_read: %#x\n", nport);
942   - return 0xff;
  1069 + SB16State *s = opaque;
  1070 +
  1071 + qemu_put_be32s (f, &s->irq);
  1072 + qemu_put_be32s (f, &s->dma);
  1073 + qemu_put_be32s (f, &s->hdma);
  1074 + qemu_put_be32s (f, &s->port);
  1075 + qemu_put_be32s (f, &s->ver);
  1076 + qemu_put_be32s (f, &s->in_index);
  1077 + qemu_put_be32s (f, &s->out_data_len);
  1078 + qemu_put_be32s (f, &s->fmt_stereo);
  1079 + qemu_put_be32s (f, &s->fmt_signed);
  1080 + qemu_put_be32s (f, &s->fmt_bits);
  1081 + qemu_put_be32s (f, &s->fmt);
  1082 + qemu_put_be32s (f, &s->dma_auto);
  1083 + qemu_put_be32s (f, &s->block_size);
  1084 + qemu_put_be32s (f, &s->fifo);
  1085 + qemu_put_be32s (f, &s->freq);
  1086 + qemu_put_be32s (f, &s->time_const);
  1087 + qemu_put_be32s (f, &s->speaker);
  1088 + qemu_put_be32s (f, &s->needed_bytes);
  1089 + qemu_put_be32s (f, &s->cmd);
  1090 + qemu_put_be32s (f, &s->use_hdma);
  1091 + qemu_put_be32s (f, &s->highspeed);
  1092 + qemu_put_be32s (f, &s->can_write);
  1093 + qemu_put_be32s (f, &s->v2x6);
  1094 +
  1095 + qemu_put_8s (f, &s->csp_param);
  1096 + qemu_put_8s (f, &s->csp_value);
  1097 + qemu_put_8s (f, &s->csp_mode);
  1098 + qemu_put_8s (f, &s->csp_param);
  1099 + qemu_put_buffer (f, s->csp_regs, 256);
  1100 + qemu_put_8s (f, &s->csp_index);
  1101 + qemu_put_buffer (f, s->csp_reg83, 4);
  1102 + qemu_put_be32s (f, &s->csp_reg83r);
  1103 + qemu_put_be32s (f, &s->csp_reg83w);
  1104 +
  1105 + qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
  1106 + qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
  1107 + qemu_put_8s (f, &s->test_reg);
  1108 + qemu_put_8s (f, &s->last_read_byte);
  1109 +
  1110 + qemu_put_be32s (f, &s->nzero);
  1111 + qemu_put_be32s (f, &s->left_till_irq);
  1112 + qemu_put_be32s (f, &s->dma_running);
  1113 + qemu_put_be32s (f, &s->bytes_per_second);
  1114 + qemu_put_be32s (f, &s->align);
  1115 +
  1116 + qemu_put_be32s (f, &s->mixer_nreg);
  1117 + qemu_put_buffer (f, s->mixer_regs, 256);
943 1118 }
944 1119  
945   -static IO_WRITE_PROTO (trap_write)
  1120 +static int SB_load (QEMUFile *f, void *opaque, int version_id)
946 1121 {
947   - switch (nport) {
948   - case 0x226:
949   - case 0x22c:
950   - dsp_write (opaque, nport, val);
951   - return;
  1122 + SB16State *s = opaque;
  1123 +
  1124 + if (version_id != 1)
  1125 + return -EINVAL;
  1126 +
  1127 + qemu_get_be32s (f, &s->irq);
  1128 + qemu_get_be32s (f, &s->dma);
  1129 + qemu_get_be32s (f, &s->hdma);
  1130 + qemu_get_be32s (f, &s->port);
  1131 + qemu_get_be32s (f, &s->ver);
  1132 + qemu_get_be32s (f, &s->in_index);
  1133 + qemu_get_be32s (f, &s->out_data_len);
  1134 + qemu_get_be32s (f, &s->fmt_stereo);
  1135 + qemu_get_be32s (f, &s->fmt_signed);
  1136 + qemu_get_be32s (f, &s->fmt_bits);
  1137 + qemu_get_be32s (f, &s->fmt);
  1138 + qemu_get_be32s (f, &s->dma_auto);
  1139 + qemu_get_be32s (f, &s->block_size);
  1140 + qemu_get_be32s (f, &s->fifo);
  1141 + qemu_get_be32s (f, &s->freq);
  1142 + qemu_get_be32s (f, &s->time_const);
  1143 + qemu_get_be32s (f, &s->speaker);
  1144 + qemu_get_be32s (f, &s->needed_bytes);
  1145 + qemu_get_be32s (f, &s->cmd);
  1146 + qemu_get_be32s (f, &s->use_hdma);
  1147 + qemu_get_be32s (f, &s->highspeed);
  1148 + qemu_get_be32s (f, &s->can_write);
  1149 + qemu_get_be32s (f, &s->v2x6);
  1150 +
  1151 + qemu_get_8s (f, &s->csp_param);
  1152 + qemu_get_8s (f, &s->csp_value);
  1153 + qemu_get_8s (f, &s->csp_mode);
  1154 + qemu_get_8s (f, &s->csp_param);
  1155 + qemu_get_buffer (f, s->csp_regs, 256);
  1156 + qemu_get_8s (f, &s->csp_index);
  1157 + qemu_get_buffer (f, s->csp_reg83, 4);
  1158 + qemu_get_be32s (f, &s->csp_reg83r);
  1159 + qemu_get_be32s (f, &s->csp_reg83w);
  1160 +
  1161 + qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
  1162 + qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
  1163 + qemu_get_8s (f, &s->test_reg);
  1164 + qemu_get_8s (f, &s->last_read_byte);
  1165 +
  1166 + qemu_get_be32s (f, &s->nzero);
  1167 + qemu_get_be32s (f, &s->left_till_irq);
  1168 + qemu_get_be32s (f, &s->dma_running);
  1169 + qemu_get_be32s (f, &s->bytes_per_second);
  1170 + qemu_get_be32s (f, &s->align);
  1171 +
  1172 + qemu_get_be32s (f, &s->mixer_nreg);
  1173 + qemu_get_buffer (f, s->mixer_regs, 256);
  1174 +
  1175 + if (s->voice)
  1176 + AUD_reset (s->voice);
  1177 +
  1178 + if (s->dma_running) {
  1179 + if (s->freq)
  1180 + s->voice = AUD_open (s->voice, "sb16", s->freq,
  1181 + 1 << s->fmt_stereo, s->fmt);
  1182 +
  1183 + control (s, 1);
  1184 + speaker (s, s->speaker);
952 1185 }
953   - linfo ("trap_write: %#x = %#x\n", nport, val);
  1186 + return 0;
954 1187 }
955   -#endif
956 1188  
957 1189 void SB16_init (void)
958 1190 {
... ... @@ -961,47 +1193,45 @@ void SB16_init (void)
961 1193 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
962 1194 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
963 1195  
964   - memset(s->mixer_regs, 0xff, sizeof(s->mixer_regs));
  1196 + s->ts = qemu_new_timer (vm_clock, SB_timer, s);
  1197 + if (!s->ts)
  1198 + return;
  1199 +
  1200 + s->irq = conf.irq;
  1201 + s->dma = conf.dma;
  1202 + s->hdma = conf.hdma;
  1203 + s->port = conf.port;
  1204 + s->ver = conf.ver_lo | (conf.ver_hi << 8);
965 1205  
966   - s->mixer_regs[0x00] = 0;
967   - s->mixer_regs[0x0e] = ~0;
968   - s->mixer_regs[0x80] = magic_of_irq (sb.irq);
969   - s->mixer_regs[0x81] = 0x80 | 0x10 | (sb.dma << 1);
970   - s->mixer_regs[0x82] = 0;
971   - s->mixer_regs[0xfd] = 16; /* bochs */
972   - s->mixer_regs[0xfe] = 6; /* bochs */
973   - mixer_write_indexw (s, 0x224, 0);
974   -
975   -#ifdef SB16_TRAP_ALL
976   - for (i = 0; i < 0x100; i++) {
977   - if (i != 4 && i != 5) {
978   - register_ioport_write (sb.port + i, 1, 1, trap_write, s);
979   - register_ioport_read (sb.port + i, 1, 1, trap_read, s);
980   - }
981   - }
982   -#else
  1206 + s->mixer_regs[0x80] = magic_of_irq (s->irq);
  1207 + s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
  1208 + s->mixer_regs[0x82] = 2 << 5;
  1209 +
  1210 + s->csp_regs[5] = 1;
  1211 + s->csp_regs[9] = 0xf8;
  1212 +
  1213 + reset_mixer (s);
  1214 + s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
  1215 + if (!s->aux_ts)
  1216 + return;
983 1217  
984 1218 for (i = 0; i < LENOFA (dsp_write_ports); i++) {
985   - register_ioport_write (sb.port + dsp_write_ports[i], 1, 1, dsp_write, s);
  1219 + register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
986 1220 }
987 1221  
988 1222 for (i = 0; i < LENOFA (dsp_read_ports); i++) {
989   - register_ioport_read (sb.port + dsp_read_ports[i], 1, 1, dsp_read, s);
  1223 + register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
990 1224 }
991   -#endif
992 1225  
993   - register_ioport_write (sb.port + 0x4, 1, 1, mixer_write_indexb, s);
994   - register_ioport_write (sb.port + 0x4, 1, 2, mixer_write_indexw, s);
995   - register_ioport_read (sb.port + 0x5, 1, 1, mixer_read, s);
996   - register_ioport_write (sb.port + 0x5, 1, 1, mixer_write_datab, s);
  1226 + register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
  1227 + register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
  1228 + register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
  1229 + register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
997 1230  
998   - for (i = 0; 4 < 4; i++) {
999   - register_ioport_read (0x330 + i, 1, 1, mpu_read, s);
1000   - register_ioport_write (0x330 + i, 1, 1, mpu_write, s);
1001   - register_ioport_read (0x388 + i, 1, 1, adlib_read, s);
1002   - register_ioport_write (0x388 + i, 1, 1, adlib_write, s);
1003   - }
  1231 + DMA_register_channel (s->hdma, SB_read_DMA, s);
  1232 + DMA_register_channel (s->dma, SB_read_DMA, s);
  1233 + s->can_write = 1;
1004 1234  
1005   - DMA_register_channel (sb.hdma, SB_read_DMA, s);
1006   - DMA_register_channel (sb.dma, SB_read_DMA, s);
  1235 + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
  1236 + register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1007 1237 }
... ...
oss.c deleted 100644 → 0
1   -/*
2   - * QEMU OSS Audio output driver
3   - *
4   - * Copyright (c) 2003 Vassili Karpov (malc)
5   - *
6   - * Permission is hereby granted, free of charge, to any person obtaining a copy
7   - * of this software and associated documentation files (the "Software"), to deal
8   - * in the Software without restriction, including without limitation the rights
9   - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10   - * copies of the Software, and to permit persons to whom the Software is
11   - * furnished to do so, subject to the following conditions:
12   - *
13   - * The above copyright notice and this permission notice shall be included in
14   - * all copies or substantial portions of the Software.
15   - *
16   - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19   - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22   - * THE SOFTWARE.
23   - */
24   -#include "vl.h"
25   -
26   -#include <stdio.h>
27   -#include <limits.h>
28   -#include <stdlib.h>
29   -#include <string.h>
30   -
31   -/* TODO: Graceful error handling */
32   -
33   -#if defined(_WIN32)
34   -#define USE_SDL_AUDIO
35   -#endif
36   -
37   -#define MIN(a, b) ((a)>(b)?(b):(a))
38   -#define MAX(a, b) ((a)<(b)?(b):(a))
39   -
40   -#define DEREF(x) (void)x
41   -#define dolog(...) fprintf (stderr, "audio: " __VA_ARGS__)
42   -#define ERRFail(...) do { \
43   - int _errno = errno; \
44   - fprintf (stderr, "audio: " __VA_ARGS__); \
45   - fprintf (stderr, "\nsystem error: %s\n", strerror (_errno)); \
46   - abort (); \
47   -} while (0)
48   -#define Fail(...) do { \
49   - fprintf (stderr, "audio: " __VA_ARGS__); \
50   - fprintf (stderr, "\n"); \
51   - abort (); \
52   -} while (0)
53   -
54   -#ifdef DEBUG_AUDIO
55   -#define lwarn(...) fprintf (stderr, "audio: " __VA_ARGS__)
56   -#define linfo(...) fprintf (stderr, "audio: " __VA_ARGS__)
57   -#define ldebug(...) fprintf (stderr, "audio: " __VA_ARGS__)
58   -#else
59   -#define lwarn(...)
60   -#define linfo(...)
61   -#define ldebug(...)
62   -#endif
63   -
64   -static int get_conf_val (const char *key, int defval)
65   -{
66   - int val = defval;
67   - char *strval;
68   -
69   - strval = getenv (key);
70   - if (strval) {
71   - val = atoi (strval);
72   - }
73   -
74   - return val;
75   -}
76   -
77   -static void copy_no_conversion (void *dst, void *src, int size)
78   -{
79   - memcpy (dst, src, size);
80   -}
81   -
82   -static void copy_u16_to_s16 (void *dst, void *src, int size)
83   -{
84   - int i;
85   - uint16_t *out, *in;
86   -
87   - out = dst;
88   - in = src;
89   -
90   - for (i = 0; i < size / 2; i++) {
91   - out[i] = in[i] + 0x8000;
92   - }
93   -}
94   -
95   -#ifdef USE_SDL_AUDIO
96   -#include <SDL/SDL.h>
97   -#include <SDL/SDL_thread.h>
98   -
99   -static struct {
100   - int samples;
101   -} conf = {
102   - .samples = 4096
103   -};
104   -
105   -typedef struct AudioState {
106   - int freq;
107   - int bits16;
108   - int nchannels;
109   - int rpos;
110   - int wpos;
111   - volatile int live;
112   - volatile int exit;
113   - int bytes_per_second;
114   - Uint8 *buf;
115   - int bufsize;
116   - int leftover;
117   - uint64_t old_ticks;
118   - SDL_AudioSpec spec;
119   - SDL_mutex *mutex;
120   - SDL_sem *sem;
121   - void (*copy_fn)(void *, void *, int);
122   -} AudioState;
123   -
124   -static AudioState sdl_audio;
125   -
126   -void AUD_run (void)
127   -{
128   -}
129   -
130   -static void own (AudioState *s)
131   -{
132   - /* SDL_LockAudio (); */
133   - if (SDL_mutexP (s->mutex))
134   - dolog ("SDL_mutexP: %s\n", SDL_GetError ());
135   -}
136   -
137   -static void disown (AudioState *s)
138   -{
139   - /* SDL_UnlockAudio (); */
140   - if (SDL_mutexV (s->mutex))
141   - dolog ("SDL_mutexV: %s\n", SDL_GetError ());
142   -}
143   -
144   -static void sem_wait (AudioState *s)
145   -{
146   - if (SDL_SemWait (s->sem))
147   - dolog ("SDL_SemWait: %s\n", SDL_GetError ());
148   -}
149   -
150   -static void sem_post (AudioState *s)
151   -{
152   - if (SDL_SemPost (s->sem))
153   - dolog ("SDL_SemPost: %s\n", SDL_GetError ());
154   -}
155   -
156   -static void audio_callback (void *data, Uint8 *stream, int len)
157   -{
158   - int to_mix;
159   - AudioState *s = data;
160   -
161   - if (s->exit) return;
162   - while (len) {
163   - sem_wait (s);
164   - if (s->exit) return;
165   - own (s);
166   - to_mix = MIN (len, s->live);
167   - len -= to_mix;
168   - /* printf ("to_mix=%d len=%d live=%d\n", to_mix, len, s->live); */
169   - while (to_mix) {
170   - int chunk = MIN (to_mix, s->bufsize - s->rpos);
171   - /* SDL_MixAudio (stream, buf, chunk, SDL_MIX_MAXVOLUME); */
172   - memcpy (stream, s->buf + s->rpos, chunk);
173   -
174   - s->rpos += chunk;
175   - s->live -= chunk;
176   -
177   - stream += chunk;
178   - to_mix -= chunk;
179   -
180   - if (s->rpos == s->bufsize) s->rpos = 0;
181   - }
182   - disown (s);
183   - }
184   -}
185   -
186   -static void sem_zero (AudioState *s)
187   -{
188   - int res;
189   -
190   - do {
191   - res = SDL_SemTryWait (s->sem);
192   - if (res < 0) {
193   - dolog ("SDL_SemTryWait: %s\n", SDL_GetError ());
194   - return;
195   - }
196   - } while (res != SDL_MUTEX_TIMEDOUT);
197   -}
198   -
199   -static void do_open (AudioState *s)
200   -{
201   - int status;
202   - SDL_AudioSpec obtained;
203   -
204   - SDL_PauseAudio (1);
205   - if (s->buf) {
206   - s->exit = 1;
207   - sem_post (s);
208   - SDL_CloseAudio ();
209   - s->exit = 0;
210   - qemu_free (s->buf);
211   - s->buf = NULL;
212   - sem_zero (s);
213   - }
214   -
215   - s->bytes_per_second = (s->spec.freq << (s->spec.channels >> 1)) << s->bits16;
216   - s->spec.samples = conf.samples;
217   - s->spec.userdata = s;
218   - s->spec.callback = audio_callback;
219   -
220   - status = SDL_OpenAudio (&s->spec, &obtained);
221   - if (status < 0) {
222   - dolog ("SDL_OpenAudio: %s\n", SDL_GetError ());
223   - goto exit;
224   - }
225   -
226   - if (obtained.freq != s->spec.freq ||
227   - obtained.channels != s->spec.channels ||
228   - obtained.format != s->spec.format) {
229   - dolog ("Audio spec mismatch requested obtained\n"
230   - "freq %5d %5d\n"
231   - "channels %5d %5d\n"
232   - "fmt %5d %5d\n",
233   - s->spec.freq, obtained.freq,
234   - s->spec.channels, obtained.channels,
235   - s->spec.format, obtained.format
236   - );
237   - }
238   -
239   - s->bufsize = obtained.size;
240   - s->buf = qemu_mallocz (s->bufsize);
241   - if (!s->buf) {
242   - dolog ("qemu_mallocz(%d)\n", s->bufsize);
243   - goto exit;
244   - }
245   - SDL_PauseAudio (0);
246   -
247   -exit:
248   - s->rpos = 0;
249   - s->wpos = 0;
250   - s->live = 0;
251   -}
252   -
253   -int AUD_write (void *in_buf, int size)
254   -{
255   - AudioState *s = &sdl_audio;
256   - int to_copy, temp;
257   - uint8_t *in, *out;
258   -
259   - own (s);
260   - to_copy = MIN (s->bufsize - s->live, size);
261   -
262   - temp = to_copy;
263   -
264   - in = in_buf;
265   - out = s->buf;
266   -
267   - while (temp) {
268   - int copy;
269   -
270   - copy = MIN (temp, s->bufsize - s->wpos);
271   - s->copy_fn (out + s->wpos, in, copy);
272   -
273   - s->wpos += copy;
274   - if (s->wpos == s->bufsize) {
275   - s->wpos = 0;
276   - }
277   -
278   - temp -= copy;
279   - in += copy;
280   - s->live += copy;
281   - }
282   -
283   - disown (s);
284   - sem_post (s);
285   - return to_copy;
286   -}
287   -
288   -static void maybe_open (AudioState *s, int req_freq, int req_nchannels,
289   - audfmt_e req_fmt, int force_open)
290   -{
291   - int sdl_fmt, bits16;
292   -
293   - switch (req_fmt) {
294   - case AUD_FMT_U8:
295   - bits16 = 0;
296   - sdl_fmt = AUDIO_U8;
297   - s->copy_fn = copy_no_conversion;
298   - break;
299   -
300   - case AUD_FMT_S8:
301   - fprintf (stderr, "audio: can not play 8bit signed\n");
302   - return;
303   -
304   - case AUD_FMT_S16:
305   - bits16 = 1;
306   - sdl_fmt = AUDIO_S16;
307   - s->copy_fn = copy_no_conversion;
308   - break;
309   -
310   - case AUD_FMT_U16:
311   - bits16 = 1;
312   - sdl_fmt = AUDIO_S16;
313   - s->copy_fn = copy_u16_to_s16;
314   - break;
315   -
316   - default:
317   - abort ();
318   - }
319   -
320   - if (force_open
321   - || (NULL == s->buf)
322   - || (sdl_fmt != s->spec.format)
323   - || (req_nchannels != s->spec.channels)
324   - || (req_freq != s->spec.freq)
325   - || (bits16 != s->bits16)) {
326   -
327   - s->spec.format = sdl_fmt;
328   - s->spec.channels = req_nchannels;
329   - s->spec.freq = req_freq;
330   - s->bits16 = bits16;
331   - do_open (s);
332   - }
333   -}
334   -
335   -void AUD_reset (int req_freq, int req_nchannels, audfmt_e req_fmt)
336   -{
337   - AudioState *s = &sdl_audio;
338   - own (s);
339   - maybe_open (s, req_freq, req_nchannels, req_fmt, 0);
340   - disown (s);
341   -}
342   -
343   -void AUD_open (int req_freq, int req_nchannels, audfmt_e req_fmt)
344   -{
345   - AudioState *s = &sdl_audio;
346   - own (s);
347   - maybe_open (s, req_freq, req_nchannels, req_fmt, 1);
348   - disown (s);
349   -}
350   -
351   -void AUD_adjust_estimate (int leftover)
352   -{
353   - AudioState *s = &sdl_audio;
354   - own (s);
355   - s->leftover = leftover;
356   - disown (s);
357   -}
358   -
359   -int AUD_get_free (void)
360   -{
361   - int free, elapsed;
362   - uint64_t ticks, delta;
363   - uint64_t ua_elapsed;
364   - uint64_t al_elapsed;
365   - AudioState *s = &sdl_audio;
366   -
367   - own (s);
368   - free = s->bufsize - s->live;
369   -
370   - if (0 == free) {
371   - disown (s);
372   - return 0;
373   - }
374   -
375   - elapsed = free;
376   - ticks = qemu_get_clock(rt_clock);
377   - delta = ticks - s->old_ticks;
378   - s->old_ticks = ticks;
379   -
380   - ua_elapsed = (delta * s->bytes_per_second) / 1000;
381   - al_elapsed = ua_elapsed & ~3ULL;
382   -
383   - ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
384   -
385   - if (al_elapsed > (uint64_t) INT_MAX)
386   - elapsed = INT_MAX;
387   - else
388   - elapsed = al_elapsed;
389   -
390   - elapsed += s->leftover;
391   - disown (s);
392   -
393   - if (elapsed > free) {
394   - lwarn ("audio can not keep up elapsed %d free %d\n", elapsed, free);
395   - return free;
396   - }
397   - else {
398   - return elapsed;
399   - }
400   -}
401   -
402   -int AUD_get_live (void)
403   -{
404   - int live;
405   - AudioState *s = &sdl_audio;
406   -
407   - own (s);
408   - live = s->live;
409   - disown (s);
410   - return live;
411   -}
412   -
413   -int AUD_get_buffer_size (void)
414   -{
415   - int bufsize;
416   - AudioState *s = &sdl_audio;
417   -
418   - own (s);
419   - bufsize = s->bufsize;
420   - disown (s);
421   - return bufsize;
422   -}
423   -
424   -#define QC_SDL_NSAMPLES "QEMU_SDL_NSAMPLES"
425   -
426   -static void cleanup (void)
427   -{
428   - AudioState *s = &sdl_audio;
429   - own (s);
430   - s->exit = 1;
431   - sem_post (s);
432   - disown (s);
433   -}
434   -
435   -void AUD_init (void)
436   -{
437   - AudioState *s = &sdl_audio;
438   -
439   - atexit (cleanup);
440   - SDL_InitSubSystem (SDL_INIT_AUDIO);
441   - s->mutex = SDL_CreateMutex ();
442   - if (!s->mutex) {
443   - dolog ("SDL_CreateMutex: %s\n", SDL_GetError ());
444   - return;
445   - }
446   -
447   - s->sem = SDL_CreateSemaphore (0);
448   - if (!s->sem) {
449   - dolog ("SDL_CreateSemaphore: %s\n", SDL_GetError ());
450   - return;
451   - }
452   -
453   - conf.samples = get_conf_val (QC_SDL_NSAMPLES, conf.samples);
454   -}
455   -
456   -#elif !defined(_WIN32) && !defined(__APPLE__)
457   -
458   -#include <fcntl.h>
459   -#include <errno.h>
460   -#include <unistd.h>
461   -#include <sys/mman.h>
462   -#include <sys/types.h>
463   -#include <sys/ioctl.h>
464   -#include <sys/soundcard.h>
465   -
466   -/* http://www.df.lth.se/~john_e/gems/gem002d.html */
467   -/* http://www.multi-platforms.com/Tips/PopCount.htm */
468   -static inline uint32_t popcount (uint32_t u)
469   -{
470   - u = ((u&0x55555555) + ((u>>1)&0x55555555));
471   - u = ((u&0x33333333) + ((u>>2)&0x33333333));
472   - u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
473   - u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
474   - u = ( u&0x0000ffff) + (u>>16);
475   - return u;
476   -}
477   -
478   -static inline uint32_t lsbindex (uint32_t u)
479   -{
480   - return popcount ((u&-u)-1);
481   -}
482   -
483   -#define IOCTL(args) do { \
484   - int ret = ioctl args; \
485   - if (-1 == ret) { \
486   - ERRFail (#args); \
487   - } \
488   - ldebug ("ioctl " #args " = %d\n", ret); \
489   -} while (0)
490   -
491   -typedef struct AudioState {
492   - int fd;
493   - int freq;
494   - int bits16;
495   - int nchannels;
496   - int rpos;
497   - int wpos;
498   - int live;
499   - int oss_fmt;
500   - int bytes_per_second;
501   - int is_mapped;
502   - void *buf;
503   - int bufsize;
504   - int nfrags;
505   - int fragsize;
506   - int old_optr;
507   - int leftover;
508   - uint64_t old_ticks;
509   - void (*copy_fn)(void *, void *, int);
510   -} AudioState;
511   -
512   -static AudioState oss_audio = { .fd = -1 };
513   -
514   -static struct {
515   - int try_mmap;
516   - int nfrags;
517   - int fragsize;
518   -} conf = {
519   - .try_mmap = 0,
520   - .nfrags = 4,
521   - .fragsize = 4096
522   -};
523   -
524   -static enum {DONT, DSP, TID} est = DONT;
525   -
526   -static void pab (AudioState *s, struct audio_buf_info *abinfo)
527   -{
528   - DEREF (abinfo);
529   -
530   - ldebug ("fragments %d, fragstotal %d, fragsize %d, bytes %d\n"
531   - "rpos %d, wpos %d, live %d\n",
532   - abinfo->fragments,
533   - abinfo->fragstotal,
534   - abinfo->fragsize,
535   - abinfo->bytes,
536   - s->rpos, s->wpos, s->live);
537   -}
538   -
539   -static void do_open (AudioState *s)
540   -{
541   - int mmmmssss;
542   - audio_buf_info abinfo;
543   - int fmt, freq, nchannels;
544   -
545   - if (s->buf) {
546   - if (s->is_mapped) {
547   - if (-1 == munmap (s->buf, s->bufsize)) {
548   - ERRFail ("failed to unmap audio buffer %p %d",
549   - s->buf, s->bufsize);
550   - }
551   - }
552   - else {
553   - qemu_free (s->buf);
554   - }
555   - s->buf = NULL;
556   - }
557   -
558   - if (-1 != s->fd)
559   - close (s->fd);
560   -
561   - s->fd = open ("/dev/dsp", O_RDWR | O_NONBLOCK);
562   - if (-1 == s->fd) {
563   - ERRFail ("can not open /dev/dsp");
564   - }
565   -
566   - fmt = s->oss_fmt;
567   - freq = s->freq;
568   - nchannels = s->nchannels;
569   -
570   - IOCTL ((s->fd, SNDCTL_DSP_RESET, 1));
571   - IOCTL ((s->fd, SNDCTL_DSP_SAMPLESIZE, &fmt));
572   - IOCTL ((s->fd, SNDCTL_DSP_CHANNELS, &nchannels));
573   - IOCTL ((s->fd, SNDCTL_DSP_SPEED, &freq));
574   - IOCTL ((s->fd, SNDCTL_DSP_NONBLOCK));
575   -
576   - mmmmssss = (conf.nfrags << 16) | conf.fragsize;
577   - IOCTL ((s->fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss));
578   -
579   - if ((s->oss_fmt != fmt)
580   - || (s->nchannels != nchannels)
581   - || (s->freq != freq)) {
582   - Fail ("failed to set audio parameters\n"
583   - "parameter | requested value | obtained value\n"
584   - "format | %10d | %10d\n"
585   - "channels | %10d | %10d\n"
586   - "frequency | %10d | %10d\n",
587   - s->oss_fmt, fmt,
588   - s->nchannels, nchannels,
589   - s->freq, freq);
590   - }
591   -
592   - IOCTL ((s->fd, SNDCTL_DSP_GETOSPACE, &abinfo));
593   -
594   - s->nfrags = abinfo.fragstotal;
595   - s->fragsize = abinfo.fragsize;
596   - s->bufsize = s->nfrags * s->fragsize;
597   - s->old_optr = 0;
598   -
599   - s->bytes_per_second = (freq << (nchannels >> 1)) << s->bits16;
600   -
601   - linfo ("bytes per second %d\n", s->bytes_per_second);
602   -
603   - linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n",
604   - abinfo.fragments,
605   - abinfo.fragstotal,
606   - abinfo.fragsize,
607   - abinfo.bytes,
608   - s->bufsize);
609   -
610   - s->buf = MAP_FAILED;
611   - s->is_mapped = 0;
612   -
613   - if (conf.try_mmap) {
614   - s->buf = mmap (NULL, s->bufsize, PROT_WRITE, MAP_SHARED, s->fd, 0);
615   - if (MAP_FAILED == s->buf) {
616   - int err;
617   -
618   - err = errno;
619   - dolog ("failed to mmap audio, size %d, fd %d\n"
620   - "syserr: %s\n",
621   - s->bufsize, s->fd, strerror (err));
622   - }
623   - else {
624   - est = TID;
625   - s->is_mapped = 1;
626   - }
627   - }
628   -
629   - if (MAP_FAILED == s->buf) {
630   - est = TID;
631   - s->buf = qemu_mallocz (s->bufsize);
632   - if (!s->buf) {
633   - ERRFail ("audio buf malloc failed, size %d", s->bufsize);
634   - }
635   - }
636   -
637   - s->rpos = 0;
638   - s->wpos = 0;
639   - s->live = 0;
640   -
641   - if (s->is_mapped) {
642   - int trig;
643   -
644   - trig = 0;
645   - IOCTL ((s->fd, SNDCTL_DSP_SETTRIGGER, &trig));
646   - trig = PCM_ENABLE_OUTPUT;
647   - IOCTL ((s->fd, SNDCTL_DSP_SETTRIGGER, &trig));
648   - }
649   -}
650   -
651   -static void maybe_open (AudioState *s, int req_freq, int req_nchannels,
652   - audfmt_e req_fmt, int force_open)
653   -{
654   - int oss_fmt, bits16;
655   -
656   - switch (req_fmt) {
657   - case AUD_FMT_U8:
658   - bits16 = 0;
659   - oss_fmt = AFMT_U8;
660   - s->copy_fn = copy_no_conversion;
661   - break;
662   -
663   - case AUD_FMT_S8:
664   - Fail ("can not play 8bit signed");
665   -
666   - case AUD_FMT_S16:
667   - bits16 = 1;
668   - oss_fmt = AFMT_S16_LE;
669   - s->copy_fn = copy_no_conversion;
670   - break;
671   -
672   - case AUD_FMT_U16:
673   - bits16 = 1;
674   - oss_fmt = AFMT_S16_LE;
675   - s->copy_fn = copy_u16_to_s16;
676   - break;
677   -
678   - default:
679   - abort ();
680   - }
681   -
682   - if (force_open
683   - || (-1 == s->fd)
684   - || (oss_fmt != s->oss_fmt)
685   - || (req_nchannels != s->nchannels)
686   - || (req_freq != s->freq)
687   - || (bits16 != s->bits16)) {
688   - s->oss_fmt = oss_fmt;
689   - s->nchannels = req_nchannels;
690   - s->freq = req_freq;
691   - s->bits16 = bits16;
692   - do_open (s);
693   - }
694   -}
695   -
696   -void AUD_reset (int req_freq, int req_nchannels, audfmt_e req_fmt)
697   -{
698   - AudioState *s = &oss_audio;
699   - maybe_open (s, req_freq, req_nchannels, req_fmt, 0);
700   -}
701   -
702   -void AUD_open (int req_freq, int req_nchannels, audfmt_e req_fmt)
703   -{
704   - AudioState *s = &oss_audio;
705   - maybe_open (s, req_freq, req_nchannels, req_fmt, 1);
706   -}
707   -
708   -int AUD_write (void *in_buf, int size)
709   -{
710   - AudioState *s = &oss_audio;
711   - int to_copy, temp;
712   - uint8_t *in, *out;
713   -
714   - to_copy = MIN (s->bufsize - s->live, size);
715   -
716   - temp = to_copy;
717   -
718   - in = in_buf;
719   - out = s->buf;
720   -
721   - while (temp) {
722   - int copy;
723   -
724   - copy = MIN (temp, s->bufsize - s->wpos);
725   - s->copy_fn (out + s->wpos, in, copy);
726   -
727   - s->wpos += copy;
728   - if (s->wpos == s->bufsize) {
729   - s->wpos = 0;
730   - }
731   -
732   - temp -= copy;
733   - in += copy;
734   - s->live += copy;
735   - }
736   -
737   - return to_copy;
738   -}
739   -
740   -void AUD_run (void)
741   -{
742   - int res;
743   - int bytes;
744   - struct audio_buf_info abinfo;
745   - AudioState *s = &oss_audio;
746   -
747   - if (0 == s->live)
748   - return;
749   -
750   - if (s->is_mapped) {
751   - count_info info;
752   -
753   - res = ioctl (s->fd, SNDCTL_DSP_GETOPTR, &info);
754   - if (res < 0) {
755   - int err;
756   -
757   - err = errno;
758   - lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
759   - return;
760   - }
761   -
762   - if (info.ptr > s->old_optr) {
763   - bytes = info.ptr - s->old_optr;
764   - }
765   - else {
766   - bytes = s->bufsize + info.ptr - s->old_optr;
767   - }
768   -
769   - s->old_optr = info.ptr;
770   - s->live -= bytes;
771   - return;
772   - }
773   -
774   - res = ioctl (s->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
775   -
776   - if (res < 0) {
777   - int err;
778   -
779   - err = errno;
780   - lwarn ("SNDCTL_DSP_GETOSPACE failed with %s\n", strerror (err));
781   - return;
782   - }
783   -
784   - bytes = abinfo.bytes;
785   - bytes = MIN (s->live, bytes);
786   -#if 0
787   - bytes = (bytes / fragsize) * fragsize;
788   -#endif
789   -
790   - while (bytes) {
791   - int left, play, written;
792   -
793   - left = s->bufsize - s->rpos;
794   - play = MIN (left, bytes);
795   - written = write (s->fd, (uint8_t *)s->buf + s->rpos, play);
796   -
797   - if (-1 == written) {
798   - if (EAGAIN == errno || EINTR == errno) {
799   - return;
800   - }
801   - else {
802   - ERRFail ("write audio");
803   - }
804   - }
805   -
806   - play = written;
807   - s->live -= play;
808   - s->rpos += play;
809   - bytes -= play;
810   -
811   - if (s->rpos == s->bufsize) {
812   - s->rpos = 0;
813   - }
814   - }
815   -}
816   -
817   -static int get_dsp_bytes (void)
818   -{
819   - int res;
820   - struct count_info info;
821   - AudioState *s = &oss_audio;
822   -
823   - res = ioctl (s->fd, SNDCTL_DSP_GETOPTR, &info);
824   - if (-1 == res) {
825   - int err;
826   -
827   - err = errno;
828   - lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
829   - return -1;
830   - }
831   - else {
832   - ldebug ("bytes %d\n", info.bytes);
833   - return info.bytes;
834   - }
835   -}
836   -
837   -void AUD_adjust_estimate (int leftover)
838   -{
839   - AudioState *s = &oss_audio;
840   - s->leftover = leftover;
841   -}
842   -
843   -int AUD_get_free (void)
844   -{
845   - int free, elapsed;
846   - AudioState *s = &oss_audio;
847   -
848   - free = s->bufsize - s->live;
849   -
850   - if (free <= 0)
851   - return 0;
852   -
853   - elapsed = free;
854   - switch (est) {
855   - case DONT:
856   - break;
857   -
858   - case DSP:
859   - {
860   - static int old_bytes;
861   - int bytes;
862   -
863   - bytes = get_dsp_bytes ();
864   - if (bytes <= 0)
865   - return free;
866   -
867   - elapsed = bytes - old_bytes;
868   - old_bytes = bytes;
869   - ldebug ("dsp elapsed %d bytes\n", elapsed);
870   - break;
871   - }
872   -
873   - case TID:
874   - {
875   - uint64_t ticks, delta;
876   - uint64_t ua_elapsed;
877   - uint64_t al_elapsed;
878   -
879   - ticks = qemu_get_clock(rt_clock);
880   - delta = ticks - s->old_ticks;
881   - s->old_ticks = ticks;
882   -
883   - ua_elapsed = (delta * s->bytes_per_second) / 1000;
884   - al_elapsed = ua_elapsed & ~3ULL;
885   -
886   - ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
887   -
888   - if (al_elapsed > (uint64_t) INT_MAX)
889   - elapsed = INT_MAX;
890   - else
891   - elapsed = al_elapsed;
892   -
893   - elapsed += s->leftover;
894   - }
895   - }
896   -
897   - if (elapsed > free) {
898   - lwarn ("audio can not keep up elapsed %d free %d\n", elapsed, free);
899   - return free;
900   - }
901   - else {
902   - return elapsed;
903   - }
904   -}
905   -
906   -int AUD_get_live (void)
907   -{
908   - AudioState *s = &oss_audio;
909   - return s->live;
910   -}
911   -
912   -int AUD_get_buffer_size (void)
913   -{
914   - AudioState *s = &oss_audio;
915   - return s->bufsize;
916   -}
917   -
918   -#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
919   -#define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS"
920   -#define QC_OSS_MMAP "QEMU_OSS_MMAP"
921   -
922   -void AUD_init (void)
923   -{
924   - int fsp;
925   -
926   - DEREF (pab);
927   -
928   - conf.fragsize = get_conf_val (QC_OSS_FRAGSIZE, conf.fragsize);
929   - conf.nfrags = get_conf_val (QC_OSS_NFRAGS, conf.nfrags);
930   - conf.try_mmap = get_conf_val (QC_OSS_MMAP, conf.try_mmap);
931   -
932   - fsp = conf.fragsize;
933   - if (0 != (fsp & (fsp - 1))) {
934   - Fail ("fragment size %d is not power of 2", fsp);
935   - }
936   -
937   - conf.fragsize = lsbindex (fsp);
938   -}
939   -
940   -#else
941   -
942   -void AUD_run (void)
943   -{
944   -}
945   -
946   -int AUD_write (void *in_buf, int size)
947   -{
948   - return 0;
949   -}
950   -
951   -void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt)
952   -{
953   -}
954   -
955   -void AUD_adjust_estimate (int _leftover)
956   -{
957   -}
958   -
959   -int AUD_get_free (void)
960   -{
961   - return 0;
962   -}
963   -
964   -int AUD_get_live (void)
965   -{
966   - return 0;
967   -}
968   -
969   -int AUD_get_buffer_size (void)
970   -{
971   - return 0;
972   -}
973   -
974   -void AUD_init (void)
975   -{
976   -}
977   -
978   -#endif
... ... @@ -2438,12 +2438,6 @@ void main_loop_wait(int timeout)
2438 2438 if (vm_running) {
2439 2439 qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
2440 2440 qemu_get_clock(vm_clock));
2441   -
2442   - if (audio_enabled) {
2443   - /* XXX: add explicit timer */
2444   - SB16_run();
2445   - }
2446   -
2447 2441 /* run dma transfers, if any */
2448 2442 DMA_run();
2449 2443 }
... ...
... ... @@ -30,6 +30,7 @@
30 30 #include <stdarg.h>
31 31 #include <string.h>
32 32 #include <inttypes.h>
  33 +#include <limits.h>
33 34 #include <time.h>
34 35 #include <ctype.h>
35 36 #include <errno.h>
... ... @@ -553,39 +554,22 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table);
553 554 int pmac_ide_init (BlockDriverState **hd_table,
554 555 openpic_t *openpic, int irq);
555 556  
556   -/* oss.c */
557   -typedef enum {
558   - AUD_FMT_U8,
559   - AUD_FMT_S8,
560   - AUD_FMT_U16,
561   - AUD_FMT_S16
562   -} audfmt_e;
563   -
564   -void AUD_open (int rfreq, int rnchannels, audfmt_e rfmt);
565   -void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt);
566   -int AUD_write (void *in_buf, int size);
567   -void AUD_run (void);
568   -void AUD_adjust_estimate (int _leftover);
569   -int AUD_get_free (void);
570   -int AUD_get_live (void);
571   -int AUD_get_buffer_size (void);
  557 +/* audio.c */
572 558 void AUD_init (void);
573 559  
574 560 /* dma.c */
575   -typedef int (*DMA_transfer_handler) (void *opaque, target_ulong addr, int size);
  561 +typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size);
576 562 int DMA_get_channel_mode (int nchan);
  563 +int DMA_read_memory (int nchan, void *buf, int pos, int size);
  564 +int DMA_write_memory (int nchan, void *buf, int pos, int size);
577 565 void DMA_hold_DREQ (int nchan);
578 566 void DMA_release_DREQ (int nchan);
579 567 void DMA_schedule(int nchan);
580 568 void DMA_run (void);
581 569 void DMA_init (int high_page_enable);
582 570 void DMA_register_channel (int nchan,
583   - DMA_transfer_handler transfer_handler, void *opaque);
584   -
585   -/* sb16.c */
586   -void SB16_run (void);
587   -void SB16_init (void);
588   -
  571 + DMA_transfer_handler transfer_handler,
  572 + void *opaque);
589 573 /* fdc.c */
590 574 #define MAX_FD 2
591 575 extern BlockDriverState *fd_table[MAX_FD];
... ...