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

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] = {
                     27:   221,220,  /* 220.5 */
                     28:   441,441,  /* 441 */
                     29:   882,882,  /* 882 */
                     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: {
                     63: 
1.1.1.2   root       64:   /* Is enabled? */
                     65:   if (bDisableSound) {
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.2   root       72:   /* Init SDL audio: */
1.1.1.3 ! root       73:   desiredAudioSpec.freq = SoundPlayBackFrequencies[OutputAudioFreqIndex];
        !            74:   desiredAudioSpec.format = AUDIO_U8;            /* 8 Bit unsigned */
        !            75:   desiredAudioSpec.channels = 1;                 /* Mono */
        !            76:   desiredAudioSpec.samples = SoundBufferSize;    /* Buffer size */
        !            77:   desiredAudioSpec.callback = Audio_CallBack;
        !            78:   desiredAudioSpec.userdata = NULL;
        !            79:   if( SDL_OpenAudio(&desiredAudioSpec, NULL) )   /* Open audio device */
        !            80:   {
        !            81:     fprintf(stderr, "Can't use audio!\n");
1.1.1.2   root       82:     bSoundWorking = FALSE;
1.1.1.3 ! root       83:     ConfigureParams.Sound.bEnableSound = FALSE;
1.1.1.2   root       84:     return;
1.1       root       85:   }
1.1.1.3 ! root       86: 
1.1.1.2   root       87:   /* Create sound buffer, return if error */
                     88:   Audio_CreateSoundBuffer();
1.1.1.3 ! root       89:   SDL_PauseAudio(FALSE);
1.1       root       90: }
                     91: 
1.1.1.2   root       92: 
                     93: /*-----------------------------------------------------------------------*/
1.1       root       94: /*
                     95:   Free object created for Direct Sound
                     96: */
1.1.1.2   root       97: void Audio_UnInit(void)
1.1       root       98: {
1.1.1.3 ! root       99:   SDL_PauseAudio(TRUE);
1.1.1.2   root      100: 
                    101:   /* Free sound buffer */
                    102:   Audio_FreeSoundBuffer();
                    103: 
                    104:   SDL_CloseAudio();
1.1       root      105: }
                    106: 
1.1.1.2   root      107: 
                    108: /*-----------------------------------------------------------------------*/
1.1       root      109: /*
                    110:   Create sound buffer to write samples into
                    111: */
1.1.1.2   root      112: BOOL Audio_CreateSoundBuffer(void)
1.1       root      113: {
1.1.1.2   root      114:   int bufferlen;
1.1       root      115: 
1.1.1.2   root      116:   /* Allocate memory for the 2 sound buffers: */
                    117:   bufferlen = SoundBufferSize + SoundPlayBackFreqFrameLengths[FREQ_44Khz][0];
                    118:   SoundBuffer1 = malloc( bufferlen );
                    119:   if( !SoundBuffer1 ) {
                    120:     bSoundWorking = FALSE;
1.1       root      121:     return(FALSE);
                    122:   }
1.1.1.2   root      123:   memset(SoundBuffer1, 128, bufferlen);
                    124: 
                    125:   SoundBuffer2 = malloc( bufferlen );
                    126:   if( !SoundBuffer2 ) {
                    127:     bSoundWorking = FALSE;
                    128:     free( SoundBuffer1 );
                    129:     SoundBuffer1 = NULL;
1.1       root      130:     return(FALSE);
                    131:   }
1.1.1.2   root      132:   memset(SoundBuffer2, 128, bufferlen);
1.1       root      133: 
1.1.1.2   root      134:   /* All OK */
                    135:   bSoundWorking = TRUE;
                    136:   /* And begin */
                    137:   Audio_ResetBuffer();
1.1       root      138: 
                    139:   return(TRUE);
                    140: }
                    141: 
1.1.1.2   root      142: 
                    143: /*-----------------------------------------------------------------------*/
1.1       root      144: /*
                    145:   Free sound buffer
                    146: */
1.1.1.2   root      147: void Audio_FreeSoundBuffer(void)
1.1       root      148: {
1.1.1.2   root      149:   /* Stop */
                    150:   Audio_StopBuffer();
                    151:   /* And free */
                    152:   if( SoundBuffer1 )
                    153:     free(SoundBuffer1);
1.1.1.3 ! root      154:   if( SoundBuffer2 )
1.1.1.2   root      155:     free(SoundBuffer2);
1.1       root      156: }
                    157: 
1.1.1.2   root      158: 
                    159: /*-----------------------------------------------------------------------*/
1.1       root      160: /*
1.1.1.3 ! root      161:   Set audio playback frequency variable, pass as PLAYBACK_xxxx
1.1       root      162: */
1.1.1.2   root      163: void Audio_SetOutputAudioFreq(int Frequency)
1.1       root      164: {
1.1.1.2   root      165:   /* Set new frequency, index into SoundPlayBackFrequencies[] */
1.1       root      166:   OutputAudioFreqIndex = Frequency;
1.1.1.3 ! root      167: 
        !           168:   /* Re-open SDL audio interface... */
        !           169:   Audio_UnInit();
        !           170:   Audio_Init();
1.1       root      171: }
                    172: 
1.1.1.2   root      173: 
                    174: /*-----------------------------------------------------------------------*/
1.1       root      175: /*
                    176:   Reset sound buffer, so plays from correct position
                    177: */
1.1.1.2   root      178: void Audio_ResetBuffer(void)
1.1       root      179: {
1.1.1.2   root      180:   /* Get new 'write' position on next frame */
1.1       root      181:   bAquireWritePosition = TRUE;
                    182: }
                    183: 
1.1.1.2   root      184: 
                    185: /*-----------------------------------------------------------------------*/
1.1       root      186: /*
                    187:   Stop sound buffer
                    188: */
1.1.1.2   root      189: void Audio_StopBuffer(void)
1.1       root      190: {
1.1.1.2   root      191:   /* Stop from playing */
1.1.1.3 ! root      192:   SDL_PauseAudio(TRUE);
1.1       root      193:   bPlayingBuffer = FALSE;
                    194: }
                    195: 
1.1.1.2   root      196: 
                    197: /*-----------------------------------------------------------------------*/
1.1       root      198: /*
                    199:   Scale sample value(-128...127) according to 'PlayVolume' setting
                    200: */
1.1.1.2   root      201: char Audio_ModifyVolume(char Sample)
1.1       root      202: {
1.1.1.2   root      203:   /* If full volume, just use current value */
1.1       root      204:   if (PlayVolume==1.0f)
                    205:     return(Sample);
                    206: 
1.1.1.2   root      207:   /* Else, scale volume */
1.1       root      208:   Sample = (char)((float)Sample*PlayVolume);
                    209: 
                    210:   return(Sample);
                    211: }
                    212: 
1.1.1.2   root      213: 
                    214: /*-----------------------------------------------------------------------*/
1.1       root      215: /*
1.1.1.2   root      216:   Write samples into Direct Sound buffer at 'Offset',
                    217:   taking care to wrap around. Pass NULL to write zero's.
1.1       root      218: */
1.1.1.2   root      219: void Audio_WriteSamplesIntoBuffer(char *pSamples,int Index,int Length,int RampSetting)
1.1       root      220: {
1.1.1.2   root      221:   void *lpWrite;
1.1       root      222:   unsigned char *pBuffer;
1.1.1.2   root      223:   short dwLenBytes;
                    224:   int dsRetVal;
                    225:   int i;
1.1       root      226: 
1.1.1.2   root      227:   /* Modify ramp volume - ramp down if sound not enabled or not in windows mouse mode */
1.1.1.3 ! root      228:   if ( (((RampSetting==RAMP_DOWN) || (!ConfigureParams.Sound.bEnableSound)) && (PlayVolume>0.0f)) ) {
1.1       root      229:     PlayVolume -= RAMP_DOWN_VOLUME_LEVEL;
                    230:     if (PlayVolume<=0.0f)
                    231:       PlayVolume = 0.0f;
                    232:   }
                    233:   else if ( (RampSetting==RAMP_UP) && (PlayVolume<1.0f) ) {
                    234:     PlayVolume += RAMP_UP_VOLUME_LEVEL;
                    235:     if (PlayVolume>=1.0f)
                    236:       PlayVolume = 1.0f;
                    237:   }
                    238: 
1.1.1.2   root      239:   if (SoundBuffer1) {
                    240: 
                    241:     /* Do need to reset 'write' position? */
1.1       root      242:     if (bAquireWritePosition) {
1.1.1.2   root      243:       WriteOffset = 0;
1.1       root      244:       bAquireWritePosition = FALSE;
                    245:     }
                    246: 
1.1.1.2   root      247:     lpWrite = SoundBuffer1 + WriteOffset;
                    248:     dwLenBytes = Length;
1.1       root      249: 
1.1.1.2   root      250:     /* Write section, convert to 'unsigned' and write '128'(unsigned) if passed NULL */
                    251:     if ( (dwLenBytes>0) && (lpWrite) ) {
                    252:       if (pSamples) {
                    253:         pBuffer = (unsigned char *)lpWrite;
                    254:         for(i=0; i<(int)dwLenBytes; i++) {
                    255:           *pBuffer++ = Audio_ModifyVolume(pSamples[Index])+128;
                    256:           Index = (Index+1)&4095;
1.1       root      257:         }
                    258:       }
1.1.1.2   root      259:       else
                    260:         memset(lpWrite,128,dwLenBytes);
1.1       root      261:     }
                    262: 
1.1.1.2   root      263:     /* Update write buffer */
1.1       root      264:     if (pSamples) {
                    265:       WriteOffset += Length;
1.1.1.2   root      266:       if (WriteOffset>=SoundBufferSize) {
                    267:         /* If the buffer is full, swap the buffers and copy overflow space to the new buffer. */
                    268:         SDL_LockAudio();
                    269:         WriteOffset -= SoundBufferSize;
                    270:         memcpy(SoundBuffer2, SoundBuffer1+SoundBufferSize, WriteOffset);  /* Copy overflow to the next buffer */
                    271:         pBuffer = SoundBuffer2;
                    272:         SoundBuffer2 = SoundBuffer1;            /* Swap the buffers */
                    273:         SoundBuffer1 = pBuffer;
                    274:         SDL_UnlockAudio();
                    275:       }
1.1       root      276:     }
                    277: 
1.1.1.2   root      278:     /* Are we playing? */
1.1       root      279:     if (!bPlayingBuffer) {
1.1.1.3 ! root      280:       SDL_PauseAudio(FALSE);
1.1.1.2   root      281:       Audio_ResetBuffer();
1.1       root      282:       bPlayingBuffer = TRUE;
                    283:     }
                    284:     else {
1.1.1.2   root      285:       /* Check here for play/write pointers getting away from each other and set 'bAquireWritePosition' to reset */
                    286:       //lpDSBPrimBuffer->GetCurrentPosition(NULL,(DWORD *)&WriteCursor);
                    287:       /* If the writecursor is too-far away from where we think it should be cause a reset */
                    288:       //CursorDiff = WriteOffset-WriteCursor;
                    289:       /* Check for overlap */
                    290:       //if (CursorDiff<0)
                    291:       //  CursorDiff = (WriteOffset+PrimaryBufferSize)-WriteCursor;
                    292:       /* So, does need reset? */
                    293:       //if (abs(CursorDiff)>(WRITE_INIT_POS*2))
                    294:       //  Audio_ResetBuffer();
1.1       root      295:     }
                    296:   }
1.1.1.2   root      297: 
1.1       root      298: }

unix.superglobalmegacorp.com

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