sound patch
Hello.
I extracted the sound code from my 3 years old local dosemu branch and re-diffed it against the current svn. This took lot of a hand-work, so the mistakes are possible.
A quick test shows that the adlib now works on x86-64. But many progs (non-adlib ones) are still mute because the cpuemu doesn't exit after every port I/O the way vm86() did. The result is that run_irqs() doesn't come in time.
If someone is willing to work on this, here's the patch.
base/dev/sb16/adlib.c +44 -21
@@ -39,6 +39,7 @@#define ADLIB_BASE 0x388#define OPL3_INTERNAL_FREQ 14400000 // The OPL3 operates at 14.4MHz#define OPL3_MAX_BUF 512 +#define ADLIB_CHANNELS 2#define ADLIB_THRESHOLD 2000000#define ADLIB_RUNNING () (adlib_time_cur > 0)
@@ -64,11 +65,15 @@Bit8u adlib_io_read_base (ioport_t port) { +Bit8u ret;#ifdef HAS_YMF262 -return YMF262Read (opl3, port); +adlib_timer (); + ret =YMF262Read (opl3, port);#else -return 0xff ; + ret =0xff ;#endif +S_printf ("Adlib: Read %hhx from port %x\n" , ret, port); +return ret; }static Bit8u adlib_io_read (ioport_t port)
@@ -79,8 +84,10 @@void adlib_io_write_base (ioport_t port,Bit8u value) { adlib_time_last =GETusTIME (0 ); +S_printf ("Adlib: Write %hhx to port %x\n" , value, port);#ifdef HAS_YMF262 YMF262Write (opl3, port, value); +adlib_timer ();#endif }
@@ -93,8 +100,10 @@static void opl3_set_timer (void *param,int num,double interval_Sec) {long long *timers = param; - timers[num] = - interval_Sec >0 ?GETusTIME (0 ) + interval_Sec *1000000 :0 ; +if (interval_Sec >0 ) + timers[num] +=GETusTIME (0 ) + interval_Sec *1000000 ; +else + timers[num] =0 ;S_printf ("Adlib: timer %i set to %ius\n" , num, (int ) (interval_Sec *1000000 )); }
@@ -105,6 +114,12 @@ADLIB_RUN (); run_new_sb(); } + +static void opl3_irq (void *param,int irq) +{ +S_printf ("SB: OPL3 IRQ (%i)\n" , irq); +/* this IRQ is not wired, nothing to do */ +}#endif void opl3_init (void )
@@ -120,7 +135,7 @@ io_device.write_portw =NULL ; io_device.read_portd =NULL ; io_device.write_portd =NULL ; - io_device.handler_name ="Adlib (+ Advanced) Emulation" ; + io_device.handler_name ="OPL3" ; io_device.start_addr =ADLIB_BASE ; io_device.end_addr =ADLIB_BASE +3 ; io_device.irq =EMU_NO_IRQ ;
@@ -130,14 +145,15 @@ }#ifdef HAS_YMF262 opl3 =YMF262Init (OPL3_INTERNAL_FREQ , opl3_rate); -YMF262SetTimerHandler (opl3, opl3_set_timer, &opl3_timers); +YMF262SetTimerHandler (opl3, opl3_set_timer, opl3_timers);YMF262SetUpdateHandler (opl3, opl3_update,NULL ); +YMF262SetIRQHandler (opl3, opl3_irq,NULL );#endif }void adlib_init (void ) { - adlib_strm =pcm_allocate_stream (2 ,"Adlib" ); + adlib_strm =pcm_allocate_stream (ADLIB_CHANNELS ,"Adlib" ); }void adlib_reset (void )
@@ -157,13 +173,24 @@ } #ifdef HAS_YMF262 -static void adlib_process_samples (int samps) +static void adlib_process_samples(int mono_samps) { -const int chan_map[] = {0 ,1 ,0 ,1 }; -int i, j, k; + const int chan_map[] = +#if ADLIB_CHANNELS == 2 + { 0, 1, 0, 1 }; +#elif ADLIB_CHANNELS == 1 + { 0, 0, 0, 0 }; +#elif ADLIB_CHANNELS == 4 + { 0, 1, 2, 3 }; +#else +#error ADLIB_CHANNELS is wrong + { -1, -1, -1, -1 }; +#endif + int i, j, k, samps; OPL3SAMPLE *chans[4], buf[4][OPL3_MAX_BUF], buf3; -int buf2[OPL3_MAX_BUF ][2 ]; + int buf2[OPL3_MAX_BUF][ADLIB_CHANNELS]; + samps = mono_samps / ADLIB_CHANNELS; if (samps > OPL3_MAX_BUF) { error("Adlib: too many samples requested (%i)\n", samps); samps = OPL3_MAX_BUF;
@@ -174,17 +201,13 @@YMF262UpdateOne (opl3, chans, samps);for (i =0 ; i < samps; i++) { -for (j =0 ; j <2 ; j++) { +for (j =0 ; j <ADLIB_CHANNELS ; j++) { buf2[i][j] =0 ;for (k =0 ; k <ARRAY_SIZE (chan_map); k++) {if (chan_map[k] == j) buf2[i][j] += buf[k][i]; } -if (buf2[i][j] >SHRT_MAX ) - buf2[i][j] =SHRT_MAX ; -if (buf2[i][j] <SHRT_MIN ) - buf2[i][j] =SHRT_MIN ; - buf3 = buf2[i][j]; + buf3 =pcm_samp_cutoff (buf2[i][j], opl3_format);pcm_write_samples (&buf3,pcm_format_size (opl3_format), opl3_rate, opl3_format, adlib_strm); }
@@ -204,13 +227,13 @@pcm_flush (adlib_strm); }if (ADLIB_RUNNING ()) { - period =pcm_samp_period (opl3_rate,2 ); + period =pcm_samp_period (opl3_rate,ADLIB_CHANNELS ); nsamps = (now - adlib_time_cur) / period;if (nsamps >OPL3_MAX_BUF ) nsamps =OPL3_MAX_BUF ; - nsamps -= nsamps %2 ; + nsamps -= nsamps %ADLIB_CHANNELS ;if (nsamps) { -adlib_process_samples (nsamps /2 ); +adlib_process_samples (nsamps); adlib_time_cur += nsamps * period;S_printf ("SB: processed %i Adlib samples\n" , nsamps); }
@@ -219,7 +242,7 @@for (i =0 ; i <2 ; i++) {if (opl3_timers[i] >0 && now > opl3_timers[i]) {S_printf ("Adlib: timer %i expired\n" , i); - opl3_timers[i] =0 ; + opl3_timers[i] = now - opl3_timers[i];YMF262TimerOver (opl3, i); } }
base/dev/sb16/dspio.c renamed from base/dev/sb16/dspio.c.orig +7 -21
@@ -36,7 +36,7 @@#include "sound/sndpcm.h" #include "sound/midi.h" #include "adlib.h" -#include "dma.h" +#include "dmanew.h" #include "sb16.h" #include "dspio.h" #include <string.h>
@@ -65,22 +65,6 @@#define DSPIO ((struct dspio_state *)dspio) -static int dma8_get_format (int is_signed) -{ -return is_signed ?PCM_FORMAT_S8 :PCM_FORMAT_U8 ; -} - -static int dma16_get_format (int is_signed) -{ -return is_signed ?PCM_FORMAT_S16_LE :PCM_FORMAT_U16_LE ; -} - -static int dma_get_format (int is_16,int is_signed) -{ -return is_16 ?dma16_get_format (is_signed) : -dma8_get_format (is_signed); -} -static void dma_get_silence (int is_signed,int is16bit,void *ptr) {if (is16bit) {
@@ -163,9 +147,10 @@if (state->output_running)return ;S_printf ("SB: starting output\n" ); -/* We would need real time here, but the HACK is to use stream time instead. +/* We would need real time here, but the HACK is to use stream +* timestamp instead. * That compensates the hack of dspio_process_dma() */ - state->output_time_cur =pcm_get_stream_time (state->dma_strm); + state->output_time_cur =pcm_calc_tstamp (state->dma.rate, state->dma_strm); state->output_running =1 ; }
@@ -296,6 +281,7 @@if (state->dma.running) { state->dma.stereo =sb_dma_samp_stereo (); state->dma.rate =sb_get_dma_sampling_rate (); + state->dma.samp_signed =sb_dma_samp_signed (); } while (state->output_running && (state->output_time_cur <= time_dst ||
@@ -308,13 +294,13 @@if (state->speaker) {pcm_write_samples (&buf,1 << state->dma.is16bit, state->dma.rate, -dma_get_format (state->dma.is16bit, +pcm_get_format (state->dma.is16bit, state->dma.samp_signed), state->dma_strm);if (!state->dma.stereo)pcm_write_samples (&buf,1 << state->dma.is16bit, state->dma.rate, -dma_get_format (state->dma.is16bit, +pcm_get_format (state->dma.is16bit, state->dma. samp_signed), state->dma_strm);
base/dev/sb16/sb16.c +3 -2
@@ -636,6 +636,7 @@ hdma_idx = config.sb_hdma ?1 << config.sb_hdma :0 ; sb.mixer_regs[0x80 ] = irq_idx; sb.mixer_regs[0x81 ] = dma_idx | hdma_idx; + sb.mixer_regs[0x82 ] =SB16_ID82 ; }static void sb_reset (void )
@@ -920,8 +921,8 @@case 0xE1 :/* DSP Version - SB */ S_printf ("SB: Query Version\n" ); -dsp_write_output (SB_16 >>8 ); -dsp_write_output (SB_16 &0xFF ); +dsp_write_output (SB16_ID >>8 ); +dsp_write_output (SB16_ID &0xFF );break ;case 0xE2 : {
base/dev/sb16/sb16.h +9 -5
@@ -26,11 +26,15 @@#include "utilities.h" // for rng_s #define SB_NONE 0x000 -#define SB_OLD 0x105 -#define SB_20 0x201 -#define SB_PRO 0x300 -#define SB_16 0x405 -#define SB_AWE32 0x40C +#define SB_ID 0x105 +#define SB20_ID 0x201 +#define SBPRO_ID 0x300 +#define SB16_ID 0x405 +#define SBAWE32_ID 0x40C + +/* bochs and the old dosemu code disagree on that value. +* Of course I trust bochs. :) */ +#define SB16_ID82 (2 << 5)/* * Various Status values
base/dev/dma/dmanew.c +71 -119
283 lines not on this page · raw message
base/dev/dma/dmaregs.h new file +74 -0
74 lines not on this page · raw message
base/sound/nullsnd.c +2 -3
@@ -37,7 +37,6 @@static const char *nullsnd_name ="Sound Output: NULL device" ;const int frag_size =4096 ;static struct player_params params; -static struct player_callbacks calls;static int running, locked;static double last_time =0 ;
@@ -83,7 +82,7 @@ time =GETusTIME (0 );while (time - last_time > frag_time) { last_time += frag_time; - calls.get_data (NULL , frag_size, ¶ms); +pcm_data_get (NULL , frag_size, ¶ms); } }
@@ -99,5 +98,5 @@ player.unlock = nullsnd_unlock; player.timer = nullsnd_timer; running = locked =0 ; -return pcm_register_clocked_player (player, &calls); +return pcm_register_clocked_player (player); }
base/sound/sndpcm.c +53 -21
150 lines not on this page · raw message
plugin/midimisc/mid_o_tmdty.c +5 -4
@@ -52,7 +51,7 @@#define TMDTY_BIN "timidity"#define TMDTY_ARGS "-EFreverb=0 -EFchorus=0 -EFresamp=1 -EFvlpf=0 -EFns=0" -static const char *midotmdty_name ="MIDI Output: midid plugin" ; +static const char *midotmdty_name ="MIDI Output: TiMidity++ plugin" ;static int ctrl_sock_in, ctrl_sock_out, data_sock, pcm_stream;static pid_t tmdty_pid =-1 ;
@@ -71,7 +70,8 @@while ((selret =select (data_sock +1 , &rfds,NULL ,NULL , &tv)) >0 ) { n =RPT_SYSCALL (read (data_sock, buf,sizeof (buf)));if (n >0 ) { -pcm_write_samples (buf, n,44100 ,PCM_FORMAT_S16_LE , +pcm_write_samples (buf, n,TMDTY_FREQ ,pcm_get_format ( +TMDTY_8BIT ?0 :1 ,TMDTY_UNS ?0 :1 ), pcm_stream); }else {break ;
@@ -233,10 +225,10 @@if (ret) {const char *ver_str ="Server Version " ;char *ptr =strstr (buf, ver_str); -int vmin, vmid, vmaj, ver;if (!ptr) { ret = FALSE; }else { +int vmin, vmid, vmaj, ver; ptr +=strlen (ver_str);sscanf (ptr,"%d.%d.%d" , &vmaj, &vmid, &vmin); ver = vmaj *10000 + vmid *100 + vmin;
@@ -311,7 +303,7 @@if (TMDTY_CAPT ) {add_to_io_select (data_sock,1 , midotmdty_io); - pcm_stream =pcm_allocate_stream (2 ,"MIDI" ); + pcm_stream =pcm_allocate_stream (TMDTY_MONO ?1 :2 ,"MIDI" ); }return TRUE;
plugin/sdl/snd_o_SDL.c +2 -4
@@ -33,12 +33,11 @@#include <SDL.h> static const char *sdlsnd_name ="Sound Output: SDL device" ; -static struct player_callbacks calls;static struct player_params params;static void sdlsnd_callback (void *userdata,Uint8 * stream,int len) { - calls.get_data (stream, len, ¶ms); +pcm_data_get (stream, len, ¶ms); }static void sdlsnd_start (void )
@@ -87,9 +86,8 @@ player.close = sdlsnd_close; player.lock = SDL_LockAudio; player.unlock = SDL_UnlockAudio; - player.timer =NULL ;#if 1 -return pcm_register_clocked_player (player, &calls); +return pcm_register_clocked_player (player);#else return 0 ;#endif
plugin/sndfile/snd_o_wav.c +1 -2
@@ -34,7 +34,7 @@#include <stdio.h> #include <sndfile.h> -static const char *wavsnd_name ="Sound Output: WAV writer" ; +static const char *wavsnd_name ="Sound Output: WAV file writer" ;static SNDFILE *wav;static int wavsnd_open (struct player_params *par)
@@ -67,7 +67,6 @@ player.open = wavsnd_open; player.close = wavsnd_close; player.write = wavsnd_write; - player.timer =NULL ;#if 0 return pcm_register_unclocked_player (player);#else
include/sound/sndpcm.h +4 -2
@@ -30,13 +30,15 @@extern void pcm_set_flag (int strm_idx,int flag);extern void pcm_set_mode (int strm_idx,int mode);extern int pcm_flush (int strm_idx); +extern int pcm_samp_cutoff (int val,int format); +extern int pcm_get_format (int is_16,int is_signed);extern double pcm_samp_period (double rate,int channels);extern double pcm_frag_period (int size,struct player_params *params);extern void pcm_write_samples (void *ptr,size_t size, -double rate,int format,int strm_idx); +double rate,int format,int strm_idx);extern int pcm_format_size (int format);extern void pcm_timer (void ); -extern double pcm_get_stream_time (int strm_idx); +extern double pcm_calc_tstamp (double rate,int strm_idx);#define PCM_FLAG_RAW 1
include/sound/sound.h +5 -9
@@ -20,8 +20,8 @@* along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef _SOUND_H -#define _SOUND_H +#ifndef __SOUND_H__ +#define __SOUND_H__/* This is the correct way to run an SB timer tick */ extern void run_new_sb (void );
@@ -36,9 +36,7 @@int channels; }; -struct player_callbacks { -size_t (*get_data)(void *buf,size_t size,struct player_params *params); -}; +size_t pcm_data_get (void *data,size_t size,struct player_params *params);struct clocked_player {const char *name;
@@ -55,12 +53,10 @@const char *name;int (*open)(struct player_params *params);void (*close)(void ); -void (*timer)(void );size_t (*write)(void *buf,size_t size); }; -extern int pcm_register_clocked_player (struct clocked_player player, -struct player_callbacks *callbacks); +extern int pcm_register_clocked_player (struct clocked_player player);extern int pcm_register_unclocked_player (struct unclocked_player player);/** PCM sample format */
@@ -84,4 +80,4 @@ PCM_FORMAT_IMA_ADPCM, }; -#endif /* EMU_SOUND_H */ +#endif
include/dma.h +0 -5
@@ -9,12 +9,7 @@void dma_init (void );void dma_reset (void ); -void dma_new_init (void ); -void dma_new_reset (void ); -enum {DMA_NO_DACK ,DMA_DACK }; -int dma_pulse_DRQ (int ch,Bit8u *buf); -/* 8237 DMA controllers */ #define IO_DMA1_BASE 0x00/* 8 bit slave DMA, channels 0..3 */ #define IO_DMA2_BASE 0xC0/* 16 bit master DMA, ch 4(=slave input)..7 */
include/dmanew.h new file +33 -0
@@ -0,0 +1,33 @@ +/* +* Copyright (C) 2006 Stas Sergeev <[email protected]> +* +* The below copyright strings have to be distributed unchanged together +* with this file. This prefix can not be modified or separated. +*/ + +/* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef __DMA_H__ +#define __DMA_H__ + +void dma_new_init (void ); +void dma_new_reset (void ); + +enum {DMA_NO_DACK ,DMA_DACK }; +int dma_pulse_DRQ (int ch,Bit8u *buf); + +#endif
base/dev/dma/dma.c +1 -0
@@ -51,6 +51,7 @@#include <sys/types.h> #include <unistd.h> #include "dma.h" +#include "dmanew.h" #include "pic.h" #include "port.h"
Quoted 6 lines · Stas Sergeev
A quick test shows that the adlib now works on x86-64. But many progs (non-adlib ones) are still mute because the cpuemu doesn't exit after every port I/O the way
vm86()did. The result is thatrun_irqs()doesn't come in time.
Thanks for the patch, I'll have a look. I fixed the cpuemu I/O issue in SVN now so cpuemu generates a GPF for every I/O except for some VGAEMU optimizations and real ports.
Bart
Quoted 3 lines · Bart Oldeman
Thanks for the patch, I'll have a look. I fixed the cpuemu I/O issue in SVN now so cpuemu generates a GPF for every I/O except for some VGAEMU optimizations and real ports.
Cool, works for me, but I am still
not getting the SF mails.