Sound Blaster improvements :
- Implemented audio recording on SB16 & AWE32 (MIDI only) - Mixer improvements - SB 2.0 CD mixer can be emulated - DSP tweaks, mainly for SB Pro. Implemented speaker on/off and limited high speed DMA to SB 2.0 & Pro - A few other things Patch from JosepMa.
This commit is contained in:
parent
9283d0e1b0
commit
4ca6d67f87
5 changed files with 1188 additions and 297 deletions
|
|
@ -1396,8 +1396,8 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p)
|
|||
if ((val&0xFF) == 0 && the_voice->cvcf_curr_volume == 0 && the_voice->vtft_vol_target == 0
|
||||
&& the_voice->dcysusv == 0x80 && the_voice->ip == 0)
|
||||
{
|
||||
// Patch to avoid some clicking noises with Impulse tracker or other software that sets different values to 0
|
||||
// to set noteoff, but here, 0 means no attenuation = full volume.
|
||||
// Patch to avoid some clicking noises with Impulse tracker or other software that sets
|
||||
// different values to 0 to set noteoff, but here, 0 means no attenuation = full volume.
|
||||
return;
|
||||
}
|
||||
the_voice->ifatn = val;
|
||||
|
|
@ -2100,7 +2100,7 @@ I've recopilated these sentences to get an idea of how to loop
|
|||
emu8k->pos = new_pos;
|
||||
}
|
||||
/* onboard_ram in kilobytes */
|
||||
void emu8k_init(emu8k_t *emu8k, int onboard_ram)
|
||||
void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram)
|
||||
{
|
||||
uint32_t const BLOCK_SIZE_WORDS = 0x10000;
|
||||
FILE *f;
|
||||
|
|
@ -2160,9 +2160,9 @@ void emu8k_init(emu8k_t *emu8k, int onboard_ram)
|
|||
|
||||
}
|
||||
|
||||
io_sethandler(0x0620, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k);
|
||||
io_sethandler(0x0a20, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k);
|
||||
io_sethandler(0x0e20, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k);
|
||||
io_sethandler(emu_addr, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k);
|
||||
io_sethandler(emu_addr+0x400, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k);
|
||||
io_sethandler(emu_addr+0x800, 0x0004, emu8k_inb, emu8k_inw, NULL, emu8k_outb, emu8k_outw, NULL, emu8k);
|
||||
|
||||
/*Create frequency table. (Convert initial pitch register value to a linear speed change)
|
||||
* The input is encoded such as 0xe000 is center note (no pitch shift)
|
||||
|
|
|
|||
|
|
@ -357,8 +357,6 @@ typedef struct emu8k_t
|
|||
|
||||
uint16_t wc;
|
||||
|
||||
uint16_t c02_read;
|
||||
|
||||
uint16_t id;
|
||||
|
||||
/* The empty block is used to act as an unallocated memory returning zero. */
|
||||
|
|
@ -370,8 +368,6 @@ typedef struct emu8k_t
|
|||
|
||||
int cur_reg, cur_voice;
|
||||
|
||||
int timer_count;
|
||||
|
||||
int16_t out_l, out_r;
|
||||
|
||||
emu8k_chorus_eng_t chorus_engine;
|
||||
|
|
@ -385,7 +381,7 @@ typedef struct emu8k_t
|
|||
|
||||
|
||||
|
||||
void emu8k_init(emu8k_t *emu8k, int onboard_ram);
|
||||
void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram);
|
||||
void emu8k_close(emu8k_t *emu8k);
|
||||
|
||||
void emu8k_update(emu8k_t *emu8k);
|
||||
|
|
|
|||
1220
src/sound_sb.c
1220
src/sound_sb.c
File diff suppressed because it is too large
Load diff
|
|
@ -16,10 +16,22 @@
|
|||
#include "sound_sb_dsp.h"
|
||||
#include "timer.h"
|
||||
|
||||
/*The recording safety margin is intended for uneven "len" calls to the get_buffer mixer calls on sound_sb*/
|
||||
#define SB_DSP_REC_SAFEFTY_MARGIN 4096
|
||||
|
||||
void pollsb(void *p);
|
||||
void sb_poll_i(void *p);
|
||||
|
||||
//#define SB_DSP_RECORD_DEBUG
|
||||
//#define SB_TEST_RECORDING_SAW
|
||||
|
||||
#ifdef SB_DSP_RECORD_DEBUG
|
||||
FILE* soundf = 0/*NULL*/;
|
||||
#endif
|
||||
|
||||
#ifdef SB_TEST_RECORDING_SAW
|
||||
int counttest;
|
||||
#endif
|
||||
|
||||
static int sbe2dat[4][9] = {
|
||||
{ 0x01, -0x02, -0x04, 0x08, -0x10, 0x20, 0x40, -0x80, -106 },
|
||||
|
|
@ -133,9 +145,20 @@ void sb_dsp_reset(sb_dsp_t *dsp)
|
|||
dsp->sbreset = 0;
|
||||
dsp->sbenable = dsp->sb_enable_i = dsp->sb_count_i = 0;
|
||||
|
||||
dsp->record_pos_read=0;
|
||||
dsp->record_pos_write=SB_DSP_REC_SAFEFTY_MARGIN;
|
||||
|
||||
picintc(1 << dsp->sb_irqnum);
|
||||
|
||||
dsp->asp_data_len = 0;
|
||||
|
||||
#ifdef SB_DSP_RECORD_DEBUG
|
||||
if (soundf != 0)
|
||||
{
|
||||
fclose(soundf);
|
||||
soundf=0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void sb_doreset(sb_dsp_t *dsp)
|
||||
|
|
@ -205,8 +228,8 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len
|
|||
if (dsp->sb_8_enable && dsp->sb_8_output) dsp->sb_8_enable = 0;
|
||||
dsp->sb_16_output = 1;
|
||||
timer_process();
|
||||
dsp->sbenable = dsp->sb_16_enable;
|
||||
timer_update_outstanding();
|
||||
dsp->sbenable = dsp->sb_16_enable;
|
||||
timer_update_outstanding();
|
||||
// pclog("Start 16-bit DMA addr %06X len %04X\n",dma16.ac[1]+(dma16.page[1]<<16),len);
|
||||
}
|
||||
}
|
||||
|
|
@ -215,6 +238,13 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l
|
|||
{
|
||||
if (dma8)
|
||||
{
|
||||
#ifdef SB_TEST_RECORDING_SAW
|
||||
switch (dsp->sb_8_format)
|
||||
{
|
||||
case 00:case 20:counttest=0x80;break;
|
||||
case 10:case 30:counttest=0;break;
|
||||
}
|
||||
#endif
|
||||
dsp->sb_8_length = len;
|
||||
dsp->sb_8_format = format;
|
||||
dsp->sb_8_autoinit = autoinit;
|
||||
|
|
@ -229,6 +259,13 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifdef SB_TEST_RECORDING_SAW
|
||||
switch (dsp->sb_16_format)
|
||||
{
|
||||
case 00:case 20:counttest=0x8000;break;
|
||||
case 10:case 30:counttest=0;break;
|
||||
}
|
||||
#endif
|
||||
dsp->sb_16_length = len;
|
||||
dsp->sb_16_format = format;
|
||||
dsp->sb_16_autoinit = autoinit;
|
||||
|
|
@ -241,6 +278,16 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l
|
|||
timer_update_outstanding();
|
||||
// pclog("Start 16-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len);
|
||||
}
|
||||
memset(dsp->record_buffer,0,sizeof(dsp->record_buffer));
|
||||
|
||||
#ifdef SB_DSP_RECORD_DEBUG
|
||||
if (soundf != 0)
|
||||
{
|
||||
fclose(soundf);
|
||||
soundf=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int sb_8_read_dma(sb_dsp_t *dsp)
|
||||
|
|
@ -250,14 +297,23 @@ int sb_8_read_dma(sb_dsp_t *dsp)
|
|||
void sb_8_write_dma(sb_dsp_t *dsp, uint8_t val)
|
||||
{
|
||||
dma_channel_write(dsp->sb_8_dmanum, val);
|
||||
#ifdef SB_DSP_RECORD_DEBUG
|
||||
if (!soundf) soundf=fopen("sound_dsp.pcm","wb");
|
||||
fwrite(&val,1,1,soundf);
|
||||
#endif
|
||||
}
|
||||
uint16_t sb_16_read_dma(sb_dsp_t *dsp)
|
||||
{
|
||||
return dma_channel_read(5);
|
||||
return dma_channel_read(dsp->sb_16_dmanum);
|
||||
}
|
||||
void sb_16_write_dma(sb_dsp_t *dsp, uint16_t val)
|
||||
int sb_16_write_dma(sb_dsp_t *dsp, uint16_t val)
|
||||
{
|
||||
dma_channel_write(5, val);
|
||||
int ret = dma_channel_write(dsp->sb_16_dmanum, val);
|
||||
#ifdef SB_DSP_RECORD_DEBUG
|
||||
if (!soundf) soundf=fopen("sound_dsp.pcm","wb");
|
||||
fwrite(&val,2,1,soundf);
|
||||
#endif
|
||||
return (ret == DMA_NODATA);
|
||||
}
|
||||
|
||||
void sb_dsp_setirq(sb_dsp_t *dsp, int irq)
|
||||
|
|
@ -270,6 +326,10 @@ void sb_dsp_setdma8(sb_dsp_t *dsp, int dma)
|
|||
dsp->sb_8_dmanum = dma;
|
||||
}
|
||||
|
||||
void sb_dsp_setdma16(sb_dsp_t *dsp, int dma)
|
||||
{
|
||||
dsp->sb_16_dmanum = dma;
|
||||
}
|
||||
void sb_exec_command(sb_dsp_t *dsp)
|
||||
{
|
||||
int temp,c;
|
||||
|
|
@ -310,7 +370,19 @@ void sb_exec_command(sb_dsp_t *dsp)
|
|||
dsp->sb_8_length--;
|
||||
break;
|
||||
case 0x20: /*8-bit direct input*/
|
||||
sb_add_data(dsp, 0);
|
||||
sb_add_data(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80);
|
||||
/*Due to the current implementation, I need to emulate a samplerate, even if this
|
||||
* mode does not imply such samplerate. Position is increased in sb_poll_i*/
|
||||
if (dsp->sb_enable_i==0)
|
||||
{
|
||||
dsp->sb_timei = 256 - 22;
|
||||
dsp->sblatchi = TIMER_USEC * 22;
|
||||
temp = 1000000 / 22;
|
||||
dsp->sb_freq = temp;
|
||||
timer_process();
|
||||
dsp->sb_enable_i = 1;
|
||||
timer_update_outstanding();
|
||||
}
|
||||
break;
|
||||
case 0x24: /*8-bit single cycle DMA input*/
|
||||
sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8));
|
||||
|
|
@ -373,28 +445,30 @@ void sb_exec_command(sb_dsp_t *dsp)
|
|||
case 0x80: /*Pause DAC*/
|
||||
dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8);
|
||||
// pclog("SB pause %04X\n",sb_pausetime);
|
||||
timer_process();
|
||||
timer_process();
|
||||
dsp->sbenable = 1;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
case 0x90: /*High speed 8-bit autoinit DMA output*/
|
||||
if (dsp->sb_type < SB2) break;
|
||||
if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break;
|
||||
sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen);
|
||||
break;
|
||||
case 0x91: /*High speed 8-bit single cycle DMA output*/
|
||||
if (dsp->sb_type < SB2) break;
|
||||
if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break;
|
||||
sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen);
|
||||
break;
|
||||
case 0x98: /*High speed 8-bit autoinit DMA input*/
|
||||
if (dsp->sb_type < SB2) break;
|
||||
if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break;
|
||||
sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen);
|
||||
break;
|
||||
case 0x99: /*High speed 8-bit single cycle DMA input*/
|
||||
if (dsp->sb_type < SB2) break;
|
||||
if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break;
|
||||
sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen);
|
||||
break;
|
||||
case 0xA0: /*Set input mode to mono*/
|
||||
case 0xA8: /*Set input mode to stereo*/
|
||||
if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break;
|
||||
//TODO: Implement. 3.xx-only command.
|
||||
break;
|
||||
case 0xB0: case 0xB1: case 0xB2: case 0xB3:
|
||||
case 0xB4: case 0xB5: case 0xB6: case 0xB7: /*16-bit DMA output*/
|
||||
|
|
@ -424,9 +498,17 @@ void sb_exec_command(sb_dsp_t *dsp)
|
|||
dsp->sb_8_pause = 1;
|
||||
break;
|
||||
case 0xD1: /*Speaker on*/
|
||||
if (dsp->sb_type < SB15 )
|
||||
dsp->sb_8_pause = 1;
|
||||
else if ( dsp->sb_type < SB16 )
|
||||
dsp->muted = 0;
|
||||
dsp->sb_speaker = 1;
|
||||
break;
|
||||
case 0xD3: /*Speaker off*/
|
||||
if (dsp->sb_type < SB15 )
|
||||
dsp->sb_8_pause = 1;
|
||||
else if ( dsp->sb_type < SB16 )
|
||||
dsp->muted = 1;
|
||||
dsp->sb_speaker = 0;
|
||||
break;
|
||||
case 0xD4: /*Continue 8-bit DMA*/
|
||||
|
|
@ -481,6 +563,10 @@ void sb_exec_command(sb_dsp_t *dsp)
|
|||
// pclog("Trigger IRQ\n");
|
||||
sb_irq(dsp, 1);
|
||||
break;
|
||||
case 0xF3: /*Trigger 16-bit IRQ*/
|
||||
// pclog("Trigger IRQ\n");
|
||||
sb_irq(dsp, 0);
|
||||
break;
|
||||
case 0xE7: /*???*/
|
||||
case 0xFA: /*???*/
|
||||
break;
|
||||
|
|
@ -517,6 +603,22 @@ void sb_exec_command(sb_dsp_t *dsp)
|
|||
break;
|
||||
// default:
|
||||
// fatal("Exec bad SB command %02X\n",sb_command);
|
||||
|
||||
|
||||
/*TODO: Some more data about the DSP registeres
|
||||
* http://the.earth.li/~tfm/oldpage/sb_dsp.html
|
||||
* http://www.synchrondata.com/pheaven/www/area19.htm
|
||||
* http://www.dcee.net/Files/Programm/Sound/
|
||||
0E3h DSP Copyright SBPro2???
|
||||
0F0h Sine Generator SB
|
||||
0F1h DSP Auxiliary Status (Obsolete) SB-Pro2
|
||||
0F2h IRQ Request, 8-bit SB
|
||||
0F3h IRQ Request, 16-bit SB16
|
||||
0FBh DSP Status SB16
|
||||
0FCh DSP Auxiliary Status SB16
|
||||
0FDh DSP Command Status SB16
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -570,7 +672,6 @@ void sb_write(uint16_t a, uint8_t v, void *priv)
|
|||
uint8_t sb_read(uint16_t a, void *priv)
|
||||
{
|
||||
sb_dsp_t *dsp = (sb_dsp_t *)priv;
|
||||
// if (a==0x224) output=1;
|
||||
// pclog("sb_read : Read soundblaster %04X %04X:%04X\n",a,CS,pc);
|
||||
switch (a & 0xf)
|
||||
{
|
||||
|
|
@ -613,8 +714,10 @@ void sb_dsp_init(sb_dsp_t *dsp, int type)
|
|||
{
|
||||
dsp->sb_type = type;
|
||||
|
||||
// Default values. Use sb_dsp_setxxx() methods to change.
|
||||
dsp->sb_irqnum = 7;
|
||||
dsp->sb_8_dmanum = 1;
|
||||
dsp->sb_16_dmanum = 5;
|
||||
|
||||
sb_doreset(dsp);
|
||||
|
||||
|
|
@ -670,7 +773,7 @@ void pollsb(void *p)
|
|||
dsp->sbleftright = !dsp->sbleftright;
|
||||
}
|
||||
else
|
||||
dsp->sbdatl = dsp->sbdatr = dsp->sbdat;
|
||||
dsp->sbdatl = dsp->sbdatr = dsp->sbdat;
|
||||
dsp->sb_8_length--;
|
||||
break;
|
||||
case 0x10: /*Mono signed*/
|
||||
|
|
@ -685,7 +788,7 @@ void pollsb(void *p)
|
|||
dsp->sbleftright = !dsp->sbleftright;
|
||||
}
|
||||
else
|
||||
dsp->sbdatl = dsp->sbdatr = dsp->sbdat;
|
||||
dsp->sbdatl = dsp->sbdatr = dsp->sbdat;
|
||||
dsp->sb_8_length--;
|
||||
break;
|
||||
case 0x20: /*Stereo unsigned*/
|
||||
|
|
@ -737,7 +840,7 @@ void pollsb(void *p)
|
|||
dsp->sbleftright = !dsp->sbleftright;
|
||||
}
|
||||
else
|
||||
dsp->sbdatl = dsp->sbdatr = dsp->sbdat;
|
||||
dsp->sbdatl = dsp->sbdatr = dsp->sbdat;
|
||||
break;
|
||||
|
||||
case ADPCM_26:
|
||||
|
|
@ -771,7 +874,7 @@ void pollsb(void *p)
|
|||
dsp->sbleftright = !dsp->sbleftright;
|
||||
}
|
||||
else
|
||||
dsp->sbdatl = dsp->sbdatr = dsp->sbdat;
|
||||
dsp->sbdatl = dsp->sbdatr = dsp->sbdat;
|
||||
break;
|
||||
|
||||
case ADPCM_2:
|
||||
|
|
@ -801,7 +904,7 @@ void pollsb(void *p)
|
|||
dsp->sbleftright = !dsp->sbleftright;
|
||||
}
|
||||
else
|
||||
dsp->sbdatl = dsp->sbdatr = dsp->sbdat;
|
||||
dsp->sbdatl = dsp->sbdatr = dsp->sbdat;
|
||||
break;
|
||||
|
||||
// default:
|
||||
|
|
@ -839,7 +942,6 @@ void pollsb(void *p)
|
|||
dsp->sbdatr = sb_16_read_dma(dsp);
|
||||
dsp->sb_16_length -= 2;
|
||||
break;
|
||||
|
||||
// default:
|
||||
// fatal("Unrecognised SB 16-bit format %02X\n",sb_16_format);
|
||||
}
|
||||
|
|
@ -867,32 +969,57 @@ void pollsb(void *p)
|
|||
void sb_poll_i(void *p)
|
||||
{
|
||||
sb_dsp_t *dsp = (sb_dsp_t *)p;
|
||||
|
||||
int processed=0;
|
||||
dsp->sb_count_i += dsp->sblatchi;
|
||||
// pclog("PollSBi %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output);
|
||||
if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output)
|
||||
{
|
||||
switch (dsp->sb_8_format)
|
||||
{
|
||||
case 0x00: /*Mono unsigned*/
|
||||
sb_8_write_dma(dsp, 0x80);
|
||||
#ifdef SB_TEST_RECORDING_SAW
|
||||
case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/
|
||||
case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/
|
||||
sb_8_write_dma(dsp, counttest);
|
||||
counttest+=0x10;
|
||||
counttest&=0xFF;
|
||||
dsp->sb_8_length--;
|
||||
break;
|
||||
case 0x10: /*Mono signed*/
|
||||
sb_8_write_dma(dsp, 0x00);
|
||||
case 0x20: /*Unsigned stereo*/
|
||||
case 0x30: /*Signed stereo*/
|
||||
sb_8_write_dma(dsp, counttest);
|
||||
sb_8_write_dma(dsp, counttest);
|
||||
counttest+=0x10;
|
||||
counttest&=0xFF;
|
||||
dsp->sb_8_length -= 2;
|
||||
break;
|
||||
#else
|
||||
case 0x00: /*Mono unsigned As the manual says, only the left channel is recorded*/
|
||||
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80);
|
||||
dsp->sb_8_length--;
|
||||
dsp->record_pos_read+=2;
|
||||
dsp->record_pos_read&=0xFFFF;
|
||||
break;
|
||||
case 0x10: /*Mono signed As the manual says, only the left channel is recorded*/
|
||||
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8));
|
||||
dsp->sb_8_length--;
|
||||
dsp->record_pos_read+=2;
|
||||
dsp->record_pos_read&=0xFFFF;
|
||||
break;
|
||||
case 0x20: /*Stereo unsigned*/
|
||||
sb_8_write_dma(dsp, 0x80);
|
||||
sb_8_write_dma(dsp, 0x80);
|
||||
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8)^0x80);
|
||||
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8)^0x80);
|
||||
dsp->sb_8_length -= 2;
|
||||
dsp->record_pos_read+=2;
|
||||
dsp->record_pos_read&=0xFFFF;
|
||||
break;
|
||||
case 0x30: /*Stereo signed*/
|
||||
sb_8_write_dma(dsp, 0x00);
|
||||
sb_8_write_dma(dsp, 0x00);
|
||||
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8));
|
||||
sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read+1]>>8));
|
||||
dsp->sb_8_length -= 2;
|
||||
dsp->record_pos_read+=2;
|
||||
dsp->record_pos_read&=0xFFFF;
|
||||
break;
|
||||
|
||||
#endif
|
||||
// default:
|
||||
// fatal("Unrecognised SB 8-bit input format %02X\n",sb_8_format);
|
||||
}
|
||||
|
|
@ -901,33 +1028,65 @@ void sb_poll_i(void *p)
|
|||
{
|
||||
// pclog("Input DMA over %i\n",sb_8_autoinit);
|
||||
if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen;
|
||||
else dsp->sb_8_enable = dsp->sbenable = 0;
|
||||
else dsp->sb_8_enable = dsp->sb_enable_i = 0;
|
||||
sb_irq(dsp, 1);
|
||||
}
|
||||
processed=1;
|
||||
}
|
||||
if (dsp->sb_16_enable && !dsp->sb_16_pause && dsp->sb_pausetime < 0 && !dsp->sb_16_output)
|
||||
{
|
||||
switch (dsp->sb_16_format)
|
||||
{
|
||||
case 0x00: /*Unsigned mono*/
|
||||
sb_16_write_dma(dsp, 0x8000);
|
||||
dsp->sb_16_length--;
|
||||
break;
|
||||
case 0x10: /*Signed mono*/
|
||||
sb_16_write_dma(dsp, 0);
|
||||
#ifdef SB_TEST_RECORDING_SAW
|
||||
case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/
|
||||
case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/
|
||||
if (sb_16_write_dma(dsp, counttest))
|
||||
return;
|
||||
counttest+=0x1000;
|
||||
counttest&=0xFFFF;
|
||||
dsp->sb_16_length--;
|
||||
break;
|
||||
case 0x20: /*Unsigned stereo*/
|
||||
sb_16_write_dma(dsp, 0x8000);
|
||||
sb_16_write_dma(dsp, 0x8000);
|
||||
case 0x30: /*Signed stereo*/
|
||||
if (sb_16_write_dma(dsp, counttest))
|
||||
return;
|
||||
sb_16_write_dma(dsp, counttest);
|
||||
counttest+=0x1000;
|
||||
counttest&=0xFFFF;
|
||||
dsp->sb_16_length -= 2;
|
||||
break;
|
||||
#else
|
||||
case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/
|
||||
if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000))
|
||||
return;
|
||||
dsp->sb_16_length--;
|
||||
dsp->record_pos_read+=2;
|
||||
dsp->record_pos_read&=0xFFFF;
|
||||
break;
|
||||
case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/
|
||||
if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]))
|
||||
return;
|
||||
dsp->sb_16_length--;
|
||||
dsp->record_pos_read+=2;
|
||||
dsp->record_pos_read&=0xFFFF;
|
||||
break;
|
||||
case 0x20: /*Unsigned stereo*/
|
||||
if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000))
|
||||
return;
|
||||
sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]^0x8000);
|
||||
dsp->sb_16_length -= 2;
|
||||
dsp->record_pos_read+=2;
|
||||
dsp->record_pos_read&=0xFFFF;
|
||||
break;
|
||||
case 0x30: /*Signed stereo*/
|
||||
sb_16_write_dma(dsp, 0);
|
||||
sb_16_write_dma(dsp, 0);
|
||||
if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]))
|
||||
return;
|
||||
sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read+1]);
|
||||
dsp->sb_16_length -= 2;
|
||||
dsp->record_pos_read+=2;
|
||||
dsp->record_pos_read&=0xFFFF;
|
||||
break;
|
||||
|
||||
#endif
|
||||
// default:
|
||||
// fatal("Unrecognised SB 16-bit input format %02X\n",sb_16_format);
|
||||
}
|
||||
|
|
@ -936,20 +1095,43 @@ void sb_poll_i(void *p)
|
|||
{
|
||||
// pclog("16iDMA over %i\n",sb_16_autoinit);
|
||||
if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen;
|
||||
else dsp->sb_16_enable = dsp->sbenable = 0;
|
||||
else dsp->sb_16_enable = dsp->sb_enable_i = 0;
|
||||
sb_irq(dsp, 0);
|
||||
}
|
||||
processed=1;
|
||||
}
|
||||
//Assume this is direct mode
|
||||
if (!processed)
|
||||
{
|
||||
dsp->record_pos_read+=2;
|
||||
dsp->record_pos_read&=0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void sb_dsp_update(sb_dsp_t *dsp)
|
||||
{
|
||||
/*this "if" implements two things: speaker on/off and buffer cleanup after stopping audio. */
|
||||
if (!dsp->sbenable || dsp->muted)
|
||||
{
|
||||
dsp->sbdatl=0;
|
||||
dsp->sbdatr=0;
|
||||
}
|
||||
for (; dsp->pos < sound_pos_global; dsp->pos++)
|
||||
{
|
||||
dsp->buffer[dsp->pos*2] = dsp->sbdatl;
|
||||
dsp->buffer[dsp->pos*2 + 1] = dsp->sbdatr;
|
||||
}
|
||||
}
|
||||
void sb_dsp_close(sb_dsp_t *dsp)
|
||||
{
|
||||
#ifdef SB_DSP_RECORD_DEBUG
|
||||
if (soundf != 0)
|
||||
{
|
||||
fclose(soundf);
|
||||
soundf=0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,11 +5,13 @@ typedef struct sb_dsp_t
|
|||
int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output;
|
||||
int sb_8_dmanum;
|
||||
int sb_16_length, sb_16_format, sb_16_autoinit, sb_16_pause, sb_16_enable, sb_16_autolen, sb_16_output;
|
||||
int sb_16_dmanum;
|
||||
int sb_pausetime;
|
||||
|
||||
uint8_t sb_read_data[256];
|
||||
int sb_read_wp, sb_read_rp;
|
||||
int sb_speaker;
|
||||
int muted;
|
||||
|
||||
int sb_data_stat;
|
||||
|
||||
|
|
@ -56,15 +58,20 @@ typedef struct sb_dsp_t
|
|||
int asp_data_len;
|
||||
|
||||
int wb_time, wb_full;
|
||||
|
||||
|
||||
int record_pos_read;
|
||||
int record_pos_write;
|
||||
int16_t record_buffer[0xFFFF];
|
||||
int16_t buffer[MAXSOUNDBUFLEN * 2];
|
||||
int pos;
|
||||
} sb_dsp_t;
|
||||
|
||||
void sb_dsp_init(sb_dsp_t *dsp, int type);
|
||||
void sb_dsp_close(sb_dsp_t *dsp);
|
||||
|
||||
void sb_dsp_setirq(sb_dsp_t *dsp, int irq);
|
||||
void sb_dsp_setdma8(sb_dsp_t *dsp, int dma);
|
||||
void sb_dsp_setdma16(sb_dsp_t *dsp, int dma);
|
||||
void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr);
|
||||
|
||||
void sb_dsp_speed_changed(sb_dsp_t *dsp);
|
||||
|
|
|
|||
Loading…
Reference in a new issue