Annotation of previous/src/snd.c, revision 1.1.1.3

1.1       root        1: #include "main.h"
                      2: #include "configuration.h"
                      3: #include "m68000.h"
                      4: #include "sysdeps.h"
                      5: #include "cycInt.h"
                      6: #include "audio.h"
                      7: #include "dma.h"
                      8: #include "snd.h"
1.1.1.2   root        9: #include "kms.h"
1.1       root       10: 
                     11: #define LOG_SND_LEVEL   LOG_DEBUG
                     12: #define LOG_VOL_LEVEL   LOG_DEBUG
                     13: 
                     14: /* Initialize the audio system */
1.1.1.2   root       15: static bool   sndout_inited;
                     16: static bool   sound_output_active = false;
                     17: static bool   sndin_inited;
                     18: static bool   sound_input_active = false;
                     19: static Uint8* snd_buffer = NULL;
                     20: 
                     21: static void sound_init(void) {
                     22:     if(snd_buffer)
                     23:         free(snd_buffer);
                     24:     snd_buffer = NULL;
1.1       root       25:     if (!sndout_inited && ConfigureParams.Sound.bEnableSound) {
                     26:         Log_Printf(LOG_WARN, "[Audio] Initializing audio device.");
                     27:         Audio_Output_Init();
                     28:         sndout_inited=true;
                     29:     }
                     30: }
                     31: 
1.1.1.2   root       32: static void sound_uninit(void) {
                     33:     if(snd_buffer)
                     34:         free(snd_buffer);
                     35:     snd_buffer = NULL;
1.1       root       36:     if(sndout_inited) {
                     37:         Log_Printf(LOG_WARN, "[Audio] Uninitializing audio device.");
                     38:         sndout_inited=false;
                     39:         Audio_Output_UnInit();
                     40:     }
                     41: }
                     42: 
                     43: void Sound_Reset(void) {
                     44:     sound_uninit();
                     45:     sound_init();
                     46:     if (sound_output_active && sndout_inited) {
                     47:         Audio_Output_Enable(true);
                     48:     }
                     49: }
                     50: 
1.1.1.2   root       51: void Sound_Pause(bool pause) {
                     52:     if (pause) {
                     53:         if (sndout_inited) {
                     54:             Log_Printf(LOG_WARN, "[Audio] Uninitializing audio output device (pause).");
                     55:             sndout_inited=false;
                     56:             Audio_Output_UnInit();
                     57:         }
                     58:         if (sndin_inited) {
                     59:             Log_Printf(LOG_WARN, "[Audio] Uninitializing audio input device (pause).");
                     60:             sndin_inited=false;
                     61:             Audio_Input_UnInit();
                     62:         }
                     63:     } else {
                     64:         if (!sndout_inited && ConfigureParams.Sound.bEnableSound) {
                     65:             Log_Printf(LOG_WARN, "[Audio] Initializing audio output device (resume).");
                     66:             Audio_Output_Init();
                     67:             sndout_inited=true;
                     68:         }
                     69:         if (!sndin_inited && sound_input_active && ConfigureParams.Sound.bEnableSound) {
                     70:             Log_Printf(LOG_WARN, "[Audio] Initializing audio input device (resume).");
                     71:             Audio_Input_Init();
                     72:             sndin_inited=true;
                     73:         }
                     74:         if (sound_output_active && sndout_inited) {
                     75:             Audio_Output_Enable(true);
                     76:         }
                     77:         if (sound_input_active && sndin_inited) {
                     78:             Audio_Input_Enable(true);
                     79:         }
                     80:     }
                     81: }
1.1       root       82: 
                     83: /* Start and stop sound output */
                     84: struct {
                     85:     Uint8 mode;
                     86:     Uint8 mute;
                     87:     Uint8 lowpass;
                     88:     Uint8 volume[2]; /* 0 = left, 1 = right */
                     89: } sndout_state;
                     90: 
                     91: /* Maximum volume (really is attenuation) */
                     92: #define SND_MAX_VOL 43
                     93: 
                     94: /* Valid modes */
                     95: #define SND_MODE_NORMAL 0x00
                     96: #define SND_MODE_DBL_RP 0x10
                     97: #define SND_MODE_DBL_ZF 0x30
                     98: 
                     99: /* Function prototypes */
