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

📄 mod2midi.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    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    mod2midi.c    Mixer event -> MIDI event conversion*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include "timidity.h"#include "common.h"#include "instrum.h"#include "playmidi.h"#include "readmidi.h"#include "tables.h"#include "mod.h"#include "output.h"#include "controls.h"#include "unimod.h"#include "mod2midi.h"#include "filter.h"#include "math.h"#include "freq.h"/* Define this to show all the notes touched by a bending in the * user interface's trace view.  This is interesting but disabled * because it needs tons of CPU power (tens of voices are activated * but unaudible). *//* #define TRACE_SLIDE_NOTES *//* Define this to give a volume envelope to a MOD's notes. This * could sound wrong with a few MODs, but gives richer sound most * of the time. */#define USE_ENVELOPE#define SETMIDIEVENT(e, at, t, ch, pa, pb) \    { /* printf("%d %d " #t " %d %d\n", at, ch, pa, pb); */ \      (e).time = (at); (e).type = (t); \      (e).channel = (uint8)(ch); (e).a = (uint8)(pa); (e).b = (uint8)(pb); }#define MIDIEVENT(at, t, ch, pa, pb) \    { MidiEvent event; SETMIDIEVENT(event, at, t, ch, pa, pb); \      readmidi_add_event(&event); }/*		   Clock   SampleRate := ----------		   Period */#define NTSC_CLOCK 3579545.25#define NTSC_RATE ((int32)(NTSC_CLOCK/428))#define PAL_CLOCK 3546894.6#define PAL_RATE ((int32)(PAL_CLOCK/428))#define MOD_ROOT_NOTE      36/* The internal bending register is 21-bits wide and it is made like this: *  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ * | | | | | | | | | | | | | | | | | | | | | | * |    8 bits     |    8 bits     |  5 bits | * |  note  shift  |   fine tune   |discarded| * '---------------'---------------'---------' * * The note shift is an `offset' field: 128 = keep this note. * To compute it, the values given to the pitch-wheel MIDI event are * multiplied by the sensitivity. We want to be able to express a full * 120 notes bending (8 bits for the note shift + 8 for the fine tune) * with 14-bit pitch-wheel event, so we want a sensitivity value that * forces the bottom 7 bits of the internal register to 0.  This value * is of course 128. */#define WHEEL_SENSITIVITY 		(1 << 7)#define WHEEL_VALUE(bend)		((bend) / WHEEL_SENSITIVITY + 0x2000)typedef struct _ModVoice  {    int sample;			/* current sample ID */    int noteon;			/* (-1 means OFF status) */    int time;			/* time when note was activated */    int period;			/* current frequency */    int wheel;			/* current pitch wheel value */    int pan;			/* current panning */    int vol;			/* current volume */    int32 noteson[4];		/* bit map for notes 0-127 */  }ModVoice;static void mod_change_tempo (int32 at, int bpm);static int period2note (int period, int *finetune);static ModVoice ModV[MOD_NUM_VOICES];static int at;/******************** bitmap handling macros **********************************/#define bitmapGet(map, n)	((map)[(n) >> 5] &  (1 << ((n) & 31)))#define bitmapSet(map, n)	((map)[(n) >> 5] |= (1 << ((n) & 31)))#define bitmapClear(map)	((map)[0] = (map)[1] = (map)[2] = (map)[3] = 0)static char significantDigitsLessOne[256] = {    -1,							/* 1 */    0,							/* 2 */    1, 1,						/* 4 */    2, 2, 2, 2,						/* 8 */    3, 3, 3, 3, 3, 3, 3, 3,				/* 16 */    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,	/* 32 */    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,	/* 64 */    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,	/* 128 */    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,	/* 256 */    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};/******************************************************************************/voidmod_change_tempo (int32 at, int bpm){  int32 tempo;  int c, a, b;  tempo = 60000000 / bpm;  c = (tempo & 0xff);  a = ((tempo >> 8) & 0xff);  b = ((tempo >> 16) & 0xff);  MIDIEVENT (at, ME_TEMPO, c, b, a);}intperiod2note (int period, int *finetune){  static int period_table[121] =  {  /*  C     C#    D     D#    E     F     F#    G     G#    A     A#    B  */     13696,12928,12192,11520,10848,10240, 9664, 9120, 8608, 8096, 7680, 7248,      6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4048, 3840, 3624,      3424, 3232, 3048, 2880, 2712, 2560, 2416, 2280, 2152, 2024, 1920, 1812,      1712, 1616, 1524, 1440, 1356, 1280, 1208, 1140, 1076, 1016,  960,  906,       856,  808,  762,  720,  678,  640,  604,  570,  538,  508,  480,  453,       428,  404,  381,  360,  339,  320,  302,  285,  269,  254,  240,  226,       214,  202,  190,  180,  170,  160,  151,  143,  135,  127,  120,  113,       107,  101,   95,   90,   85,   80,   75,   71,   67,   63,   60,   56,	53,   50,   47,   45,   42,   40,   37,   35,   33,   31,   30,   28,	27,   25,   24,   22,   21,   20,   19,   18,   17,   16,   15,   14,	  	-100 /* just a guard */  };  int note;  int l, r, m;  if (period < 14 || period > 13696)  {    ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "BAD period %d\n", period);    return -1;  }  /* bin search */  l = 0;  r = 120;  while (l < r)    {      m = (l + r) / 2;      if (period_table[m] >= period)	l = m + 1;      else	r = m;    }  note = l - 1;  /*   * 112 >= note >= 0   * period_table[note] >= period > period_table[note + 1]   */  if (period_table[note] == period)    *finetune = 0;  else {    /* Pick the closest note even if it is higher than this one.     * (e.g. 721 - 720 < 762 - 721 ----> pick 720)    */    if (period - period_table[note + 1] < period_table[note] - period)      note++;        /* fine tune completion */    *finetune = ((period_table[note] - period) << 8) /		   (period_table[note] - period_table[note + 1]);    *finetune <<= 5;  }  return note;}/********** Interface to mod.c */voidVoice_SetVolume (UBYTE v, UWORD vol){  if (v >= MOD_NUM_VOICES)    return;  /* MOD volume --> MIDI volume */  vol >>= 1;  /* if (vol < 0) vol = 0; *//* UNSIGNED! */  if (vol > 127) vol = 127;  if (ModV[v].vol != vol) {    ModV[v].vol = vol;    MIDIEVENT (at, ME_EXPRESSION, v, vol, 0);  }}voidVoice_SetPeriod (UBYTE v, ULONG period){  int new_noteon, bend;  if (v >= MOD_NUM_VOICES)    return;  ModV[v].period = period;  if (ModV[v].noteon < 0)    return;  new_noteon = period2note (ModV[v].period, &bend);#ifndef TRACE_SLIDE_NOTES  bend += (new_noteon - ModV[v].noteon) << 13;  new_noteon = ModV[v].noteon;#endif  bend = WHEEL_VALUE(bend);  if (ModV[v].noteon != new_noteon)    {      MIDIEVENT(at, ME_KEYPRESSURE, v, ModV[v].noteon, 1);      if (new_noteon < 0)        {	  ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,			  "Strange period %d",			  ModV[v].period);	  return;	}      else if (!bitmapGet(ModV[v].noteson, new_noteon))	{	  MIDIEVENT(ModV[v].time, ME_NOTEON, v, new_noteon, 1);	  bitmapSet(ModV[v].noteson, new_noteon);	}    }  if (ModV[v].wheel != bend)    {      ModV[v].wheel = bend;      MIDIEVENT (at, ME_PITCHWHEEL, v, bend & 0x7F, (bend >> 7) & 0x7F);    }  if (ModV[v].noteon != new_noteon)    {      MIDIEVENT(at, ME_KEYPRESSURE, v, new_noteon, 127);      ModV[v].noteon = new_noteon;    }}voidVoice_SetPanning (UBYTE v, ULONG pan){  if (v >= MOD_NUM_VOICES)    return;  if (pan == PAN_SURROUND)    pan = PAN_CENTER; /* :-( */  if (pan != ModV[v].pan) {    ModV[v].pan = pan;    MIDIEVENT(at, ME_PAN, v, pan * 127 / PAN_RIGHT, 0);  }}voidVoice_Play (UBYTE v, SAMPLE * s, ULONG start){  int new_noteon, bend;  if (v >= MOD_NUM_VOICES)    return;  if (ModV[v].noteon != -1)    Voice_Stop (v);  new_noteon = period2note (ModV[v].period, &bend);  bend = WHEEL_VALUE(bend);  if (new_noteon < 0) {    ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,			  "Strange period %d",			  ModV[v].period);    return;  }  ModV[v].noteon = new_noteon;  ModV[v].time = at;  bitmapSet(ModV[v].noteson, new_noteon);  if (ModV[v].sample != s->id)    {      ModV[v].sample = s->id;      MIDIEVENT(at, ME_SET_PATCH, v, ModV[v].sample, 0);    }  if (start > 0)    {      int a, b;

⌨️ 快捷键说明

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