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

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

unix.superglobalmegacorp.com

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