1.1.1.2   root      100: int  snd_send_samples(Uint8* bufffer, int len);
1.1       root      101: void snd_make_normal_samples(Uint8 *buf, int len);
                    102: void snd_make_double_samples(Uint8 *buf, int len, bool repeat);
                    103: void snd_adjust_volume_and_lowpass(Uint8 *buf, int len);
                    104: void sndout_queue_put(Uint8 *buf, int len);
                    105: 
                    106: void snd_start_output(Uint8 mode) {
                    107:     sndout_state.mode = mode;
                    108:     /* Starting SDL Audio */
                    109:     if (sndout_inited) {
                    110:         Audio_Output_Enable(true);
                    111:     } else {
1.1.1.2   root      112:         Log_Printf(LOG_SND_LEVEL, "[Audio] Not starting. Audio output device not initialized.");
1.1       root      113:     }
                    114:     /* Starting sound output loop */
                    115:     if (!sound_output_active) {
1.1.1.2   root      116:         Log_Printf(LOG_SND_LEVEL, "[Sound] Starting output loop.");
1.1       root      117:         sound_output_active = true;
1.1.1.2   root      118:         CycInt_AddRelativeInterruptCycles(10, INTERRUPT_SND_OUT);
1.1       root      119:     } else { /* Even re-enable loop if we are already active. This lowers the delay. */
1.1.1.2   root      120:         Log_Printf(LOG_DEBUG, "[Sound] Restarting output loop.");
                    121:         CycInt_AddRelativeInterruptCycles(10, INTERRUPT_SND_OUT);
1.1       root      122:     }
                    123: }
                    124: 
                    125: void snd_stop_output(void) {
1.1.1.2   root      126:     sound_output_active=false;
                    127: }
                    128: 
                    129: void snd_start_input(Uint8 mode) {
                    130:     
                    131:     /* Starting SDL Audio */
                    132:     if (sndin_inited) {
                    133:         Audio_Input_Enable(true);
                    134:     } else if (ConfigureParams.Sound.bEnableSound) {
                    135:         sndin_inited = true;
                    136:         Audio_Input_Init();
                    137:         Audio_Input_Enable(true);
1.1       root      138:     }
1.1.1.2   root      139:     /* Starting sound output loop */
                    140:     if (!sound_input_active) {
                    141:         Log_Printf(LOG_SND_LEVEL, "[Sound] Starting input loop.");
                    142:         sound_input_active = true;
                    143:         CycInt_AddRelativeInterruptCycles(10, INTERRUPT_SND_IN);
                    144:     } else { /* Even re-enable loop if we are already active. This lowers the delay. */
                    145:         Log_Printf(LOG_DEBUG, "[Sound] Restarting input loop.");
                    146:         CycInt_AddRelativeInterruptCycles(10, INTERRUPT_SND_IN);
                    147:     }
                    148: }
                    149: 
                    150: void snd_stop_input(void) {
                    151:     sound_input_active=false;
                    152:     sndin_inited = false;
                    153:     Audio_Input_UnInit();
1.1       root      154: }
                    155: 
1.1.1.2   root      156: /* Sound IO loops */
                    157: 
                    158: static void do_dma_sndout_intr(void) {
                    159:     if(snd_buffer) {
                    160:         dma_sndout_intr();
                    161:         free(snd_buffer);
                    162:         snd_buffer = NULL;
                    163:     }
                    164: }
