Annotation of hatari/src/audio.c, revision 1.1.1.4

1.1       root        1: /*
                      2:   Hatari
                      3: */
                      4: 
1.1.1.2   root        5: #include <SDL.h>
                      6: 
1.1       root        7: #include "main.h"
                      8: #include "audio.h"
                      9: #include "debug.h"
                     10: #include "dialog.h"
                     11: #include "errlog.h"
                     12: #include "memAlloc.h"
                     13: #include "misc.h"
                     14: #include "sound.h"
                     15: 
                     16: #define WRITE_INIT_POS  ((SoundPlayBackFrequencies[OutputAudioFreqIndex]/50)*2)  /* Write 2/50th ahead of write position */
                     17: 
                     18: /* 11Khz, 22Khz, 44Khz playback */
                     19: int SoundPlayBackFrequencies[] = {
                     20:   11025,  /* PLAYBACK_LOW */
                     21:   22050,  /* PLAYBACK_MEDIUM */
                     22:   44100,  /* PLAYBACK_HIGH */
                     23: };
                     24: 
                     25: /* Bytes to download on each odd/even frame - as 11Khz does not divide by 50 exactly */
                     26: int SoundPlayBackFreqFrameLengths[][2] = {
1.1.1.4 ! root       27:   { 221,220 },  /* 220.5 */
        !            28:   { 441,441 },  /* 441 */
        !            29:   { 882,882 },  /* 882 */
1.1       root       30: };
                     31: 
1.1.1.3   root       32: BOOL bDisableSound=FALSE;
1.1.1.2   root       33: BOOL bSoundWorking=TRUE;                          /* Is sound OK */
                     34: volatile BOOL bPlayingBuffer = FALSE;             /* Is playing buffer? Start when start processing ST */
                     35: int WriteOffset=0;                                /* Write offset into buffer */
1.1.1.3   root       36: int OutputAudioFreqIndex=FREQ_22Khz;              /* Playback rate (11Khz,22Khz or 44Khz) */
1.1       root       37: float PlayVolume=0.0f;
                     38: BOOL bAquireWritePosition=FALSE;
1.1.1.2   root       39: unsigned char *SoundBuffer1, *SoundBuffer2;
                     40: int SoundBufferSize=1024;                         /* Size of sound buffer */
                     41: 
1.1.1.3   root       42: SDL_AudioSpec desiredAudioSpec;                   /* We fill in the desired SDL audio options here */
1.1.1.2   root       43: 
1.1       root       44: 
                     45: 
1.1.1.2   root       46: /*-----------------------------------------------------------------------*/
                     47: /*
                     48:   SDL audio callback function
                     49: */
                     50: void Audio_CallBack(void *userdata, Uint8 *stream, int len)
                     51: {
1.1.1.3   root       52:   memcpy(stream, SoundBuffer2, len);
1.1.1.2   root       53: }
                     54: 
1.1       root       55: 
1.1.1.2   root       56: /*-----------------------------------------------------------------------*/
1.1       root       57: /*
1.1.1.3   root       58:   Create object for sound. Return TRUE if all OK
1.1       root       59:   We use direct access to the primary buffer, set to an unsigned 8-bit mono stream
                     60: */
