Mercurial > sdl-ios-xcode
diff src/audio/mint/SDL_mintaudio.c @ 644:594422ab8f9f
Atari MiNT: added more audio drivers
author | Patrice Mandin <patmandin@gmail.com> |
---|---|
date | Mon, 07 Jul 2003 19:16:03 +0000 |
parents | 0ce5a68278fd |
children | c4803992e09c |
line wrap: on
line diff
--- a/src/audio/mint/SDL_mintaudio.c Tue Jul 01 16:35:54 2003 +0000 +++ b/src/audio/mint/SDL_mintaudio.c Mon Jul 07 19:16:03 2003 +0000 @@ -1,628 +1,93 @@ /* - * MiNT audio driver - * - * Patrice Mandin - */ + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. -#include <stdlib.h> -#include <stdio.h> + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + Audio interrupt variables and callback function + + Patrice Mandin +*/ + #include <string.h> -/* Mint includes */ -#include <mint/osbind.h> -#include <mint/falcon.h> -#include <mint/cookie.h> - -#include "SDL_endian.h" +#include "SDL_types.h" #include "SDL_audio.h" -#include "SDL_audio_c.h" -#include "SDL_audiomem.h" -#include "SDL_sysaudio.h" #include "SDL_mintaudio.h" -#include "SDL_mintaudiodma.h" -#include "SDL_mintaudiogsxb.h" -#include "SDL_mintaudiointerrupt_s.h" - -#include "SDL_atarimxalloc_c.h" - -/*--- Defines ---*/ - -#define MINT_AUDIO_DRIVER_NAME "mint" - -/* Master clocks for replay frequencies */ -#define MASTERCLOCK_STE 8010666 /* Not sure of this one */ -#define MASTERCLOCK_TT 16107953 /* Not sure of this one */ -#define MASTERCLOCK_FALCON1 25175000 -#define MASTERCLOCK_FALCON2 32000000 /* Only usable for DSP56K */ -#define MASTERCLOCK_FALCONEXT -1 /* Clock on DSP56K port, unknown */ -#define MASTERCLOCK_MILAN1 22579200 /* Standard clock for 44.1 Khz */ -#define MASTERCLOCK_MILAN2 24576000 /* Standard clock for 48 Khz */ - -/* Master clock predivisors */ -#define MASTERPREDIV_STE 160 -#define MASTERPREDIV_TT 320 -#define MASTERPREDIV_FALCON 256 -#define MASTERPREDIV_MILAN 256 - -/* Values>>16 in _MCH cookie */ -enum { - MCH_ST=0, - MCH_STE, - MCH_TT, - MCH_F30 -}; +#include "SDL_mintaudio_stfa.h" -/* MFP 68901 interrupt sources */ -enum { - MFP_PARALLEL=0, - MFP_DCD, - MFP_CTS, - MFP_BITBLT, - MFP_TIMERD, - MFP_BAUDRATE=MFP_TIMERD, - MFP_TIMERC, - MFP_200HZ=MFP_TIMERC, - MFP_ACIA, - MFP_DISK, - MFP_TIMERB, - MFP_HBLANK=MFP_TIMERB, - MFP_TERR, - MFP_TBE, - MFP_RERR, - MFP_RBF, - MFP_TIMERA, - MFP_DMASOUND=MFP_TIMERA, - MFP_RING, - MFP_MONODETECT -}; - -/* Xbtimer() timers */ -enum { - XB_TIMERA=0, - XB_TIMERB, - XB_TIMERC, - XB_TIMERD -}; - -/*--- Static variables ---*/ - -static unsigned long cookie_snd, cookie_mch, cookie_gsxb; -static Uint16 hardfreq[16]; -static Uint16 numfreq; -static SDL_AudioDevice *SDL_MintAudio_device; - -/*--- Audio driver functions ---*/ - -static void Mint_CloseAudio(_THIS); -static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec); -static void Mint_LockAudio(_THIS); -static void Mint_UnlockAudio(_THIS); - -/*--- Audio driver bootstrap functions ---*/ - -static int Audio_Available(void) -{ - const char *envr = getenv("SDL_AUDIODRIVER"); - - /* Check if user asked a different audio driver */ - if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) { - return 0; - } - - /* Cookie _SND present ? if not, assume ST machine */ - if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { - cookie_snd = SND_PSG; - } +/* The audio device */ - /* Cookie _MCH present ? if not, assume ST machine */ - if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { - cookie_mch = MCH_ST << 16; - } - - /* Cookie GSXB present ? */ - cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND); - - /* Check if we have xbios functions (Falcon, clones) */ - if ((cookie_snd & SND_16BIT)!=0) { - /* Check if audio is lockable */ - if (Locksnd()==1) { - Unlocksnd(); - } else { - /* Already in use */ - return(0); - } - - return(1); - } - - /* Check if we have 8 bits DMA audio (STE, TT) */ - if ((cookie_snd & SND_8BIT)!=0) { - return(1); - } - - return(0); -} - -static void Audio_DeleteDevice(SDL_AudioDevice *device) -{ - free(device->hidden); - free(device); -} - -static SDL_AudioDevice *Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; +SDL_AudioDevice *SDL_MintAudio_device; +Uint8 *SDL_MintAudio_audiobuf[2]; /* Pointers to buffers */ +long SDL_MintAudio_audiosize; /* Length of audio buffer=spec->size */ +long SDL_MintAudio_numbuf; /* Buffer to play */ +long SDL_MintAudio_mutex; +cookie_stfa_t *SDL_MintAudio_stfa; - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); - if ( this ) { - memset(this, 0, (sizeof *this)); - } - if ( this == NULL ) { - SDL_OutOfMemory(); - if ( this ) { - free(this); - } - return(0); - } - - /* Set the function pointers */ - this->OpenAudio = Mint_OpenAudio; - this->CloseAudio = Mint_CloseAudio; - this->LockAudio = Mint_LockAudio; - this->UnlockAudio = Mint_UnlockAudio; - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap MINTAUDIO_bootstrap = { - MINT_AUDIO_DRIVER_NAME, "MiNT audio driver", - Audio_Available, Audio_CreateDevice -}; +/* The callback function, called by each driver whenever needed */ -static void Mint_LockAudio(_THIS) -{ - void *oldpile; - - /* Stop replay */ - if ((cookie_snd & SND_16BIT)!=0) { - Buffoper(0); - } else if ((cookie_snd & SND_8BIT)!=0) { - oldpile=(void *)Super(0); - DMAAUDIO_IO.control=0; - Super(oldpile); - } -} - -static void Mint_UnlockAudio(_THIS) -{ - void *oldpile; - - /* Restart replay */ - if ((cookie_snd & SND_16BIT)!=0) { - Buffoper(SB_PLA_ENA|SB_PLA_RPT); - } else if ((cookie_snd & SND_8BIT)!=0) { - oldpile=(void *)Super(0); - DMAAUDIO_IO.control=3; - Super(oldpile); - } -} - -/* This is called from the interrupt routine */ void SDL_MintAudio_Callback(void) { - SDL_AudioDevice *audio; Uint8 *buffer; - audio = SDL_MintAudio_device; buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; + memset(buffer, SDL_MintAudio_device->spec.silence, SDL_MintAudio_device->spec.size); - if ( ! audio->paused ) { - if ( audio->convert.needed ) { - audio->spec.callback(audio->spec.userdata, - (Uint8 *)audio->convert.buf,audio->convert.len); - SDL_ConvertAudio(&audio->convert); - memcpy(buffer, audio->convert.buf, audio->convert.len_cvt); + if ( ! SDL_MintAudio_device->paused ) { + if ( SDL_MintAudio_device->convert.needed ) { + SDL_MintAudio_device->spec.callback(SDL_MintAudio_device->spec.userdata, + (Uint8 *)SDL_MintAudio_device->convert.buf,SDL_MintAudio_device->convert.len); + SDL_ConvertAudio(&SDL_MintAudio_device->convert); + memcpy(buffer, SDL_MintAudio_device->convert.buf, SDL_MintAudio_device->convert.len_cvt); } else { - audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size); + SDL_MintAudio_device->spec.callback(SDL_MintAudio_device->spec.userdata, buffer, SDL_MintAudio_device->spec.size); } } } -static void Mint_StopAudio_Dma8(void) -{ - void *oldpile; - - oldpile=(void *)Super(0); - DMAAUDIO_IO.control=0; - Super(oldpile); - - Jdisint(MFP_DMASOUND); -} - -static void Mint_StopAudio_Xbios(void) -{ - Buffoper(0); - Jdisint(MFP_DMASOUND); -} - -static void Mint_StopAudio_Gsxb(void) -{ - Buffoper(0); -} - -static void Mint_CloseAudio(_THIS) -{ - if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) { - Mint_StopAudio_Gsxb(); - } else if ((cookie_snd & SND_16BIT)!=0) { - Mint_StopAudio_Xbios(); - } else if ((cookie_snd & SND_8BIT)!=0) { - Mint_StopAudio_Dma8(); - } - - /* Clear buffers */ - if (SDL_MintAudio_audiobuf[0]) { - Mfree(SDL_MintAudio_audiobuf[0]); - SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; - } - - /* Unlock sound system */ - if ((cookie_snd & SND_16BIT)!=0) { - Unlocksnd(); - } -} - -static void Mint_CheckAudio_Dma8(SDL_AudioSpec *spec) +/* Simple function to search for the nearest frequency */ +int SDL_MintAudio_SearchFrequency(_THIS, int falcon_codec, int desired_freq) { int i; - spec->format = AUDIO_S8; - - switch(cookie_mch>>16) { - case MCH_STE: - /* STE replay frequencies */ - for (i=0;i<4;i++) { - hardfreq[i]=MASTERCLOCK_STE/(MASTERPREDIV_STE*(i+1)); - } - - if (spec->freq>=(hardfreq[0]+hardfreq[1])>>1) { - numfreq=3; /* 50066 */ - } else if (spec->freq>=(hardfreq[1]+hardfreq[2])>>1) { - numfreq=2; /* 25033 */ - } else if (spec->freq>=(hardfreq[2]+hardfreq[3])>>1) { - numfreq=1; /* 12517 */ - } else { - numfreq=0; /* 6258 */ - } - - spec->freq=hardfreq[numfreq]; - break; - case MCH_TT: - /* TT replay frequencies */ - for (i=0;i<4;i++) { - hardfreq[i]=MASTERCLOCK_TT/(MASTERPREDIV_TT*(i+1)); - } - - if (spec->freq>=(hardfreq[0]+hardfreq[1])>>1) { - numfreq=3; /* 50337 */ - } else if (spec->freq>=(hardfreq[1]+hardfreq[2])>>1) { - numfreq=2; /* 25169 */ - } else if (spec->freq>=(hardfreq[2]+hardfreq[3])>>1) { - numfreq=1; /* 12584 */ - } else { - numfreq=0; /* 6292 */ - } - spec->freq=hardfreq[numfreq]; - break; - } -} - -static void Mint_CheckAudio_Xbios(SDL_AudioSpec *spec) -{ - int i; - - /* Check conversions needed */ - switch (spec->format & 0xff) { - case 8: - spec->format = AUDIO_S8; - break; - case 16: - spec->format = AUDIO_S16MSB; - break; - } - - /* Check hardware channels */ - if ((spec->channels==1) && ((spec->format & 0xff)==16)) { - spec->channels=2; - } - - /* Falcon replay frequencies */ - for (i=0;i<16;i++) { - hardfreq[i]=MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1)); + /* Only 1 freq ? */ + if (MINTAUDIO_nfreq==1) { + return(MINTAUDIO_sfreq); } - /* The Falcon CODEC only support some frequencies */ - if (spec->freq>=(hardfreq[CLK50K]+hardfreq[CLK33K])>>1) { - numfreq=CLK50K; /* 49170 */ - } else if (spec->freq>=(hardfreq[CLK33K]+hardfreq[CLK25K])>>1) { - numfreq=CLK33K; /* 32780 */ - } else if (spec->freq>=(hardfreq[CLK25K]+hardfreq[CLK20K])>>1) { - numfreq=CLK25K; /* 24585 */ - } else if (spec->freq>=(hardfreq[CLK20K]+hardfreq[CLK16K])>>1) { - numfreq=CLK20K; /* 19668 */ - } else if (spec->freq>=(hardfreq[CLK16K]+hardfreq[CLK12K])>>1) { - numfreq=CLK16K; /* 16390 */ - } else if (spec->freq>=(hardfreq[CLK12K]+hardfreq[CLK10K])>>1) { - numfreq=CLK12K; /* 12292 */ - } else if (spec->freq>=(hardfreq[CLK10K]+hardfreq[CLK8K])>>1) { - numfreq=CLK10K; /* 9834 */ - } else { - numfreq=CLK8K; /* 8195 */ - } - - spec->freq=hardfreq[numfreq]; -} - -static int Mint_CheckAudio_Gsxb(SDL_AudioSpec *spec) -{ - long snd_format; - int i, resolution, format_signed, format_bigendian; - - resolution = spec->format & 0x00ff; - format_signed = ((spec->format & 0x8000)!=0); - format_bigendian = ((spec->format & 0x1000)!=0); + /* Check the array */ + for (i=MINTAUDIO_sfreq; i<MINTAUDIO_nfreq-1; i++) { + /* Remove unusable falcon codec frequencies */ + if (falcon_codec) { + if ((i==6) || (i==8) || (i==10)) { + continue; + } + } - /* Check formats available */ - snd_format = Sndstatus(SND_QUERYFORMATS); - switch (resolution) { - case 8: - if ((snd_format & SND_FORMAT8)==0) { - SDL_SetError("Mint_CheckAudio: 8 bits samples not supported"); - return -1; - } - snd_format = Sndstatus(SND_QUERY8BIT); - break; - case 16: - if ((snd_format & SND_FORMAT16)==0) { - SDL_SetError("Mint_CheckAudio: 16 bits samples not supported"); - return -1; - } - snd_format = Sndstatus(SND_QUERY16BIT); - break; - default: - SDL_SetError("Mint_CheckAudio: Unsupported sample resolution"); - return -1; - break; - } - - /* Check signed/unsigned format */ - if (format_signed) { - if (snd_format & SND_FORMATSIGNED) { - /* Ok */ - } else if (snd_format & SND_FORMATUNSIGNED) { - /* Give unsigned format */ - spec->format = spec->format & (~0x8000); - } - } else { - if (snd_format & SND_FORMATUNSIGNED) { - /* Ok */ - } else if (snd_format & SND_FORMATSIGNED) { - /* Give signed format */ - spec->format |= 0x8000; + if (desired_freq >= ((MINTAUDIO_hardfreq[i]+MINTAUDIO_hardfreq[i+1])>>1)) { + return i; } } - if (format_bigendian) { - if (snd_format & SND_FORMATBIGENDIAN) { - /* Ok */ - } else if (snd_format & SND_FORMATLITTLEENDIAN) { - /* Give little endian format */ - spec->format = spec->format & (~0x1000); - } - } else { - if (snd_format & SND_FORMATBIGENDIAN) { - /* Ok */ - } else if (snd_format & SND_FORMATLITTLEENDIAN) { - /* Give big endian format */ - spec->format |= 0x1000; - } - } - - /* Only xbios functions available = clone with PC board */ - for (i=0;i<8;i++) { - hardfreq[i]=MASTERCLOCK_MILAN1/(MASTERPREDIV_MILAN*(i+1)); - } - - if (spec->freq>=(hardfreq[CLK_44K]+hardfreq[CLK_22K])>>1) { - numfreq = CLK_44K; /* 44100 */ - } else if (spec->freq>=(hardfreq[CLK_22K]+hardfreq[CLK_11K])>>1) { - numfreq = CLK_22K; /* 22050 */ - } else { - numfreq = CLK_11K; /* 11025 */ - } - - spec->freq=hardfreq[numfreq]; - - return 0; -} - -static void Mint_InitAudio_Dma8(SDL_AudioSpec *spec) -{ - void *oldpile; - unsigned long buffer; - unsigned char mode; - - oldpile=(void *)Super(0); - - /* Stop currently playing sound */ - DMAAUDIO_IO.control=0; - - /* Set buffer */ - buffer = (unsigned long) SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; - DMAAUDIO_IO.start_high = (buffer>>16) & 255; - DMAAUDIO_IO.start_mid = (buffer>>8) & 255; - DMAAUDIO_IO.start_low = buffer & 255; - - buffer += SDL_MintAudio_audiosize; - DMAAUDIO_IO.end_high = (buffer>>16) & 255; - DMAAUDIO_IO.end_mid = (buffer>>8) & 255; - DMAAUDIO_IO.end_low = buffer & 255; - - mode = numfreq; - if (spec->channels==1) { - mode |= 1<<7; - } - DMAAUDIO_IO.mode = mode; - - /* Set interrupt */ - Jdisint(MFP_DMASOUND); - Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_IntDma); - Jenabint(MFP_DMASOUND); - - /* Go */ - DMAAUDIO_IO.control = 3; /* playback + repeat */ - - Super(oldpile); + /* Not in the array, give the latest */ + return MINTAUDIO_nfreq-1; } - -static void Mint_InitAudio_Xbios(SDL_AudioSpec *spec) -{ - int channels_mode; - void *buffer; - - /* Stop currently playing sound */ - Buffoper(0); - - Settracks(0,0); - Setmontracks(0); - - switch (spec->format & 0xff) { - case 8: - if (spec->channels==2) { - channels_mode=STEREO8; - } else { - channels_mode=MONO8; - } - break; - case 16: - default: - channels_mode=STEREO16; - break; - } - Setmode(channels_mode); - - Devconnect(DMAPLAY, DAC, CLK25M, numfreq, 1); - - /* Set buffer */ - buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; - Setbuffer(0, buffer, buffer+SDL_MintAudio_audiosize); - - /* Install interrupt */ - Setinterrupt(SI_TIMERA, SI_PLAY); - - Jdisint(MFP_DMASOUND); - Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_IntXbios); - Jenabint(MFP_DMASOUND); - - /* Go */ - Buffoper(SB_PLA_ENA|SB_PLA_RPT); -} - -static void Mint_InitAudio_Gsxb(SDL_AudioSpec *spec) -{ - int channels_mode; - void *buffer; - - /* Stop currently playing sound */ - Buffoper(0); - - switch (spec->format & 0xff) { - case 8: - if (spec->channels==2) { - channels_mode=STEREO8; - } else { - channels_mode=MONO8; - } - break; - case 16: - if (spec->channels==2) { - channels_mode=STEREO16; - } else { - channels_mode=MONO16; - } - break; - default: - channels_mode=STEREO16; - break; - } - Setmode(channels_mode); - - Devconnect(0, 0, CLKEXT, numfreq, 1); - - /* Set buffer */ - buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; - Setbuffer(0, buffer, buffer+SDL_MintAudio_audiosize); - - /* Install interrupt */ - NSetinterrupt(2, SI_PLAY, SDL_MintAudio_IntGsxb); - - /* Go */ - Buffoper(SB_PLA_ENA|SB_PLA_RPT); -} - -static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec) -{ - /* Lock sound system */ - if ((cookie_snd & SND_16BIT)!=0) { - if (Locksnd()!=1) { - SDL_SetError("Mint_OpenAudio: Audio system already in use"); - return(-1); - } - } - - /* Check audio capabilities */ - if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) { - if (Mint_CheckAudio_Gsxb(spec)==-1) { - return -1; - } - } else if ((cookie_snd & SND_16BIT)!=0) { - Mint_CheckAudio_Xbios(spec); - } else if ((cookie_snd & SND_8BIT)!=0) { - Mint_CheckAudio_Dma8(spec); - } - - SDL_CalculateAudioSpec(spec); - - /* Allocate memory for audio buffers in DMA-able RAM */ - spec->size = spec->samples; - spec->size *= spec->channels; - spec->size *= (spec->format & 0xFF)/8; - - SDL_MintAudio_audiosize = spec->size; - - SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(SDL_MintAudio_audiosize *2, MX_STRAM); - if (SDL_MintAudio_audiobuf[0]==NULL) { - SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); - return (-1); - } - SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + SDL_MintAudio_audiosize; - SDL_MintAudio_numbuf=0; - memset(SDL_MintAudio_audiobuf[0], 0, SDL_MintAudio_audiosize * 2); - SDL_MintAudio_mutex = 0; - - SDL_MintAudio_device = this; - - /* Setup audio hardware */ - if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) { - Mint_InitAudio_Gsxb(spec); - } else if ((cookie_snd & SND_16BIT)!=0) { - Mint_InitAudio_Xbios(spec); - } else if ((cookie_snd & SND_8BIT)!=0) { - Mint_InitAudio_Dma8(spec); - } - - return 1; -}