1.1       root      165: 
1.1.1.2   root      166: /*
                    167:  At a playback rate of 44.1kHz a sample takes about 23 microseconds.
                    168:  Assuming that the emulation runs at least 1/3 as fast as a real m68k
                    169:  checking the sound queue every 8 microseconds should be ok.
                    170: */
                    171: static const int SND_CHECK_DELAY = 8;
                    172: void SND_Out_Handler(void) {
                    173:     int len;
1.1       root      174: 
                    175:     CycInt_AcknowledgeInterrupt();
                    176:     
1.1.1.2   root      177:     if (!sound_output_active) {
                    178:         return;
                    179:     }
                    180: 
                    181:     if (sndout_inited && Audio_Output_Queue_Size() > AUDIO_BUFFER_SAMPLES * 2) {
                    182:         CycInt_AddRelativeInterruptUs(SND_CHECK_DELAY * AUDIO_BUFFER_SAMPLES, 0, INTERRUPT_SND_OUT);
                    183:         return;
                    184:     }
                    185:     
                    186:     do_dma_sndout_intr();
                    187:     snd_buffer = dma_sndout_read_memory(&len);
1.1       root      188:     
1.1.1.2   root      189:     if (len) {
                    190:         len = snd_send_samples(snd_buffer, len);
                    191:         len = (len / 4) + 1;
                    192:         CycInt_AddRelativeInterruptUs(SND_CHECK_DELAY * len, 0, INTERRUPT_SND_OUT);
1.1       root      193:     } else {
1.1.1.2   root      194:         kms_sndout_underrun();
                    195:         /* Call do_dma_sndout_intr() a little bit later */
                    196:         CycInt_AddRelativeInterruptUs(100, 0, INTERRUPT_SND_OUT);
                    197:     }
                    198: }
                    199: 
                    200: bool snd_output_active() {
                    201:     return sound_output_active;
                    202: }
                    203: 
                    204: void SND_In_Handler(void) {
                    205:     CycInt_AcknowledgeInterrupt();
                    206:     
                    207:     int dma_done = dma_sndin_write_memory();
                    208:        
                    209:        if (dma_done) {
                    210:                if(snd_input_active()) {
                    211:                        kms_sndin_overrun();
                    212:                }
                    213:        } else {
                    214:                CycInt_AddRelativeInterruptUs(10000, 0, INTERRUPT_SND_IN);
                    215:        }
                    216: }
                    217: 
                    218: bool snd_input_active() {
                    219:     return sound_input_active;
                    220: }
                    221: 
                    222: /* This functions generates 8-bit ulaw samples from 16 bit pcm audio */
                    223: #define BIAS 0x84               /* define the add-in bias for 16 bit samples */
                    224: #define CLIP 32635
                    225: 
                    226: Uint8 snd_make_ulaw(Sint16 sample) {
                    227:        static Sint16 exp_lut[256] = {
                    228:                0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
                    229:                4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
                    230:                5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
                    231:                5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
                    232:                6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                    233:                6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                    234:                6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                    235:                6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                    236:                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                    237:                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                    238:                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                    239:                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                    240:                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                    241:                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                    242:                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
                    243:                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
                    244:        };
                    245:        Sint16 sign, exponent, mantissa;
                    246:        Uint8 ulawbyte;
                    247:        
                    248:        /** get the sample into sign-magnitude **/
                    249:        sign = (sample >> 8) & 0x80;        /* set aside the sign */
                    250:        if (sign != 0) {
                    251:                sample = -sample;         /* get magnitude */
                    252:        }
                    253:        /* sample can be zero because we can overflow in the inversion,
                    254:         * checking against the unsigned version solves this */
                    255:        if (((Uint16) sample) > CLIP)
                    256:                sample = CLIP;            /* clip the magnitude */
                    257:        
                    258:        /** convert from 16 bit linear to ulaw **/
                    259:        sample = sample + BIAS;
                    260:        exponent = exp_lut[(sample >> 7) & 0xFF];
                    261:        mantissa = (sample >> (exponent + 3)) & 0x0F;
                    262:        ulawbyte = ~(sign | (exponent << 4) | mantissa);
                    263:        
                    264:        return ulawbyte;
1.1       root      265: }
                    266: 
                    267: 
                    268: /* These functions put samples to a buffer for further processing */
1.1.1.2   root      269: void snd_make_double_samples(Uint8 *buffer, int len, bool repeat) {
                    270:     for (int i=len - 4; i >= 0; i -= 4) {
                    271:         buffer[i*2+7] = repeat ? buffer[i+3] : 0; /* repeat or zero-fill */
                    272:         buffer[i*2+6] = repeat ? buffer[i+2] : 0; /* repeat or zero-fill */
                    273:         buffer[i*2+5] = repeat ? buffer[i+1] : 0; /* repeat or zero-fill */
                    274:         buffer[i*2+4] = repeat ? buffer[i+0] : 0; /* repeat or zero-fill */
                    275:         buffer[i*2+3] =          buffer[i+3];
                    276:         buffer[i*2+2] =          buffer[i+2];
                    277:         buffer[i*2+1] =          buffer[i+1];
                    278:         buffer[i*2+0] =          buffer[i+0];
1.1       root      279:     }
                    280: }
                    281: 
