src/audio/mint/SDL_mintaudio_stfa.c
author Patrice Mandin
Fri, 29 Oct 2004 11:19:03 +0000
changeset 962 176240cf4405
parent 961 185acc07127a
child 1107 856f76a099c7
permissions -rw-r--r--
Forgot to disable debug messages
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2004 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 /*
    24 	MiNT audio driver
    25 	using XBIOS functions (STFA driver)
    26 
    27 	Patrice Mandin
    28 */
    29 
    30 #include <stdlib.h>
    31 #include <stdio.h>
    32 #include <string.h>
    33 
    34 /* Mint includes */
    35 #include <mint/osbind.h>
    36 #include <mint/falcon.h>
    37 #include <mint/cookie.h>
    38 
    39 #include "SDL_endian.h"
    40 #include "SDL_audio.h"
    41 #include "SDL_audio_c.h"
    42 #include "SDL_audiomem.h"
    43 #include "SDL_sysaudio.h"
    44 
    45 #include "SDL_atarimxalloc_c.h"
    46 
    47 #include "SDL_mintaudio.h"
    48 #include "SDL_mintaudio_stfa.h"
    49 
    50 /*--- Defines ---*/
    51 
    52 #define MINT_AUDIO_DRIVER_NAME "mint_stfa"
    53 
    54 /* Debug print info */
    55 #define DEBUG_NAME "audio:stfa: "
    56 #if 0
    57 #define DEBUG_PRINT(what) \
    58 	{ \
    59 		printf what; \
    60 	}
    61 #else
    62 #define DEBUG_PRINT(what)
    63 #endif
    64 
    65 /*--- Static variables ---*/
    66 
    67 static unsigned long cookie_snd, cookie_mch;
    68 static cookie_stfa_t *cookie_stfa;
    69 
    70 static const int freqs[16]={
    71 	4995,	6269,	7493,	8192,
    72 	9830,	10971,	12538,	14985,
    73 	16384,	19819,	21943,	24576,
    74 	30720,	32336,	43885,	49152
    75 };
    76 
    77 /*--- Audio driver functions ---*/
    78 
    79 static void Mint_CloseAudio(_THIS);
    80 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
    81 static void Mint_LockAudio(_THIS);
    82 static void Mint_UnlockAudio(_THIS);
    83 
    84 /* To check/init hardware audio */
    85 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
    86 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
    87 
    88 /*--- Audio driver bootstrap functions ---*/
    89 
    90 static int Audio_Available(void)
    91 {
    92 	const char *envr = getenv("SDL_AUDIODRIVER");
    93 
    94 	/* Check if user asked a different audio driver */
    95 	if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
    96 		DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
    97 		return(0);
    98 	}
    99 
   100 	/* Cookie _MCH present ? if not, assume ST machine */
   101 	if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
   102 		cookie_mch = MCH_ST;
   103 	}
   104 
   105 	/* Cookie _SND present ? if not, assume ST machine */
   106 	if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
   107 		cookie_snd = SND_PSG;
   108 	}
   109 
   110 	/* Cookie STFA present ? */
   111 	if (Getcookie(C_STFA, (long *) &cookie_stfa) != C_FOUND) {
   112 		DEBUG_PRINT((DEBUG_NAME "no STFA audio\n"));
   113 		return(0);
   114 	}
   115 
   116 	SDL_MintAudio_stfa = cookie_stfa;
   117 
   118 	DEBUG_PRINT((DEBUG_NAME "STFA audio available!\n"));
   119 	return(1);
   120 }
   121 
   122 static void Audio_DeleteDevice(SDL_AudioDevice *device)
   123 {
   124     free(device->hidden);
   125     free(device);
   126 }
   127 
   128 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
   129 {
   130 	SDL_AudioDevice *this;
   131 
   132 	/* Initialize all variables that we clean on shutdown */
   133 	this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
   134     if ( this ) {
   135         memset(this, 0, (sizeof *this));
   136         this->hidden = (struct SDL_PrivateAudioData *)
   137                 malloc((sizeof *this->hidden));
   138     }
   139     if ( (this == NULL) || (this->hidden == NULL) ) {
   140         SDL_OutOfMemory();
   141         if ( this ) {
   142             free(this);
   143         }
   144         return(0);
   145     }
   146     memset(this->hidden, 0, (sizeof *this->hidden));
   147 
   148     /* Set the function pointers */
   149     this->OpenAudio   = Mint_OpenAudio;
   150     this->CloseAudio  = Mint_CloseAudio;
   151     this->LockAudio   = Mint_LockAudio;
   152     this->UnlockAudio = Mint_UnlockAudio;
   153     this->free        = Audio_DeleteDevice;
   154 
   155     return this;
   156 }
   157 
   158 AudioBootStrap MINTAUDIO_STFA_bootstrap = {
   159 	MINT_AUDIO_DRIVER_NAME, "MiNT STFA audio driver",
   160 	Audio_Available, Audio_CreateDevice
   161 };
   162 
   163 static void Mint_LockAudio(_THIS)
   164 {
   165 	void *oldpile;
   166 
   167 	/* Stop replay */
   168 	oldpile=(void *)Super(0);
   169 	cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
   170 	Super(oldpile);
   171 }
   172 
   173 static void Mint_UnlockAudio(_THIS)
   174 {
   175 	void *oldpile;
   176 
   177 	/* Restart replay */
   178 	oldpile=(void *)Super(0);
   179 	cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT;
   180 	Super(oldpile);
   181 }
   182 
   183 static void Mint_CloseAudio(_THIS)
   184 {
   185 	void *oldpile;
   186 
   187 	/* Stop replay */
   188 	oldpile=(void *)Super(0);
   189 	cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
   190 	Super(oldpile);
   191 
   192 	/* Wait if currently playing sound */
   193 	while (SDL_MintAudio_mutex != 0) {
   194 	}
   195 
   196 	/* Clear buffers */
   197 	if (SDL_MintAudio_audiobuf[0]) {
   198 		Mfree(SDL_MintAudio_audiobuf[0]);
   199 		SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
   200 	}
   201 }
   202 
   203 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
   204 {
   205 	int i;
   206 
   207 	DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
   208 	DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
   209 	DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0)));
   210 	DEBUG_PRINT(("channels=%d, ", spec->channels));
   211 	DEBUG_PRINT(("freq=%d\n", spec->freq));
   212 
   213 	/* Check formats available */
   214 	MINTAUDIO_freqcount=0;
   215 	for (i=0;i<16;i++) {
   216 		SDL_MintAudio_AddFrequency(this, freqs[i], 0, i);
   217 	}
   218 
   219 #if 1
   220 	for (i=0; i<MINTAUDIO_freqcount; i++) {
   221 		DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n",
   222 			i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock,
   223 			MINTAUDIO_frequencies[i].predivisor
   224 		));
   225 	}
   226 #endif
   227 
   228 	MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq);
   229 	spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
   230 
   231 	DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
   232 	DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
   233 	DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0)));
   234 	DEBUG_PRINT(("channels=%d, ", spec->channels));
   235 	DEBUG_PRINT(("freq=%d\n", spec->freq));
   236 
   237 	return 0;
   238 }
   239 
   240 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
   241 {
   242 	void *buffer;
   243 	void *oldpile;
   244 
   245 	buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
   246 
   247 	oldpile=(void *)Super(0);
   248 
   249 	/* Stop replay */
   250 	cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
   251 
   252 	/* Select replay format */
   253 	cookie_stfa->sound_control = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
   254 	if ((spec->format & 0xff)==8) {
   255 		cookie_stfa->sound_control |= STFA_FORMAT_8BIT;
   256 	} else {
   257 		cookie_stfa->sound_control |= STFA_FORMAT_16BIT;
   258 	}
   259 	if (spec->channels==2) {
   260 		cookie_stfa->sound_control |= STFA_FORMAT_STEREO;
   261 	} else {
   262 		cookie_stfa->sound_control |= STFA_FORMAT_MONO;
   263 	}
   264 	if ((spec->format & 0x8000)!=0) {
   265 		cookie_stfa->sound_control |= STFA_FORMAT_SIGNED;
   266 	} else {
   267 		cookie_stfa->sound_control |= STFA_FORMAT_UNSIGNED;
   268 	}
   269 	if ((spec->format & 0x1000)!=0) {
   270 		cookie_stfa->sound_control |= STFA_FORMAT_BIGENDIAN;
   271 	} else {
   272 		cookie_stfa->sound_control |= STFA_FORMAT_LITENDIAN;
   273 	}
   274 
   275 	/* Set buffer */
   276 	cookie_stfa->sound_start = (unsigned long) buffer;
   277 	cookie_stfa->sound_end = (unsigned long) (buffer + spec->size);
   278 
   279 	/* Set interrupt */
   280 	cookie_stfa->stfa_it = SDL_MintAudio_StfaInterrupt;
   281 
   282 	/* Restart replay */
   283 	cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT;
   284 
   285 	Super(oldpile);
   286 
   287 	DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
   288 }
   289 
   290 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
   291 {
   292 	SDL_MintAudio_device = this;
   293 
   294 	/* Check audio capabilities */
   295 	if (Mint_CheckAudio(this, spec)==-1) {
   296 		return -1;
   297 	}
   298 
   299 	SDL_CalculateAudioSpec(spec);
   300 
   301 	/* Allocate memory for audio buffers in DMA-able RAM */
   302 	DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
   303 
   304 	SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
   305 	if (SDL_MintAudio_audiobuf[0]==NULL) {
   306 		SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
   307 		return (-1);
   308 	}
   309 	SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
   310 	SDL_MintAudio_numbuf=0;
   311 	memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
   312 	SDL_MintAudio_audiosize = spec->size;
   313 	SDL_MintAudio_mutex = 0;
   314 
   315 	DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
   316 	DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
   317 
   318 	/* Setup audio hardware */
   319 	Mint_InitAudio(this, spec);
   320 
   321     return(1);	/* We don't use threaded audio */
   322 }