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 + -
显示快捷键?