Commit 15b614700062dde8801762b1cfd4717a63a2cfd9

Authored by bellard
1 parent 9e89a4be

audio fix (malc)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1137 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 45 additions and 20 deletions
hw/sb16.c
@@ -26,15 +26,16 @@ @@ -26,15 +26,16 @@
26 #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) 26 #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
27 27
28 #define dolog(...) AUD_log ("sb16", __VA_ARGS__) 28 #define dolog(...) AUD_log ("sb16", __VA_ARGS__)
  29 +
  30 +/* #define DEBUG */
  31 +/* #define DEBUG_SB16_MOST */
  32 +
29 #ifdef DEBUG 33 #ifdef DEBUG
30 #define ldebug(...) dolog (__VA_ARGS__) 34 #define ldebug(...) dolog (__VA_ARGS__)
31 #else 35 #else
32 #define ldebug(...) 36 #define ldebug(...)
33 #endif 37 #endif
34 38
35 -/* #define DEBUG */  
36 -/* #define DEBUG_SB16_MOST */  
37 -  
38 #define IO_READ_PROTO(name) \ 39 #define IO_READ_PROTO(name) \
39 uint32_t name (void *opaque, uint32_t nport) 40 uint32_t name (void *opaque, uint32_t nport)
40 #define IO_WRITE_PROTO(name) \ 41 #define IO_WRITE_PROTO(name) \
@@ -206,8 +207,18 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len) @@ -206,8 +207,18 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
206 s->freq = (1000000 + (tmp / 2)) / tmp; 207 s->freq = (1000000 + (tmp / 2)) / tmp;
207 } 208 }
208 209
209 - if (-1 != dma_len)  
210 - s->block_size = dma_len + 1; 210 + if (dma_len != -1)
  211 + s->block_size = dma_len << s->fmt_stereo;
  212 + else {
  213 + /* This is apparently the only way to make both Act1/PL
  214 + and SecondReality/FC work
  215 +
  216 + Act1 sets block size via command 0x48 and it's an odd number
  217 + SR does the same with even number
  218 + Both use stereo, and Creatives own documentation states that
  219 + 0x48 sets block size in bytes less one.. go figure */
  220 + s->block_size &= ~s->fmt_stereo;
  221 + }
211 222
212 s->freq >>= s->fmt_stereo; 223 s->freq >>= s->fmt_stereo;
213 s->left_till_irq = s->block_size; 224 s->left_till_irq = s->block_size;
@@ -216,6 +227,9 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len) @@ -216,6 +227,9 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
216 s->dma_auto = (mask & DMA8_AUTO) != 0; 227 s->dma_auto = (mask & DMA8_AUTO) != 0;
217 s->align = (1 << s->fmt_stereo) - 1; 228 s->align = (1 << s->fmt_stereo) - 1;
218 229
  230 + if (s->block_size & s->align)
  231 + dolog ("warning: unaligned buffer\n");
  232 +
219 ldebug ("freq %d, stereo %d, sign %d, bits %d, " 233 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
220 "dma %d, auto %d, fifo %d, high %d\n", 234 "dma %d, auto %d, fifo %d, high %d\n",
221 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits, 235 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
@@ -260,8 +274,13 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) @@ -260,8 +274,13 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
260 274
261 s->block_size = dma_len + 1; 275 s->block_size = dma_len + 1;
262 s->block_size <<= (s->fmt_bits == 16); 276 s->block_size <<= (s->fmt_bits == 16);
263 - if (!s->dma_auto) /* Miles Sound System ? */ 277 + if (!s->dma_auto) {
  278 + /* It is clear that for DOOM and auto-init this value
  279 + shouldn't take stereo into account, while Miles Sound Systems
  280 + setsound.exe with single transfer mode wouldn't work without it
  281 + wonders of SB16 yet again */
264 s->block_size <<= s->fmt_stereo; 282 s->block_size <<= s->fmt_stereo;
  283 + }
265 284
266 ldebug ("freq %d, stereo %d, sign %d, bits %d, " 285 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
267 "dma %d, auto %d, fifo %d, high %d\n", 286 "dma %d, auto %d, fifo %d, high %d\n",
@@ -290,6 +309,8 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) @@ -290,6 +309,8 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
290 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16); 309 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
291 s->highspeed = 0; 310 s->highspeed = 0;
292 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1; 311 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
  312 + if (s->block_size & s->align)
  313 + dolog ("warning: unaligned buffer\n");