1.1.1.2   root       61: void Audio_Init(void)
1.1       root       62: {
1.1.1.2   root       63:   /* Is enabled? */
1.1.1.4 ! root       64:   if(bDisableSound)
        !            65:   {
1.1.1.3   root       66:     /* Stop any sound access */
1.1.1.2   root       67:     ErrLog_File("Sound: Disabled\n");
                     68:     bSoundWorking = FALSE;
1.1       root       69:     return;
                     70:   }
                     71: 
1.1.1.4 ! root       72:   /* Init the SDL's audio subsystem: */
        !            73:   if( SDL_WasInit(SDL_INIT_AUDIO)==0 )
        !            74:   {
        !            75:     if( SDL_InitSubSystem(SDL_INIT_AUDIO)<0 )
        !            76:     {
        !            77:       fprintf(stderr, "Could not init audio: %s\n", SDL_GetError() );
        !            78:       bSoundWorking = FALSE;
        !            79:       return;
        !            80:     }
        !            81:   }
        !            82: 
        !            83:   /* Set up SDL audio: */
1.1.1.3   root       84:   desiredAudioSpec.freq = SoundPlayBackFrequencies[OutputAudioFreqIndex];
                     85:   desiredAudioSpec.format = AUDIO_U8;            /* 8 Bit unsigned */
                     86:   desiredAudioSpec.channels = 1;                 /* Mono */
                     87:   desiredAudioSpec.samples = SoundBufferSize;    /* Buffer size */
                     88:   desiredAudioSpec.callback = Audio_CallBack;
                     89:   desiredAudioSpec.userdata = NULL;
                     90:   if( SDL_OpenAudio(&desiredAudioSpec, NULL) )   /* Open audio device */
                     91:   {
1.1.1.4 ! root       92:     fprintf(stderr, "Can't use audio: %s\n", SDL_GetError());
1.1.1.2   root       93:     bSoundWorking = FALSE;
1.1.1.3   root       94:     ConfigureParams.Sound.bEnableSound = FALSE;
1.1.1.2   root       95:     return;
1.1       root       96:   }
1.1.1.3   root       97: 
1.1.1.2   root       98:   /* Create sound buffer, return if error */
                     99:   Audio_CreateSoundBuffer();
1.1.1.3   root      100:   SDL_PauseAudio(FALSE);
1.1       root      101: }
                    102: 
1.1.1.2   root      103: 
                    104: /*-----------------------------------------------------------------------*/
1.1       root      105: /*
                    106:   Free object created for Direct Sound
                    107: */
1.1.1.2   root      108: void Audio_UnInit(void)
1.1       root      109: {
1.1.1.3   root      110:   SDL_PauseAudio(TRUE);
1.1.1.2   root      111: 
                    112:   /* Free sound buffer */
                    113:   Audio_FreeSoundBuffer();
                    114: 
                    115:   SDL_CloseAudio();
1.1       root      116: }
                    117: 
1.1.1.2   root      118: 
                    119: /*-----------------------------------------------------------------------*/
1.1       root      120: /*
                    121:   Create sound buffer to write samples into
                    122: */
1.1.1.2   root      123: BOOL Audio_CreateSoundBuffer(void)
1.1       root      124: {
1.1.1.2   root      125:   int bufferlen;
1.1       root      126: 
1.1.1.2   root      127:   /* Allocate memory for the 2 sound buffers: */
                    128:   bufferlen = SoundBufferSize + SoundPlayBackFreqFrameLengths[FREQ_44Khz][0];
                    129:   SoundBuffer1 = malloc( bufferlen );
                    130:   if( !SoundBuffer1 ) {
                    131:     bSoundWorking = FALSE;
1.1       root      132:     return(FALSE);
                    133:   }
1.1.1.2   root      134:   memset(SoundBuffer1, 128, bufferlen);
                    135: 
                    136:   SoundBuffer2 = malloc( bufferlen );
                    137:   if( !SoundBuffer2 ) {
                    138:     bSoundWorking = FALSE;
                    139:     free( SoundBuffer1 );
                    140:     SoundBuffer1 = NULL;
1.1       root      141:     return(FALSE);
                    142:   }
1.1.1.2   root      143:   memset(SoundBuffer2, 128, bufferlen);
1.1       root      144: 
1.1.1.2   root      145:   /* All OK */
                    146:   bSoundWorking = TRUE;
                    147:   /* And begin */
                    148:   Audio_ResetBuffer();
1.1       root      149: 
                    150:   return(TRUE);
                    151: }
                    152: 
1.1.1.2   root      153: 
                    154: /*-----------------------------------------------------------------------*/
