src/audio/riscos/SDL_drenderer.c
changeset 955 d74fbf56f2f6
parent 769 b8d311d90021
equal deleted inserted replaced
954:3acd16ea0180 955:d74fbf56f2f6
    32 #include "SDL_audio.h"
    32 #include "SDL_audio.h"
    33 #include "SDL_audio_c.h"
    33 #include "SDL_audio_c.h"
    34 #include "SDL_audiomem.h"
    34 #include "SDL_audiomem.h"
    35 #include "SDL_sysaudio.h"
    35 #include "SDL_sysaudio.h"
    36 #include "SDL_drenderer.h"
    36 #include "SDL_drenderer.h"
       
    37 
       
    38 #ifndef DISABLE_THREADS
       
    39 #include <pthread.h>
       
    40 #endif
    37 
    41 
    38 #define DigitalRenderer_Activate    0x4F700
    42 #define DigitalRenderer_Activate    0x4F700
    39 #define DigitalRenderer_Deactivate	0x4F701
    43 #define DigitalRenderer_Deactivate	0x4F701
    40 #define DigitalRenderer_ReadState	0x4F705
    44 #define DigitalRenderer_ReadState	0x4F705
    41 #define DigitalRenderer_NewSample	0x4F706
    45 #define DigitalRenderer_NewSample	0x4F706
    55 /* Audio driver functions */
    59 /* Audio driver functions */
    56 
    60 
    57 static void DRenderer_CloseAudio(_THIS);
    61 static void DRenderer_CloseAudio(_THIS);
    58 static int DRenderer_OpenAudio(_THIS, SDL_AudioSpec *spec);
    62 static int DRenderer_OpenAudio(_THIS, SDL_AudioSpec *spec);
    59 
    63 
       
    64 #ifndef DISABLE_THREADS
       
    65 static void DRenderer_WaitAudio(_THIS);
       
    66 static Uint8 *DRenderer_GetAudioBuf(_THIS);
       
    67 static void DRenderer_PlayAudio(_THIS);
       
    68 #endif
       
    69 
    60 /* Audio driver bootstrap functions */
    70 /* Audio driver bootstrap functions */
    61 
    71 
    62 /* Define following to dump stats to stdout */
    72 /* Define following to dump stats to stdout */
    63 /* #define DUMP_AUDIO */
    73 /* #define DUMP_AUDIO */
    64 
    74 
   102     memset(this->hidden, 0, (sizeof *this->hidden));
   112     memset(this->hidden, 0, (sizeof *this->hidden));
   103 
   113 
   104     /* Set the function pointers */
   114     /* Set the function pointers */
   105     this->OpenAudio   = DRenderer_OpenAudio;
   115     this->OpenAudio   = DRenderer_OpenAudio;
   106     this->CloseAudio  = DRenderer_CloseAudio;
   116     this->CloseAudio  = DRenderer_CloseAudio;
       
   117 #ifndef DISABLE_THREADS
       
   118     this->GetAudioBuf = DRenderer_GetAudioBuf;
       
   119     this->PlayAudio   = DRenderer_PlayAudio;
       
   120     this->WaitAudio   = DRenderer_WaitAudio;
       
   121 #endif
   107     this->free        = Audio_DeleteDevice;
   122     this->free        = Audio_DeleteDevice;
   108 
   123 
   109     return this;
   124     return this;
   110 }
   125 }
   111 
   126 
   115 };
   130 };
   116 
   131 
   117 /* Routine called to check and fill audio buffers if necessary */
   132 /* Routine called to check and fill audio buffers if necessary */
   118 static Uint8 *buffer = NULL;
   133 static Uint8 *buffer = NULL;
   119 
   134 
       
   135 #ifdef DISABLE_THREADS
       
   136 
       
   137 /* Buffer fill routine called during polling */
   120 void DRenderer_FillBuffers()
   138 void DRenderer_FillBuffers()
   121 {
   139 {
   122 	SDL_AudioDevice *audio = current_audio;
   140 	SDL_AudioDevice *audio = current_audio;
   123 
   141 
   124    if ( !audio || ! audio->enabled )
   142    if ( !audio || ! audio->enabled )
   180 	   }
   198 	   }
   181 
   199 
   182    }
   200    }
   183 }
   201 }
   184 
   202 
       
   203 #endif
       
   204 
   185 /* Size of DMA buffer to use */
   205 /* Size of DMA buffer to use */
   186 #define DRENDERER_BUFFER_SIZE 512
   206 #define DRENDERER_BUFFER_SIZE 512
   187 
   207 
   188 /* Number of centiseconds of sound to buffer.
   208 /* Number of centiseconds of sound to buffer.
   189    Hopefully more than the maximum time between calls to the
   209    Hopefully more than the maximum time between calls to the
   190    FillBuffers routine above
   210    FillBuffers routine above (non-threaded) or the PlayAudio
       
   211    routine below (threaded).
   191 */
   212 */
       
   213 
   192 #define DRENDERER_CSEC_TO_BUFFER 10
   214 #define DRENDERER_CSEC_TO_BUFFER 10
       
   215 
       
   216 static void DeactivateAudio()
       
   217 {
       
   218 	_kernel_swi_regs regs;
       
   219 
       
   220 	/* Close down the digital renderer */
       
   221 	_kernel_swi(DigitalRenderer_Deactivate, &regs, &regs);
       
   222 
       
   223 	if (buffer != NULL)
       
   224 	{
       
   225 	   free(buffer);
       
   226 	   buffer = NULL;
       
   227 	}
       
   228 }
   193 
   229 
   194 static int DRenderer_OpenAudio(_THIS, SDL_AudioSpec *spec)
   230 static int DRenderer_OpenAudio(_THIS, SDL_AudioSpec *spec)
   195 {
   231 {
   196 	_kernel_swi_regs regs;
   232 	_kernel_swi_regs regs;
   197 	int buffers_per_sample;
   233 	int buffers_per_sample;
   198 
   234 
   199 #ifdef DUMP_AUDIO
   235 #ifdef DUMP_AUDIO
   200     printf("Request format %d\n", spec->format);
   236     printf("Request format %d\n", spec->format);
   201     printf("Request freq   %d\n", spec->freq);
   237     printf("Request freq   %d\n", spec->freq);
   202     printf("Samples        %d\n", spec->samples);
   238     printf("Samples        %d\n", spec->samples);
       
   239     printf("Channels       %d\n", spec->channels);
   203 #endif
   240 #endif
   204 
   241 
   205 	/* Only support signed 16bit format */
   242 	/* Only support signed 16bit format */
   206 	spec->format = AUDIO_S16LSB;
   243 	spec->format = AUDIO_S16LSB;
   207 
   244 
   208     if (spec->samples < DRENDERER_BUFFER_SIZE) spec->samples = DRENDERER_BUFFER_SIZE;
   245     if (spec->samples < DRENDERER_BUFFER_SIZE) spec->samples = DRENDERER_BUFFER_SIZE;
   209 
   246 
   210     SDL_CalculateAudioSpec(spec);
       
   211 
       
   212 
       
   213 	buffers_per_sample = spec->samples / DRENDERER_BUFFER_SIZE;
   247 	buffers_per_sample = spec->samples / DRENDERER_BUFFER_SIZE;
   214 
   248 
   215 	if ((spec->samples % DRENDERER_BUFFER_SIZE) != 0)
   249 	if ((spec->samples % DRENDERER_BUFFER_SIZE) != 0)
   216 	{
   250 	{
   217 		buffers_per_sample++;
   251 		buffers_per_sample++;
   218 		spec->samples = buffers_per_sample * DRENDERER_BUFFER_SIZE;
   252 		spec->samples = buffers_per_sample * DRENDERER_BUFFER_SIZE;
   219 	}
   253 	}
       
   254 	
   220 
   255 
   221 	/* Set number of buffers to use - the following should give enough
   256 	/* Set number of buffers to use - the following should give enough
   222 	   data between calls to the sound polling.
   257 	   data between calls to the sound polling.
   223 	*/
   258 	*/
   224 
   259 
   225     if (riscos_audiobuffer == 0)
   260     if (riscos_audiobuffer == 0)
   226     {
   261     {
   227     	FillBuffer = (int)((double)DRENDERER_CSEC_TO_BUFFER / ((double)DRENDERER_BUFFER_SIZE * 100.0 / (double)spec->freq)) + 1;
   262     	FillBuffer = (int)((double)DRENDERER_CSEC_TO_BUFFER / ((double)DRENDERER_BUFFER_SIZE * 100.0 / (double)spec->freq)) + 1;
   228     } else FillBuffer = riscos_audiobuffer/DRENDERER_BUFFER_SIZE - buffers_per_sample;
   263     } else FillBuffer = riscos_audiobuffer/DRENDERER_BUFFER_SIZE - buffers_per_sample;
   229 
   264 
   230 	if (FillBuffer < buffers_per_sample) FillBuffer = buffers_per_sample;
   265     if (FillBuffer < buffers_per_sample) FillBuffer = buffers_per_sample;
       
   266 #ifndef DISABLE_THREADS
       
   267     if (buffers_per_sample < FillBuffer)
       
   268     {
       
   269        /* For the threaded version we are only called once per cycle
       
   270           so the callback needs to give us the full data we need in
       
   271           one go, rather than multiple calls as it the case for the
       
   272           non threaded version */
       
   273        buffers_per_sample = FillBuffer;
       
   274        spec->samples = buffers_per_sample * DRENDERER_BUFFER_SIZE;
       
   275     }
       
   276 #endif
       
   277         SDL_CalculateAudioSpec(spec);
   231 	regs.r[0] = FillBuffer + buffers_per_sample;
   278 	regs.r[0] = FillBuffer + buffers_per_sample;
   232 
   279 
   233 #ifdef DUMP_AUDIO
   280 #ifdef DUMP_AUDIO
   234     printf("Buffers per sample %d\n", buffers_per_sample);
   281     printf("Buffers per sample %d\n", buffers_per_sample);
   235     printf("Fill buffer        %d\n", FillBuffer);
   282     printf("Fill buffer        %d\n", FillBuffer);
   257 	if (_kernel_swi(DigitalRenderer_GetFrequency, &regs, &regs) == 0)
   304 	if (_kernel_swi(DigitalRenderer_GetFrequency, &regs, &regs) == 0)
   258 	{
   305 	{
   259 		spec->freq = regs.r[0];
   306 		spec->freq = regs.r[0];
   260 	}
   307 	}
   261 
   308 
       
   309         /* Ensure sound is deactivated if we exit without calling SDL_Quit */
       
   310         atexit(DeactivateAudio);
       
   311 
   262 #ifdef DUMP_AUDIO
   312 #ifdef DUMP_AUDIO
   263     printf("Got format %d\n", spec->format);
   313     printf("Got format %d\n", spec->format);
   264     printf("Frequency  %d\n", spec->freq);
   314     printf("Frequency  %d\n", spec->freq);
   265     printf("Samples    %d\n", spec->samples);
   315     printf("Samples    %d\n", spec->samples);
   266 #endif                 
   316 #endif                 
   275 	{
   325 	{
   276 		SDL_OutOfMemory();
   326 		SDL_OutOfMemory();
   277 		return -1;
   327 		return -1;
   278 	}
   328 	}
   279 
   329 
       
   330 #ifdef DISABLE_THREADS
   280    /* Hopefully returning 2 will show success, but not start up an audio thread */
   331    /* Hopefully returning 2 will show success, but not start up an audio thread */
   281    return 2;
   332    return 2;
       
   333 #else
       
   334    /* Success and start audio thread */
       
   335    return 0;
       
   336 #endif
   282 }
   337 }
   283 
   338 
   284 static void DRenderer_CloseAudio(_THIS)
   339 static void DRenderer_CloseAudio(_THIS)
   285 {
   340 {
       
   341         DeactivateAudio();
       
   342 }
       
   343 
       
   344 #ifndef DISABLE_THREADS
       
   345 
       
   346 /* Routines for threaded version of audio */
       
   347 
       
   348 void DRenderer_WaitAudio(_THIS)
       
   349 {
       
   350    _kernel_swi_regs regs;
       
   351    int waiting = 1;
       
   352 
       
   353    while (waiting)
       
   354    {
       
   355       /* Check filled buffers count */
       
   356       _kernel_swi(DigitalRenderer_StreamStatistics, &regs, &regs);
       
   357 #if 0
       
   358     if (regs.r[0] <= FillBuffer)
       
   359     {
       
   360        printf("Buffers in use %d\n", regs.r[0]);
       
   361     }
       
   362 #endif
       
   363       if (regs.r[0] <= FillBuffer) waiting = 0;
       
   364       else pthread_yield();
       
   365    }
       
   366 }
       
   367 
       
   368 Uint8 *DRenderer_GetAudioBuf(_THIS)
       
   369 {
       
   370     return buffer;
       
   371 }
       
   372 
       
   373 void DRenderer_PlayAudio(_THIS)
       
   374 {
   286 	_kernel_swi_regs regs;
   375 	_kernel_swi_regs regs;
   287 
   376 
   288 	/* Close down the digital renderer */
   377 	regs.r[0] = (int)buffer;
   289 	_kernel_swi(DigitalRenderer_Deactivate, &regs, &regs);
   378 	regs.r[1] = current_audio->spec.samples * current_audio->spec.channels;
   290 
   379 	_kernel_swi(DigitalRenderer_Stream16BitSamples, &regs, &regs);
   291 	if (buffer != NULL) free(buffer);
   380 }
   292 }
   381 
   293 
   382 #endif