293 314
294 if (s->freq) 315 if (s->freq)
295 s->voice = AUD_open (s->voice, "sb16", s->freq, 316 s->voice = AUD_open (s->voice, "sb16", s->freq,
@@ -373,6 +394,10 @@ static void command (SB16State *s, uint8_t cmd) @@ -373,6 +394,10 @@ static void command (SB16State *s, uint8_t cmd)
373 s->block_size = 0; 394 s->block_size = 0;
374 break; 395 break;
375 396
  397 + case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
  398 + control (s, 1);
  399 + break;
  400 +
376 case 0x20: /* Direct ADC, Juice/PL */ 401 case 0x20: /* Direct ADC, Juice/PL */
377 dsp_out_data (s, 0xff); 402 dsp_out_data (s, 0xff);
378 goto warn; 403 goto warn;
@@ -607,9 +632,7 @@ static void complete (SB16State *s) @@ -607,9 +632,7 @@ static void complete (SB16State *s)
607 break; 632 break;
608 633
609 case 0x14: 634 case 0x14:
610 - dma_cmd8 (s, 0, dsp_get_lohi (s));  
611 - /* s->can_write = 0; */  
612 - /* qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + (ticks_per_sec * 320) / 1000000); */ 635 + dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
613 break; 636 break;
614 637
615 case 0x40: 638 case 0x40:
@@ -626,22 +649,20 @@ static void complete (SB16State *s) @@ -626,22 +649,20 @@ static void complete (SB16State *s)
626 break; 649 break;
627 650
628 case 0x48: 651 case 0x48:
629 - s->block_size = dsp_get_lohi (s);  
630 - /* s->highspeed = 1; */ 652 + s->block_size = dsp_get_lohi (s) + 1;
631 ldebug ("set dma block len %d\n", s->block_size); 653 ldebug ("set dma block len %d\n", s->block_size);
632 break; 654 break;
633 655
634 case 0x80: 656 case 0x80:
635 { 657 {
636 - int samples, bytes; 658 + int freq, samples, bytes;
637 int64_t ticks; 659 int64_t ticks;
638 660
639 - if (-1 == s->freq)  
640 - s->freq = 11025;  
641 - samples = dsp_get_lohi (s); 661 + freq = s->freq > 0 ? s->freq : 11025;
  662 + samples = dsp_get_lohi (s) + 1;
642 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16); 663 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
643 - ticks = bytes ? (ticks_per_sec / (s->freq / bytes)) : 0;  
644 - if (!bytes || ticks < ticks_per_sec / 1024) 664 + ticks = (bytes * ticks_per_sec) / freq;
  665 + if (ticks < ticks_per_sec / 1024)
645 pic_set_irq (s->irq, 1); 666 pic_set_irq (s->irq, 1);
646 else 667 else
647 qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks); 668 qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks);
@@ -658,7 +679,7 @@ static void complete (SB16State *s) @@ -658,7 +679,7 @@ static void complete (SB16State *s)
658 679
659 case 0xe2: 680 case 0xe2:
660 d0 = dsp_get_data (s); 681 d0 = dsp_get_data (s);
661 - dolog ("E2 = %#x\n", d0); 682 + ldebug ("E2 = %#x\n", d0);
662 break; 683 break;
663 684
664 case 0xe4: 685 case 0xe4:
@@ -967,6 +988,9 @@ static IO_WRITE_PROTO(mixer_write_indexw) @@ -967,6 +988,9 @@ static IO_WRITE_PROTO(mixer_write_indexw)
967 static IO_READ_PROTO(mixer_read) 988 static IO_READ_PROTO(mixer_read)
968 { 989 {
969 SB16State *s = opaque; 990 SB16State *s = opaque;
  991 +#ifndef DEBUG_SB16_MOST
  992 + if (s->mixer_nreg != 0x82)
  993 +#endif
970 ldebug ("mixer_read[%#x] -> %#x\n", 994 ldebug ("mixer_read[%#x] -> %#x\n",
971 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]); 995 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
972 return s->mixer_regs[s->mixer_nreg]; 996 return s->mixer_regs[s->mixer_nreg];
@@ -1049,8 +1073,9 @@ static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) @@ -1049,8 +1073,9 @@ static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1049 } 1073 }
1050 1074
1051 #ifdef DEBUG_SB16_MOST 1075 #ifdef DEBUG_SB16_MOST
1052 - ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",  
1053 - dma_pos, free, dma_len, s->left_till_irq, copy, s->block_size); 1076 + ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
  1077 + dma_pos, free, dma_len, s->left_till_irq, copy, written,
  1078 + s->block_size);
1054 #endif 1079 #endif
1055 1080
1056 while (s->left_till_irq <= 0) { 1081 while (s->left_till_irq <= 0) {