1.1.1.2   root      282: 
                    283: void snd_make_normal_samples(Uint8 *buffer, int len) {
                    284:     // do nothing
1.1       root      285: }
                    286: 
                    287: 
                    288: /* This function processes and sends out our samples */
1.1.1.2   root      289: int snd_send_samples(Uint8* buffer, int len) {
1.1       root      290:     switch (sndout_state.mode) {
                    291:         case SND_MODE_NORMAL:
1.1.1.2   root      292:             snd_make_normal_samples(buffer, len);
                    293:             snd_adjust_volume_and_lowpass(buffer, len);
                    294:             Audio_Output_Queue(buffer, len);
                    295:             return len;
1.1       root      296:         case SND_MODE_DBL_RP:
1.1.1.2   root      297:             snd_make_double_samples(buffer, len, true);
                    298:             snd_adjust_volume_and_lowpass(buffer, 2*len);
                    299:             Audio_Output_Queue(buffer, len);
                    300:             Audio_Output_Queue(buffer+len, len);
                    301:             return 2*len;
1.1       root      302:         case SND_MODE_DBL_ZF:
1.1.1.2   root      303:             snd_make_double_samples(buffer, len, false);
                    304:             snd_adjust_volume_and_lowpass(buffer, 2*len);
                    305:             Audio_Output_Queue(buffer, len);
                    306:             Audio_Output_Queue(buffer+len, len);
                    307:             return 2*len;
1.1       root      308:         default:
                    309:             Log_Printf(LOG_WARN, "[Sound] Error: Unknown sound output mode!");
1.1.1.2   root      310:             return 0;
1.1       root      311:     }
                    312: }
                    313: 
                    314: #if 1 /* FIXME: Is this correct? */
                    315: /* This is a simple lowpass filter */
                    316: static Sint16 snd_lowpass_filter(Sint16 insample, bool left) {
                    317:     Sint16 outsample;
                    318:     static Sint16 lfiltersample[2] = {0,0};
                    319:     static Sint16 rfiltersample[2] = {0,0};
                    320:     
                    321:     if (left) {
                    322:         outsample = (lfiltersample[0] + (lfiltersample[1]<<1) + insample)>>2;
                    323:         lfiltersample[0] = lfiltersample[1];
                    324:         lfiltersample[1] = insample;
                    325:     } else {
                    326:         outsample = (rfiltersample[0] + (rfiltersample[1]<<1) + insample)>>2;
                    327:         rfiltersample[0] = rfiltersample[1];
                    328:         rfiltersample[1] = insample;
                    329:     }
                    330:     return outsample;
                    331: }
                    332: #endif
                    333: 
                    334: /* This function adjusts sound output volume */
                    335: void snd_adjust_volume_and_lowpass(Uint8 *buf, int len) {
                    336:     int i;
                    337:     Sint16 ldata, rdata;
                    338:     float ladjust, radjust;
1.1.1.2   root      339:     if (sndout_state.mute) {
                    340:         for (i=0; i<len; i++) {
                    341:             buf[i] = 0;
                    342:         }
                    343:     } else if (sndout_state.volume[0] || sndout_state.volume[1] || sndout_state.lowpass) {
1.1       root      344:         ladjust = (sndout_state.volume[0]==0)?1:(1-log(sndout_state.volume[0])/log(SND_MAX_VOL));
                    345:         radjust = (sndout_state.volume[1]==0)?1:(1-log(sndout_state.volume[1])/log(SND_MAX_VOL));
                    346:         
                    347:         for (i=0; i<len; i+=4) {
                    348:             ldata = (Sint16)((buf[i]<<8)|buf[i+1]);
                    349:             rdata = (Sint16)((buf[i+2]<<8)|buf[i+3]);
                    350: #if 1       /* Append lowpass filter */
                    351:             if (sndout_state.lowpass) {
                    352:                 ldata = snd_lowpass_filter(ldata, true);
                    353:                 rdata = snd_lowpass_filter(rdata, false);
                    354:             }
                    355: #endif
                    356:             ldata = ldata*ladjust;
                    357:             rdata = rdata*radjust;
                    358:             buf[i] = ldata>>8;
                    359:             buf[i+1] = ldata;
                    360:             buf[i+2] = rdata>>8;
                    361:             buf[i+3] = rdata;
                    362:         }
                    363:     }
                    364: }
                    365: 
                    366: 
                    367: /* Internal volume control register access (shifted in left to right)
                    368:  *
                    369:  * xxx ---- ----  unused bits
                    370:  * --- xx-- ----  channel (0x80 = right, 0x40 = left)
                    371:  * --- --xx xxxx  volume
                    372:  */
                    373: 
                    374: Uint8 tmp_vol;
                    375: Uint8 chan_lr;
                    376: int bit_num;
                    377: 
