native_midi_gpl.c

来自「SDL_mixer 是一个基于 SDL 的混音器」· C语言 代码 · 共 513 行

C
513
字号
/***************************************************************************                           native_midi_lnx.c			   -----------------			       copyright            : (C) 2002 by Peter Ku会k    email                : kutak@stonline.sk ***************************************************************************//* in this file is used code from PlayMidi    Copyright (C) 1994-1996 Nathan I. Laredo *//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * ***************************************************************************/#if defined(linux) || defined(__FreeBSD__)#ifndef __FreeBSD__#include <getopt.h>#endif#include <fcntl.h>#include <ctype.h>#include <unistd.h>#include <sys/stat.h>#include <string.h>#include "SDL_thread.h"#include "native_midi.h"#include "playmidi.h"SEQ_DEFINEBUF(SEQUENCERBLOCKSIZE);int play_fm = 0, play_gus = 0, play_ext = 0, play_awe = 0;int opl3_patch_aviable = 0, fm_patch_aviable = 0;struct miditrack seq[MAXTRKS];struct synth_info card_info[MAX_CARDS];int FORCE_EXT_DEV = -1;int chanmask = 0xffff, perc = PERCUSSION;int dochan = 1, force8bit = 0, wantopl3 = FM_DEFAULT_MODE;int patchloaded[256], fmloaded[256], useprog[16], usevol[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};int reverb = 0, chorus = 0, nrsynths, nrmidis;int sb_dev = -1, gus_dev = -1, ext_dev = -1, awe_dev = -1, p_remap = 0;int seqfd,  MT32 = 0;FILE *mfd;unsigned long int default_tempo;float skew = 1.0;char ImPlaying = 0;SDL_Thread *playevents_thread=NULL;extern int ntrks;extern char *gmvoice[256];extern int mt32pgm[128];extern int note_vel[16][128];extern int playevents();extern int gus_load(int);extern int readmidi(unsigned char *, off_t);extern void loadfm();void seqbuf_dump();int synth_setup();struct _NativeMidiSong{    char *filebuf;    unsigned long int file_size;};int native_midi_detect(){    int sbfd;    int ret=0;        /* Open sequencer device */    if ((seqfd = open(SEQUENCER_DEV, O_WRONLY, 0)) < 0)     {	perror("open " SEQUENCER_DEV);	return 0;    }    gus_dev = -1;    sb_dev = -1;    ext_dev = -1;    awe_dev = -1;    play_fm = 0;    play_gus = 0;    play_ext = 0;    play_awe = 0;        opl3_patch_aviable = 0;    fm_patch_aviable = 0;    sbfd = open(SBMELODIC, O_RDONLY, 0);    if (sbfd != -1)    {	close(sbfd);	sbfd = open(SBDRUMS, O_RDONLY, 0);	if (sbfd != -1)	{            close(sbfd);	    fm_patch_aviable = 1;	}    }    sbfd = open(O3MELODIC, O_RDONLY, 0);    if (sbfd != -1)    {        close(sbfd);        sbfd = open(O3DRUMS, O_RDONLY, 0);	if (sbfd != -1)	{            close(sbfd);	    opl3_patch_aviable = 1;	}    }    ret=synth_setup();    /* Close sequencer device */    close(seqfd);    return ret;}NativeMidiSong *native_midi_loadsong(char *midifile){    NativeMidiSong	*song = NULL;    char 		*extra;    int 		piped = 0;    struct stat 	info;    song = malloc(sizeof(NativeMidiSong));    if (!song)    {	return NULL;    };    if (stat(midifile, &info) == -1)     {        if ((extra = malloc(strlen(midifile) + 4)) == NULL)        {	    goto end;	}	sprintf(extra, "%s.mid", midifile);	if (stat(extra, &info) == -1)	{	    free(extra);	    goto end;	}	if ((mfd = fopen(extra, "r")) == NULL)	{	    free(extra);	    goto end;	}	free(extra);    } else    {        char *ext = strrchr(midifile, '.');        if (ext && strcmp(ext, ".gz") == 0) 	{	    char temp[1024];	    piped = 1;	    sprintf(temp, "gzip -l %s", midifile);	    if ((mfd = popen(temp, "r")) == NULL)	    {	        goto end;	    }	    fgets(temp, sizeof(temp), mfd); /* skip 1st line */	    fgets(temp, sizeof(temp), mfd);	    strtok(temp, " "); /* compressed size */	    info.st_size = atoi(strtok(NULL, " ")); /* original size */	    pclose(mfd);	    sprintf(temp, "gzip -d -c %s",midifile);	    if ((mfd = popen(temp, "r")) == NULL)	    {	        goto end;	    }	}else if ((mfd = fopen(midifile, "r")) == NULL)	{	    goto end;	}    }    if ((song->filebuf = malloc(info.st_size)) == NULL)    {        if (piped)        {	    pclose(mfd);	}else	{	    fclose(mfd);	}	goto end;    }    song->file_size=info.st_size;    fread(song->filebuf, 1, info.st_size, mfd);    if (piped)    {        pclose(mfd);    } else    {        fclose(mfd);    }      return song;end:    free(song);    return NULL;}NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw){	NativeMidiSong	*song = NULL;	char 		*extra;	song = malloc(sizeof(NativeMidiSong));	if (!song) {		return NULL;	};	SDL_RWseek(rw, 0, SEEK_END);	song->file_size = SDL_RWtell(rw);	SDL_RWseek(rw, 0, SEEK_SET);	song->filebuf = malloc(song->file_size);	if (!song->filebuf) {		free(song);		return NULL;	}	SDL_RWread(rw, song->filebuf, song->file_size, 1);	return song;}void native_midi_freesong(NativeMidiSong *song){    free(song->filebuf);    free(song);}void native_midi_start(NativeMidiSong *song){    int i, error = 0, j;    for (i = 0; i < 16; i++)    {	useprog[i] = 0;	/* reset options */    }        /* Open sequencer device */    if ((seqfd = open(SEQUENCER_DEV, O_WRONLY, 0)) < 0)     {	perror("open " SEQUENCER_DEV);	goto eend;    }    if(!synth_setup()) { goto end;};	    if (play_gus)	    {		gus_load(-1);	    }	    default_tempo = 500000;	    /* error holds number of tracks read */	    error = readmidi(song->filebuf, song->file_size);	    if (play_gus && error > 0) 	    {		int i;		/* need to keep other i safe */#define CMD (seq[i].data[j] & 0xf0)#define CHN (seq[i].data[j] & 0x0f)#define PGM (seq[i].data[j + 1])		/* REALLY STUPID way to preload GUS, but it works */		for (i = 0; i < ntrks; i++)		    for (j = 0; j < seq[i].length - 5; j++)			if (ISGUS(CHN) && !(PGM & 0x80) &&			    ((CMD == MIDI_PGM_CHANGE && !ISPERC(CHN))			     || (CMD == MIDI_NOTEON && ISPERC(CHN))))			    gus_load(ISPERC(CHN) ? PGM + 128 :				     useprog[CHN] ? useprog[CHN] - 1 :				     MT32 ? mt32pgm[PGM] : PGM);		/* make sure that some program was loaded to use */		for (j = 0; patchloaded[j] != 1 && j < 128; j++);		if (j > 127)		    gus_load(0);	    }				/* if there's an error skip to next file */	    if (error > 0)	/* error holds number of tracks read */	    {		ImPlaying=1;	    	playevents_thread=SDL_CreateThread(playevents,NULL);	    }end:eend:	    return;}void native_midi_stop(){    /* Close sequencer device */    close(seqfd);}int native_midi_active(){    return ImPlaying;}void native_midi_setvolume(int volume){}char *native_midi_error(){  return "stala sa chyba";}void seqbuf_dump(){    if (_seqbufptr)	if (write(seqfd, _seqbuf, _seqbufptr) == -1) {	    perror("write " SEQUENCER_DEV);	    return;	}    _seqbufptr = 0;}int synth_setup(){    int i;    char *nativemusicenv = getenv("SDL_NATIVE_MUSIC");    char *extmidi=getenv("SDL_NATIVE_MUSIC_EXT");    if(extmidi)    {	    	FORCE_EXT_DEV = atoi(extmidi);	printf("EXT midi %s , %d \n",extmidi,FORCE_EXT_DEV);    }        if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrsynths) == -1)     {	fprintf(stderr, "there is no soundcard\n");	return 0;    }    for (i = 0; i < nrsynths; i++)     {	card_info[i].device = i;	if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info[i]) == -1) 	{	    fprintf(stderr, "cannot get info on soundcard\n");	    perror(SEQUENCER_DEV);	    return 0;	}	card_info[i].device = i;	if (card_info[i].synth_type == SYNTH_TYPE_SAMPLE	    && card_info[i].synth_subtype == SAMPLE_TYPE_GUS)	{	    gus_dev = i;	}else if (card_info[i].synth_type == SYNTH_TYPE_SAMPLE	    && card_info[i].synth_subtype == SAMPLE_TYPE_AWE32)	{	    awe_dev = i;	}else if (card_info[i].synth_type == SYNTH_TYPE_FM) 	{	    sb_dev = i;	    if (play_fm)		loadfm();	    if (wantopl3) 	    {		card_info[i].nr_voices = 12;	/* we have 12 with 4-op */	    }	}    }    if (gus_dev >= 0) {	if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &gus_dev) == -1) 	{	    perror("Sample reset");	    return 0;	}    }    if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &nrmidis) == -1)     {	fprintf(stderr, "can't get info about midi ports\n");	return 0;    }    if (nrmidis > 0) {	if (FORCE_EXT_DEV >= 0)	    ext_dev = FORCE_EXT_DEV;	else	    ext_dev = nrmidis - 1;    }    if( nativemusicenv ) /* select device by SDL_NATIVE_MUSIC */    {	if(strcasecmp(nativemusicenv,"GUS") == 0)	{    	    if( gus_dev >= 0 )	    {    		play_gus = -1;	        awe_dev = -1;		sb_dev  = -1;	        ext_dev = -1;	        return 1;            }else	    {    		play_gus = 0;		return 0;	    }	}else if(strcasecmp(nativemusicenv,"AWE") == 0)	{    	    if( awe_dev >= 0 )	    {    		play_awe = -1;	        gus_dev = -1;		sb_dev  = -1;	        ext_dev = -1;	        return 1;            }else	    {    		play_awe = 0;		return 0;	    }	}else if(strcasecmp(nativemusicenv,"FM") == 0)	{    	    if( sb_dev >= 0 && fm_patch_aviable )	    {    		play_fm = -1;		gus_dev = -1;	        awe_dev = -1;	        ext_dev = -1;	        wantopl3 = 0;	        return 1;            }else	    {    		play_fm = 0;		return 0;	    }	}else if(strcasecmp(nativemusicenv,"OPL3") == 0)	{    	    if( sb_dev >= 0 && opl3_patch_aviable )	    {    		play_fm = -1;		gus_dev = -1;	        awe_dev = -1;	        ext_dev = -1;	        wantopl3 = 1;	        return 1;            }else	    {    		play_fm = 0;		return 0;	    }	}else if(strcasecmp(nativemusicenv,"EXT") == 0)	{    	    if( ext_dev >= 0 )	    {    		play_ext = -1;	        gus_dev = -1;	        awe_dev = -1;		sb_dev  = -1;	        return 1;            }else	    {    		play_ext = 0;		return 0;	    }	}    }    /* autoselect best device */    if( gus_dev >= 0 )    {        play_gus = -1;        awe_dev = -1;        sb_dev  = -1;        ext_dev = -1;        return 1;        }    if( awe_dev >= 0 )    {        play_awe = -1;	gus_dev = -1;        sb_dev  = -1;        ext_dev = -1;        return 1;    }    if( sb_dev >= 0 && fm_patch_aviable )    {        play_fm = -1;	gus_dev = -1;        awe_dev = -1;        ext_dev = -1;        return 2;	/* return 1 if use FM befor Timidity */    }    if( ext_dev >= 0 )    {        play_ext = -1;	gus_dev = -1;        awe_dev = -1;        sb_dev  = -1;        return 3;    }    return 0;}#endif /* linux || FreeBSD */

⌨️ 快捷键说明

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