⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl_mintaudio.c

📁 网络MPEG4IP流媒体开发源代码
💻 C
字号:
/* * MiNT audio driver *  * Patrice Mandin */#include <stdlib.h>#include <stdio.h>#include <string.h>/* Mint includes */#include <mint/osbind.h>#include <mint/falcon.h>#include <sys/cookie.h>#include "SDL_endian.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};/* 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;	}	/* 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;    /* 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};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];	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);		} else {			audio->spec.callback(audio->spec.userdata, buffer, audio->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){	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));	}	/* 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 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 (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);}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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -