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

📄 track_smf.c

📁 一个很好的c++ midi解码算法,不依赖于任何平台.
💻 C
字号:
/* *  track_smf.cc *  Copyright (C) 1998-2000 SAKAI Katsuya * *  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 */#include <stdio.h> // #include <iostream.h>#include <sys/types.h>#include "config.h"#include "extern.h"#include "smf.h"#include "defines.h"#include "midievdefs.h"u_long SMF_Chunk::ReadVarLen(){  register int value;  if((value=Data[Index])&0x80)    {      value &= 0x7F;      do {	Index++;	if (Length<=Index) return 0;	value = (value<<7) + (Data[Index]&0x7F);      } while(Data[Index]&0x80);    }  Index++;  return value;}u_long SMF_Chunk::ReadLen(int len){  register int value;  value = Data[Index++];  while(--len)    value = (value<<8) + Data[Index++];  return value;}void SMF_Track::init(){  Port = 0;  Index = 0;  Tick = ReadVarLen();  for(int i=0;i<16;i++)    LocalLastStatus[i]=0;}int SMF_Track::playaEvent(){  u_char nextevent;  u_long len;  int rtn=0;  #ifdef SHOW_EVENT  cout << dec <<  "Tick:" << Tick << " Track:"  << Number;#endif    if(!(EVENT&0x80))    {	#ifdef SHOW_EVENT      cout << " (rs)";#endif	  nextevent = LocalLastStatus[Port];    }  else    {      LocalLastStatus[Port] = nextevent = EVENT;      Index++;    }  # ifdef SHOW_EVENT  cout << ' ' << hex << (int)nextevent << ' ';# endif    switch (nextevent&0xf0)    {    case MIDI_NOTEOFF: case MIDI_NOTEON:    case MIDI_KEY_PRESSURE: case MIDI_CTL_CHANGE: case MIDI_PITCH_BEND:      if (Length<Index+1)	{#ifdef SHOW_INFO	  cout << "data error" << endl;#endif	  return -2;	}      aSequencer->midiEvent2(Port, nextevent, Data[Index], Data[Index+1]);#ifdef SHOW_EVENT      cout << (int)Data[Index] << ' ' << (int)Data[Index+1] << ' ';#endif      Index += 2;      break;    case MIDI_PGM_CHANGE: case MIDI_CHN_PRESSURE:      if (Length<Index)	{#ifdef SHOW_INFO	  cout << "data error2" << endl;#endif	  return -2;	}      aSequencer->midiEvent1(Port, nextevent, Data[Index]);#ifdef SHOW_EVENT      cout << (int)Data[Index]  << ' ';#endif      Index++;      break;    case MIDI_SYSTEM_PREFIX:      if(nextevent==META_EVENT)	{	  u_char MetaType;	  MetaType = Data[Index++];	  len = ReadVarLen(); #ifdef SHOW_INFO	      cout << "len=" << len << " ";#endif	  if (Length<Index+len)	    {#ifdef SHOW_INFO	      cout << "data error 3: Length=" << Length		   << ", Index=" << Index << endl;#endif	      return -2;	    }	  switch(MetaType)	    {	    case META_TEMPO:	      if(len!=3)		{#             ifdef SHOW_EVENT		  cout << "invalid tempo value" << endl;#             endif		  ReadLen(len);		}	      else		{ 		  // *Tempo = ReadLen(3);		  aSequencer->set_tempo (ReadLen (3));#             ifdef SHOW_EVENT		  cout << "tempo:" << dec << aSequencer->show_tempo() << hex << ' ';#             endif		}	      break;	    case META_PORT_CHANGE:	      if(len!=1)		{		  ReadLen(len);#             ifdef SHOW_EVENT		  cout << "invalid port change event" << endl;#             endif		}	      else		{		  Port = ReadLen(1);#             ifdef SHOW_EVENT		  cout << "port : " << (int)Port << ' ';				  #             endif		}	      break;	    case META_TRACKEND:	      Tick=~0;#             ifdef SHOW_EVENT	      cout << "End of Track" << endl;#             endif	      return -1;	      break;	      	    default:#             ifdef SHOW_EVENT	      cout << "Meta Event ";#             endif	      	      u_int i;	      char *metadata = new char [len];	      for (i=0;i<len;i++)		metadata[i] = Data[Index++];	      aSequencer->metaEvent (MetaType, len, metadata);	      	      delete [] metadata;	      // Index += len;	      break;	    }	}      else       // exclusive message	{	  u_char ex[512];	  int exlen=0;#ifdef RUNNING_ST	  aSequencer->clearStatus(Port);#endif	  len = ReadVarLen();	  ex[exlen++] = nextevent;	  for(u_long i=0;i<len;i++)	    {#ifdef SHOW_EVENT	      cout << (int)Data[Index] << ' ';#endif	      ex[exlen++] = Data[Index++];	    }	  aSequencer->send_exclusive (Port, ex, exlen);	}      break;    default:      printf("unknown status\n"); // cout << "unknown status" << endl;      return -3;      break;    }    len = ReadVarLen ();  Tick += len;  # ifdef SHOW_EVENT  cout << "\tNextTick:" << Tick << endl;# endif  if (Length<=Index)    {#ifdef SHOW_INFO      cout << "data error 4" << endl;#endif      return -2;    }    if (len==0L)    rtn = playaEvent ();   return rtn;}

⌨️ 快捷键说明

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