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

📄 native_midi_mac.c

📁 SDL_mixer 是一个基于 SDL 的混音器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    native_midi_mac:  Native Midi support on MacOS for the SDL_mixer library    Copyright (C) 2001  Max Horn    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.    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    Max Horn    max@quendi.de*/#include "SDL_config.h"#include "SDL_endian.h"#if __MACOS__ || __MACOSX__#include "native_midi.h"#include "native_midi_common.h"#if __MACOSX__#include <QuickTime/QuickTimeMusic.h>#else#include <QuickTimeMusic.h>#endif#include <assert.h>#include <stdlib.h>#include <string.h>/* Native Midi song */struct _NativeMidiSong{	Uint32		*tuneSequence;	Uint32		*tuneHeader;};enum{	/* number of (32-bit) long words in a note request event */	kNoteRequestEventLength = ((sizeof(NoteRequest)/sizeof(long)) + 2),	/* number of (32-bit) long words in a marker event */	kMarkerEventLength	= 1,	/* number of (32-bit) long words in a general event, minus its data */	kGeneralEventLength	= 2};#define ERROR_BUF_SIZE			256#define	BUFFER_INCREMENT		5000#define REST_IF_NECESSARY()	do {\			int timeDiff = eventPos->time - lastEventTime;	\			if(timeDiff)	\			{	\				timeDiff = (int)(timeDiff*tick);	\				qtma_StuffRestEvent(*tunePos, timeDiff);	\				tunePos++;	\				lastEventTime = eventPos->time;	\			}	\		} while(0)static Uint32 *BuildTuneSequence(MIDIEvent *evntlist, int ppqn, int part_poly_max[32], int part_to_inst[32], int *numParts);static Uint32 *BuildTuneHeader(int part_poly_max[32], int part_to_inst[32], int numParts);/* The global TunePlayer instance */static TunePlayer	gTunePlayer = NULL;static int			gInstaceCount = 0;static Uint32		*gCurrentTuneSequence = NULL;static char			gErrorBuffer[ERROR_BUF_SIZE] = "";/* Check whether QuickTime is available */int native_midi_detect(){	/* TODO */	return 1;}NativeMidiSong *native_midi_loadsong(char *midifile){	NativeMidiSong	*song = NULL;	MIDIEvent		*evntlist = NULL;	int				part_to_inst[32];	int				part_poly_max[32];	int				numParts = 0;	Uint16			ppqn;	SDL_RWops		*rw;	/* Init the arrays */	memset(part_poly_max,0,sizeof(part_poly_max));	memset(part_to_inst,-1,sizeof(part_to_inst));		/* Attempt to load the midi file */	rw = SDL_RWFromFile(midifile, "rb");	if (rw) {		evntlist = CreateMIDIEventList(rw, &ppqn);		SDL_RWclose(rw);		if (!evntlist)			goto bail;	}	/* Allocate memory for the song struct */	song = malloc(sizeof(NativeMidiSong));	if (!song)		goto bail;	/* Build a tune sequence from the event list */	song->tuneSequence = BuildTuneSequence(evntlist, ppqn, part_poly_max, part_to_inst, &numParts);	if(!song->tuneSequence)		goto bail;	/* Now build a tune header from the data we collect above, create	   all parts as needed and assign them the correct instrument.	*/	song->tuneHeader = BuildTuneHeader(part_poly_max, part_to_inst, numParts);	if(!song->tuneHeader)		goto bail;		/* Increment the instance count */	gInstaceCount++;	if (gTunePlayer == NULL)		gTunePlayer = OpenDefaultComponent(kTunePlayerComponentType, 0);	/* Finally, free the event list */	FreeMIDIEventList(evntlist);		return song;	bail:	if (evntlist)		FreeMIDIEventList(evntlist);		if (song)	{		if(song->tuneSequence)			free(song->tuneSequence);				if(song->tuneHeader)			DisposePtr((Ptr)song->tuneHeader);		free(song);	}		return NULL;}NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw){	NativeMidiSong	*song = NULL;	MIDIEvent		*evntlist = NULL;	int				part_to_inst[32];	int				part_poly_max[32];	int				numParts = 0;	Uint16			ppqn;	/* Init the arrays */	memset(part_poly_max,0,sizeof(part_poly_max));	memset(part_to_inst,-1,sizeof(part_to_inst));		/* Attempt to load the midi file */	evntlist = CreateMIDIEventList(rw, &ppqn);	if (!evntlist)		goto bail;	/* Allocate memory for the song struct */	song = malloc(sizeof(NativeMidiSong));	if (!song)		goto bail;	/* Build a tune sequence from the event list */	song->tuneSequence = BuildTuneSequence(evntlist, ppqn, part_poly_max, part_to_inst, &numParts);	if(!song->tuneSequence)		goto bail;	/* Now build a tune header from the data we collect above, create	   all parts as needed and assign them the correct instrument.	*/	song->tuneHeader = BuildTuneHeader(part_poly_max, part_to_inst, numParts);	if(!song->tuneHeader)		goto bail;		/* Increment the instance count */	gInstaceCount++;	if (gTunePlayer == NULL)		gTunePlayer = OpenDefaultComponent(kTunePlayerComponentType, 0);	/* Finally, free the event list */	FreeMIDIEventList(evntlist);		return song;	bail:	if (evntlist)		FreeMIDIEventList(evntlist);		if (song)	{		if(song->tuneSequence)			free(song->tuneSequence);				if(song->tuneHeader)			DisposePtr((Ptr)song->tuneHeader);		free(song);	}		return NULL;}void native_midi_freesong(NativeMidiSong *song){	if(!song || !song->tuneSequence)		return;	/* If this is the currently playing song, stop it now */		if (song->tuneSequence == gCurrentTuneSequence)		native_midi_stop();		/* Finally, free the data storage */	free(song->tuneSequence);	DisposePtr((Ptr)song->tuneHeader);	free(song);	/* Increment the instance count */	gInstaceCount--;	if ((gTunePlayer != NULL) && (gInstaceCount == 0))	{		CloseComponent(gTunePlayer);		gTunePlayer = NULL;	}}void native_midi_start(NativeMidiSong *song){	UInt32		queueFlags = 0;	ComponentResult tpError;		assert (gTunePlayer != NULL);		SDL_PauseAudio(1);	SDL_UnlockAudio();    	/* First, stop the currently playing music */	native_midi_stop();		/* Set up the queue flags */	queueFlags = kTuneStartNow;	/* Set the time scale (units per second), we want milliseconds */	tpError = TuneSetTimeScale(gTunePlayer, 1000);	if (tpError != noErr)	{		strncpy (gErrorBuffer, "MIDI error during TuneSetTimeScale", ERROR_BUF_SIZE);		goto done;	}	/* Set the header, to tell what instruments are used */	tpError = TuneSetHeader(gTunePlayer, (UInt32 *)song->tuneHeader);	if (tpError != noErr)	{		strncpy (gErrorBuffer, "MIDI error during TuneSetHeader", ERROR_BUF_SIZE);		goto done;	}		/* Have it allocate whatever resources are needed */	tpError = TunePreroll(gTunePlayer);	if (tpError != noErr)	{		strncpy (gErrorBuffer, "MIDI error during TunePreroll", ERROR_BUF_SIZE);		goto done;	}	/* We want to play at normal volume */	tpError = TuneSetVolume(gTunePlayer, 0x00010000);	if (tpError != noErr)	{		strncpy (gErrorBuffer, "MIDI error during TuneSetVolume", ERROR_BUF_SIZE);		goto done;	}		/* Finally, start playing the full song */	gCurrentTuneSequence = song->tuneSequence;	tpError = TuneQueue(gTunePlayer, (UInt32 *)song->tuneSequence, 0x00010000, 0, 0xFFFFFFFF, queueFlags, NULL, 0);	if (tpError != noErr)	{		strncpy (gErrorBuffer, "MIDI error during TuneQueue", ERROR_BUF_SIZE);		goto done;	}    done:	SDL_LockAudio();	SDL_PauseAudio(0);}void native_midi_stop(){	if (gTunePlayer == NULL)		return;	/* Stop music */	TuneStop(gTunePlayer, 0);		/* Deallocate all instruments */	TuneUnroll(gTunePlayer);}int native_midi_active(){	if (gTunePlayer != NULL)	{		TuneStatus	ts;		TuneGetStatus(gTunePlayer,&ts);		return ts.queueTime != 0;	}	else		return 0;}void native_midi_setvolume(int volume){	if (gTunePlayer == NULL)		return;	/* QTMA olume may range from 0.0 to 1.0 (in 16.16 fixed point encoding) */	TuneSetVolume(gTunePlayer, (0x00010000 * volume)/SDL_MIX_MAXVOLUME);}char *native_midi_error(){	return gErrorBuffer;}Uint32 *BuildTuneSequence(MIDIEvent *evntlist, int ppqn, int part_poly_max[32], int part_to_inst[32], int *numParts){	int			part_poly[32];	int			channel_to_part[16];		int			channel_pan[16];	int			channel_vol[16];

⌨️ 快捷键说明

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