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

📄 smplfile.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 3 页
字号:
/*     TiMidity++ -- MIDI to WAVE converter and player    Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>    Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>    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.    This program 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 General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA		smplfile.c		core and WAVE,AIFF/AIFF-C importer by Kentaro Sato	<kentaro@ranvis.com>*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdlib.h>#include <math.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include "timidity.h"#include "common.h"#include "controls.h"#include "filter.h"#include "instrum.h"#include "output.h"#include "playmidi.h"#include "resample.h"#include "tables.h"typedef int (*SampleImporterDiscriminateProc)(char *sample_file);	/* returns 0 if file may be loadable */typedef int (*SampleImporterSampleLoaderProc)(char *sample_file, Instrument *inst);	/* sets inst->samples, inst->sample and returns 0 if loaded */	/* inst is pre-allocated, and is freed by caller if loading failed */	/* -1 to let caller give up testing other importers */typedef struct {	char				*extension;		/* file extension excluding '.' */	SampleImporterDiscriminateProc	discriminant;	SampleImporterSampleLoaderProc	load;	/* either extension or discriminant may be NULL */	int					added;			/* for get_importers()'s internal use */} SampleImporter, *SampleImporterRef;Instrument *extract_sample_file(char *sample_file);static int get_importers(const char *sample_file, int limit, SampleImporter **importers);static int get_next_importer(char *sample_file, int start, int count, SampleImporter **importers);static double ConvertFromIeeeExtended(const char *);static int import_wave_discriminant(char *sample_file);static int import_wave_load(char *sample_file, Instrument *inst);static int import_aiff_discriminant(char *sample_file);static int import_aiff_load(char *sample_file, Instrument *inst);static SampleImporter	sample_importers[] = {	{"wav", import_wave_discriminant, import_wave_load},	{"aiff", import_aiff_discriminant, import_aiff_load},	{NULL, NULL, NULL},};Instrument *extract_sample_file(char *sample_file){	Instrument		*inst;	SampleImporter	*importers[10], *importer;	int				i, j, count, result;	Sample			*sample;		if ((count = get_importers(sample_file, sizeof importers / sizeof importers[0], importers)) == 0)		return NULL;	inst = (Instrument *)safe_malloc(sizeof(Instrument));	inst->type = INST_PCM;	inst->instname = NULL;	inst->samples = 0;	inst->sample = NULL;	i = 0;	importer = NULL;	while ((i = get_next_importer(sample_file, i, count, importers)) < count)	{		if ((result = importers[i]->load(sample_file, inst)) == 0)		{			importer = importers[i];			break;		}		if (result == -1)	/* importer told to give up test */			break;		j = inst->samples;		while(j > 0)		{			if (inst->sample[--j].data_alloced)				free(inst->sample[j].data);		}		inst->samples = 0;		free(inst->sample);		inst->sample = NULL;		i++;	/* try next */	}	if (importer == NULL)	{		free_instrument(inst);		return NULL;	}	/* post-process */	if (inst->instname == NULL)	{		const char			*name;				name = pathsep_strrchr(sample_file);		if (name == NULL)			name = sample_file - 1;		inst->instname = strdup(name + 1);	}	for(i = 0; i < inst->samples; i++)	{		sample = &inst->sample[i];		/* If necessary do some anti-aliasing filtering  */		if (antialiasing_allowed)			antialiasing((int16 *)sample->data,				sample->data_length >> FRACTION_BITS,				sample->sample_rate, play_mode->rate);		/* resample it if possible */		if (sample->note_to_use && !(sample->modes & MODES_LOOPING))			pre_resample(sample);#ifdef LOOKUP_HACK		squash_sample_16to8(sample);#endif	}	return inst;}#define ADD_IMPORTER		importer->added = 1;	\							importers[count++] = importer;/* returns number of importers which may be suitable for the file */static int get_importers(const char *sample_file, int limit, SampleImporter **importers){	SampleImporter	*importer;	int				count;	const char		*extension;		count = 0;	importer = sample_importers;	while(importer->load != NULL && count < limit)	{		importer->added = 0;		importer++;	}	/* first, extension matched importers */	extension = pathsep_strrchr(sample_file);	if (extension != NULL && (extension = strrchr(extension, '.')) != NULL)	{		extension++;		/* ones which have discriminant first */		importer = sample_importers;		while(importer->load != NULL && count < limit)		{			if (!importer->added && importer->extension != NULL && importer->discriminant != NULL					&& strcasecmp(extension, importer->extension) == 0)				{ADD_IMPORTER}			importer++;		}		/* then ones which don't have discriminant */		importer = sample_importers;		while(importer->load != NULL && count < limit)		{			if (!importer->added && importer->extension != NULL					&& importer->discriminant == NULL					&& strcasecmp(extension, importer->extension) == 0)				{ADD_IMPORTER}			importer++;		}	}	/* lastly, ones which has discriminant */	importer = sample_importers;	while(importer->load != NULL && count < limit)	{		if (!importer->added && importer->discriminant != NULL)			{ADD_IMPORTER}		importer++;	}	return count;}/* returns importer index for the file *//* returns count if no importer available */static int get_next_importer(char *sample_file, int start, int count, SampleImporter **importers){	int					i;		for(i = start; i < count; i++)	{		if (importers[i]->discriminant != NULL)		{			if (importers[i]->discriminant(sample_file) != 0)				continue;		}		return i;	}	return i;}/*************** Sample Importers ***************/#define MAX_SAMPLE_CHANNELS		16/* from instrum.c */#define READ_CHAR(thing) \      if (1 != tf_read(&tmpchar, 1, 1, tf)) goto fail; \      thing = tmpchar;#define READ_SHORT_LE(thing) \      if (1 != tf_read(&tmpshort, 2, 1, tf)) goto fail; \      thing = LE_SHORT(tmpshort);#define READ_LONG_LE(thing) \      if (1 != tf_read(&tmplong, 4, 1, tf)) goto fail; \      thing = LE_LONG(tmplong);#define READ_SHORT_BE(thing) \      if (1 != tf_read(&tmpshort, 2, 1, tf)) goto fail; \      thing = BE_SHORT(tmpshort);#define READ_LONG_BE(thing) \      if (1 != tf_read(&tmplong, 4, 1, tf)) goto fail; \      thing = BE_LONG(tmplong);const uint8		pan_mono[] = {64};	/* center */const uint8		pan_stereo[] = {1,127};	/* left,right */const uint8		pan_3ch[] = {1,127,64};	/* left,right,center*//* pannings below are set by guess *//*const uint8		pan_quad[] = {1,127,16,112};*/	/* front-left?,front-right?,rear-left?,rear-right? */const uint8		pan_4ch[] = {1,64,127,64};	/* left,center,right,surround?*/const uint8		pan_6ch[] = {1,32,64,127,95,64};	/* left,left-center?,center,right,right-center?,surround? */const uint8		*const gen_pan_list[6] = {		pan_mono, pan_stereo, pan_3ch,		pan_4ch, NULL, pan_6ch,};typedef struct {	uint8	baseNote;	int8	detune;	uint8	lowNote;	uint8	highNote;	uint8	lowVelocity;	uint8	highVelocity;	int16	gain;} GeneralInstrumentInfo;static void initialize_sample(Instrument *inst, int frames, int sample_bits, int sample_rate);static void apply_GeneralInstrumentInfo(int samples, Sample *sample, const GeneralInstrumentInfo *info);/* read_sample_data() flags */#define SAMPLE_BIG_ENDIAN		(1 << 0)#define SAMPLE_8BIT_UNSIGNED	(1 << 1)static int read_sample_data(int32 flags, struct timidity_file *tf, int bits, int samples, int frames, sample_t **sdata);/*************** WAV Importer ***************/typedef struct {	int16	wFormatTag;	uint16	wChannels;	uint32	dwSamplesPerSec;	uint32	dwAvgBytesPerSec;	uint16	wBlockAlign;	uint16	wBitsPerSample;} WAVFormatChunk;typedef struct {	int32	dwSamplePeriod;	int32	dwMIDIUnityNote;	uint32	dwMIDIPitchFraction;	int		hasLoop, loopType;	int32	loop_dwStart, loop_dwEnd, loop_dwFraction;} WAVSamplerChunk;static int read_WAVFormatChunk(struct timidity_file *tf, WAVFormatChunk *fmt, int psize);static int read_WAVSamplerChunk(struct timidity_file *tf, WAVSamplerChunk *smpl, int psize);static int read_WAVInstrumentChunk(struct timidity_file *tf, GeneralInstrumentInfo *inst, int psize);static int import_wave_discriminant(char *sample_file){	struct timidity_file	*tf;	char				buf[12];		if ((tf = open_file(sample_file, 1, OF_NORMAL)) == NULL)		return 1;	if (tf_read(buf, 12, 1, tf) != 1			|| memcmp(&buf[0], "RIFF", 4) != 0 || memcmp(&buf[8], "WAVE", 4) != 0)	{		close_file(tf);		return 1;	}	close_file(tf);	return 0;}#define WAVE_CHUNKFLAG_SAMPLER		(1 << 0)#define WAVE_CHUNKFLAG_INSTRUMENT	(1 << 1)static int import_wave_load(char *sample_file, Instrument *inst){	struct timidity_file	*tf;	char			buf[12];	int				state;		/* initial > fmt_read > data_read */	int				i, chunk_size, type_index, type_size, samples;	int32			chunk_flags;	Sample			*sample;	WAVFormatChunk	format;	WAVSamplerChunk	samplerc;	GeneralInstrumentInfo	instc;		if ((tf = open_file(sample_file, 1, OF_NORMAL)) == NULL)		return 1;	if (tf_read(buf, 12, 1, tf) != 1			|| memcmp(&buf[0], "RIFF", 4) != 0 || memcmp(&buf[8], "WAVE", 4) != 0)	{		close_file(tf);		return 1;	}	ctl->cmsg(CMSG_INFO, VERB_NOISY, "Loading WAV: %s", sample_file);	state = chunk_flags = 0;	type_index = 4, type_size = 8;	for(;;) {		if (tf_read(&buf[type_index], type_size, 1, tf) != 1)			break;		chunk_size = LE_LONG(*(int32 *)&buf[4 + 4]);		if (memcmp(&buf[4 + 0], "fmt ", 4) == 0)		{			if (state != 0					/* only one format chunk is required */					|| chunk_size < 0x10)	/* too small */				break;			if (!read_WAVFormatChunk(tf, &format, chunk_size))				break;			if (format.wChannels < 1				/* invalid range */					|| format.wChannels > MAX_SAMPLE_CHANNELS					|| format.wFormatTag != 1		/* compressed */					|| format.wBitsPerSample & 0x7	/* padding not supported */					|| format.wBitsPerSample > 16)	/* more than 16-bit is not supported */				break;			state++;		}		else if (memcmp(&buf[4 + 0], "data", 4) == 0)		{			int				frames;			sample_t		*sdata[MAX_SAMPLE_CHANNELS];						if (state != 1)				break;			frames = chunk_size / format.wBlockAlign;			inst->samples = samples = format.wChannels;			inst->sample = (Sample *)safe_malloc(sizeof(Sample) * samples);			ctl->cmsg(CMSG_INFO, VERB_NOISY, "Format: %d-bits %dHz %dch, %d frames",					format.wBitsPerSample, format.dwSamplesPerSec, samples, frames);			initialize_sample(inst, frames, format.wBitsPerSample, format.dwSamplesPerSec);			/* load waveform data */			for(i = 0; i < samples; i++)			{				inst->sample[i].data = sdata[i] = (sample_t *)safe_malloc(sizeof(sample_t) * frames);				inst->sample[i].data_alloced = 1;			}			if (!read_sample_data(SAMPLE_8BIT_UNSIGNED, tf, format.wBitsPerSample, samples, frames, sdata))				break;			state++;		}		else if (!(chunk_flags & WAVE_CHUNKFLAG_SAMPLER) && memcmp(&buf[4 + 0], "smpl", 4) == 0)		{			if (!read_WAVSamplerChunk(tf, &samplerc, chunk_size))				break;			chunk_flags |= WAVE_CHUNKFLAG_SAMPLER;		}		else if (!(chunk_flags & WAVE_CHUNKFLAG_INSTRUMENT) && memcmp(&buf[4 + 0], "inst", 4) == 0)		{			if (!read_WAVInstrumentChunk(tf, &instc, chunk_size))				break;			chunk_flags |= WAVE_CHUNKFLAG_INSTRUMENT;		}		else if (tf_seek(tf, chunk_size, SEEK_CUR) == -1)			break;		type_index = 4 - (chunk_size & 1);		type_size = 8 + (chunk_size & 1);	}	close_file(tf);	if (chunk_flags & WAVE_CHUNKFLAG_SAMPLER)	{		uint8		modes;		int32		sample_rate, root_freq;		uint32		loopStart, loopEnd;				sample_rate = 1000000000 / samplerc.dwSamplePeriod;		root_freq = freq_table[samplerc.dwMIDIUnityNote];		if (samplerc.dwMIDIPitchFraction != 0				&& samplerc.dwMIDIUnityNote != 127)	/* no table data */		{			int32		diff;						diff = freq_table[samplerc.dwMIDIUnityNote + 1] - root_freq;			root_freq += (float)samplerc.dwMIDIPitchFraction * diff / 0xFFFFFFFF;		}		if (samplerc.hasLoop)		{			const uint8		loopModes[] = {MODES_LOOPING, MODES_LOOPING | MODES_PINGPONG, MODES_LOOPING | MODES_REVERSE};						modes = loopModes[samplerc.loopType];			loopStart = samplerc.loop_dwStart << FRACTION_BITS;			loopEnd = samplerc.loop_dwEnd << FRACTION_BITS;		}

⌨️ 快捷键说明

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