1.1.1.2   root      378: static void snd_access_volume_reg(Uint8 databit) {
1.1       root      379:     Log_Printf(LOG_VOL_LEVEL, "[Sound] Interface shift bit %i (%i).",bit_num,databit?1:0);
                    380:     
                    381:     if (bit_num<3) {
                    382:         /* nothing to do */
                    383:     } else if (bit_num<5) {
                    384:         chan_lr = (chan_lr<<1)|(databit?1:0);
                    385:     } else if (bit_num<11) {
                    386:         tmp_vol = (tmp_vol<<1)|(databit?1:0);
                    387:     }
                    388:     bit_num++;
                    389: }
                    390: 
1.1.1.2   root      391: static void snd_volume_interface_reset(void) {
1.1       root      392:     Log_Printf(LOG_VOL_LEVEL, "[Sound] Interface reset.");
                    393:     
                    394:     bit_num = 0;
                    395:     chan_lr = 0;
                    396:     tmp_vol = 0;
                    397: }
                    398: 
1.1.1.2   root      399: static void snd_save_volume_reg(void) {
1.1       root      400:     if (bit_num!=11) {
                    401:         Log_Printf(LOG_WARN, "[Sound] Incomplete volume transfer (%i bits).",bit_num);
                    402:         return;
                    403:     }
                    404:     if (tmp_vol>SND_MAX_VOL) {
                    405:         Log_Printf(LOG_WARN, "[Sound] Volume limit exceeded (%i).",tmp_vol);
                    406:         tmp_vol=SND_MAX_VOL;
                    407:     }
                    408:     if (chan_lr&1) {
                    409:         Log_Printf(LOG_WARN, "[Sound] Setting volume of left channel to %i",tmp_vol);
                    410:         sndout_state.volume[0] = tmp_vol;
                    411:     }
                    412:     if (chan_lr&2) {
                    413:         Log_Printf(LOG_WARN, "[Sound] Setting volume of right channel to %i",tmp_vol);
                    414:         sndout_state.volume[1] = tmp_vol;
                    415:     }
                    416: }
                    417: 
                    418: /* This function fills the internal volume register */
                    419: #define SND_SPEAKER_ENABLE  0x10
                    420: #define SND_LOWPASS_ENABLE  0x08
                    421: 
                    422: #define SND_INTFC_CLOCK     0x04
                    423: #define SND_INTFC_DATA      0x02
                    424: #define SND_INTFC_STROBE    0x01
                    425: 
                    426: Uint8 old_data;
                    427: 
                    428: void snd_gpo_access(Uint8 data) {
                    429:     Log_Printf(LOG_VOL_LEVEL, "[Sound] Control logic access: %02X",data);
                    430:     
                    431:     sndout_state.mute = data&SND_SPEAKER_ENABLE;
                    432:     sndout_state.lowpass = data&SND_LOWPASS_ENABLE;
                    433:     
                    434:     if (data&SND_INTFC_STROBE) {
                    435:         snd_save_volume_reg();
                    436:     } else if ((data&SND_INTFC_CLOCK) && !(old_data&SND_INTFC_CLOCK)) {
                    437:         snd_access_volume_reg(data&SND_INTFC_DATA);
                    438:     } else if ((data&SND_INTFC_CLOCK) == (old_data&SND_INTFC_CLOCK)) {
                    439:         snd_volume_interface_reset();
                    440:     }
                    441:     old_data = data;
                    442: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.