1.1       root      155: /*
                    156:   Free sound buffer
                    157: */
1.1.1.2   root      158: void Audio_FreeSoundBuffer(void)
1.1       root      159: {
1.1.1.2   root      160:   /* Stop */
                    161:   Audio_StopBuffer();
                    162:   /* And free */
                    163:   if( SoundBuffer1 )
                    164:     free(SoundBuffer1);
1.1.1.3   root      165:   if( SoundBuffer2 )
1.1.1.2   root      166:     free(SoundBuffer2);
1.1       root      167: }
                    168: 
1.1.1.2   root      169: 
                    170: /*-----------------------------------------------------------------------*/
1.1       root      171: /*
1.1.1.3   root      172:   Set audio playback frequency variable, pass as PLAYBACK_xxxx
1.1       root      173: */
1.1.1.2   root      174: void Audio_SetOutputAudioFreq(int Frequency)
1.1       root      175: {
1.1.1.2   root      176:   /* Set new frequency, index into SoundPlayBackFrequencies[] */
1.1       root      177:   OutputAudioFreqIndex = Frequency;
1.1.1.3   root      178: 
                    179:   /* Re-open SDL audio interface... */
                    180:   Audio_UnInit();
                    181:   Audio_Init();
1.1       root      182: }
                    183: 
1.1.1.2   root      184: 
                    185: /*-----------------------------------------------------------------------*/
1.1       root      186: /*
                    187:   Reset sound buffer, so plays from correct position
                    188: */
1.1.1.2   root      189: void Audio_ResetBuffer(void)
1.1       root      190: {
1.1.1.2   root      191:   /* Get new 'write' position on next frame */
1.1       root      192:   bAquireWritePosition = TRUE;
                    193: }
                    194: 
1.1.1.2   root      195: 
                    196: /*-----------------------------------------------------------------------*/
1.1       root      197: /*
                    198:   Stop sound buffer
                    199: */
1.1.1.2   root      200: void Audio_StopBuffer(void)
1.1       root      201: {
1.1.1.2   root      202:   /* Stop from playing */
1.1.1.3   root      203:   SDL_PauseAudio(TRUE);
1.1       root      204:   bPlayingBuffer = FALSE;
                    205: }
                    206: 
1.1.1.2   root      207: 
                    208: /*-----------------------------------------------------------------------*/
1.1       root      209: /*
                    210:   Scale sample value(-128...127) according to 'PlayVolume' setting
                    211: */
1.1.1.2   root      212: char Audio_ModifyVolume(char Sample)
1.1       root      213: {
1.1.1.2   root      214:   /* If full volume, just use current value */
1.1       root      215:   if (PlayVolume==1.0f)
                    216:     return(Sample);
                    217: 
1.1.1.2   root      218:   /* Else, scale volume */
1.1       root      219:   Sample = (char)((float)Sample*PlayVolume);
                    220: 
                    221:   return(Sample);
                    222: }
                    223: 
1.1.1.2   root      224: 
                    225: /*-----------------------------------------------------------------------*/
1.1       root      226: /*
1.1.1.2   root      227:   Write samples into Direct Sound buffer at 'Offset',
                    228:   taking care to wrap around. Pass NULL to write zero's.
1.1       root      229: */
1.1.1.2   root      230: void Audio_WriteSamplesIntoBuffer(char *pSamples,int Index,int Length,int RampSetting)
1.1       root      231: {
1.1.1.2   root      232:   void *lpWrite;
1.1       root      233:   unsigned char *pBuffer;
1.1.1.2   root      234:   short dwLenBytes;
                    235:   int i;
1.1       root      236: 
1.1.1.2   root      237:   /* Modify ramp volume - ramp down if sound not enabled or not in windows mouse mode */
1.1.1.3   root      238:   if ( (((RampSetting==RAMP_DOWN) || (!ConfigureParams.Sound.bEnableSound)) && (PlayVolume>0.0f)) ) {
1.1       root      239:     PlayVolume -= RAMP_DOWN_VOLUME_LEVEL;
                    240:     if (PlayVolume<=0.0f)
                    241:       PlayVolume = 0.0f;
                    242:   }
                    243:   else if ( (RampSetting==RAMP_UP) && (PlayVolume<1.0f) ) {
                    244:     PlayVolume += RAMP_UP_VOLUME_LEVEL;
                    245:     if (PlayVolume>=1.0f)
                    246:       PlayVolume = 1.0f;
                    247:   }
                    248: 
1.1.1.2   root      249:   if (SoundBuffer1) {
                    250: 
                    251:     /* Do need to reset 'write' position? */
1.1       root      252:     if (bAquireWritePosition) {
1.1.1.2   root      253:       WriteOffset = 0;
1.1       root      254:       bAquireWritePosition = FALSE;
                    255:     }
                    256: 
1.1.1.2   root      257:     lpWrite = SoundBuffer1 + WriteOffset;
                    258:     dwLenBytes = Length;
1.1       root      259: 
1.1.1.2   root      260:     /* Write section, convert to 'unsigned' and write '128'(unsigned) if passed NULL */
                    261:     if ( (dwLenBytes>0) && (lpWrite) ) {
                    262:       if (pSamples) {
                    263:         pBuffer = (unsigned char *)lpWrite;
                    264:         for(i=0; i<(int)dwLenBytes; i++) {
                    265:           *pBuffer++ = Audio_ModifyVolume(pSamples[Index])+128;
                    266:           Index = (Index+1)&4095;
1.1       root      267:         }
                    268:       }
1.1.1.2   root      269:       else
                    270:         memset(lpWrite,128,dwLenBytes);
1.1       root      271:     }
                    272: 
1.1.1.2   root      273:     /* Update write buffer */
1.1       root      274:     if (pSamples) {
                    275:       WriteOffset += Length;
1.1.1.2   root      276:       if (WriteOffset>=SoundBufferSize) {
                    277:         /* If the buffer is full, swap the buffers and copy overflow space to the new buffer. */
                    278:         SDL_LockAudio();
                    279:         WriteOffset -= SoundBufferSize;
                    280:         memcpy(SoundBuffer2, SoundBuffer1+SoundBufferSize, WriteOffset);  /* Copy overflow to the next buffer */
                    281:         pBuffer = SoundBuffer2;
                    282:         SoundBuffer2 = SoundBuffer1;            /* Swap the buffers */
                    283:         SoundBuffer1 = pBuffer;
                    284:         SDL_UnlockAudio();
                    285:       }
1.1       root      286:     }
                    287: 
1.1.1.2   root      288:     /* Are we playing? */
1.1       root      289:     if (!bPlayingBuffer) {
1.1.1.3   root      290:       SDL_PauseAudio(FALSE);
1.1.1.2   root      291:       Audio_ResetBuffer();
1.1       root      292:       bPlayingBuffer = TRUE;
                    293:     }
                    294:     else {
1.1.1.2   root      295:       /* Check here for play/write pointers getting away from each other and set 'bAquireWritePosition' to reset */
                    296:       //lpDSBPrimBuffer->GetCurrentPosition(NULL,(DWORD *)&WriteCursor);
                    297:       /* If the writecursor is too-far away from where we think it should be cause a reset */
                    298:       //CursorDiff = WriteOffset-WriteCursor;
                    299:       /* Check for overlap */
                    300:       //if (CursorDiff<0)
                    301:       //  CursorDiff = (WriteOffset+PrimaryBufferSize)-WriteCursor;
                    302:       /* So, does need reset? */
                    303:       //if (abs(CursorDiff)>(WRITE_INIT_POS*2))
                    304:       //  Audio_ResetBuffer();
1.1       root      305:     }
                    306:   }
1.1.1.2   root      307: 
1.1       root      308: }

unix.superglobalmegacorp.com

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