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

📄 player_r36.c

📁 一个很好的c++ midi解码算法,不依赖于任何平台.
💻 C
字号:
/* *  player_r36.cc *  Copyright (C) 1998,1999 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 <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <string.h>#include <stdio.h>#include "config.h"#include "sequencer.h"#include "player.h"#include "defines.h"#include "extern.h"R36_Player::R36_Player(){  Track=NULL;}R36_Player::~R36_Player(){  clear();}//介袋肋年void R36_Player::init(){  u_long n;  Event *NextEvent;  for(n=0;n<Header.NumOfTrack;n++)	{	  Track[n].init(&Header, &Exclusive, &Noff_Queue);	  NextEvent = new Event;	  NextEvent->Type = EV_NORMAL;	  NextEvent->Track = n;	  NextEvent->Time = Track[n].tick();	  Queue.store(NextEvent);	}}//遍琳メインル〖チンvoid R36_Player::play(){  Event *Next;  if(Noff_Queue.NextTime()>Queue.NextTime())	{	  Next = Queue.retrieve();	}  else	{	  Next = Noff_Queue.retrieve();	}  aSequencer->startTimer();  while(Next!=NULL && stop==FALSE && next==FALSE)	{	  aSequencer->waitTime(Next->Time);	  if(Next->Type == EV_NOTE_OFF)		{		  NoteOff(Next);		  delete Next;		}	  else		{		  if(Track[Next->Track].playaEvent()<0)			{			  delete Next;			}		  else			{			  Next->Time = Track[Next->Track].tick();			  Queue.store(Next);			}		}	  	  if(Noff_Queue.NextTime()>Queue.NextTime())		{		  Next = Queue.retrieve();		}	  else		{		  Next = Noff_Queue.retrieve();		}	}  if(stop==TRUE || next==TRUE)	{	  aSequencer->reset();	  aSequencer->seqbuf_clear();	  AllNoteOff();	  while((Next=Queue.retrieve())!=NULL) delete Next;	  next=FALSE;	}  aSequencer->stopTimer();    if(stop==TRUE)	{#ifdef SHOW_INFO	  cout << "stop." << endl;#endif	  aSequencer->close();	  exit(1);	}}void R36_Player::AllNoteOff(){  Event *off;  while((off=Noff_Queue.retrieve())!=NULL)	NoteOff(off);  aSequencer->seqbuf_dump();  for(u_long n=0;n<Header.NumOfTrack;n++)	{	  Track[n].AllNoteOff();	}	}void R36_Player::NoteOff(Event *off){  (Track[off->Track].N_ON[off->Note])--;# ifdef SHOW_EVENT  cout << "Tick:" << dec << off->Time 	   << " Channel:" <<(int)off->Channel+1	   << " Note:" << hex << (int)off->Note	   << " NoteOff(" <<  (int) Track[off->Track].N_ON[off->Note] << ')' ;# endif  if(Track[off->Track].N_ON[off->Note] == 0)	{	  aSequencer->midiEvent2(off->Port, 0x90|off->Channel, off->Note, 0x0);	}#ifdef SHOW_EVENT  else if(Track[off->Track].N_ON[off->Note] < 0)	{	  Track[off->Track].N_ON[off->Note]=0;	  cout << "- BUG!?" << endl;	}	    else	{	  cout << " - ingore";	}  cout << endl;#endif}void R36_Player::clear(){  if(Track!=NULL)	{	  delete [] Track;	  Track=NULL;	}}/*  load  喇根 : 0  error:  -1: RCPfileオ〖プンエラ〖  -2: unknown format  -3: file broken    -4: memory allocation error*/int R36_Player::load(char *filename){  int songfd;  clear();  if (filename==NULL)	songfd = fileno(stdin);  else	songfd = open(filename, O_RDONLY);  if(songfd<0)	{	  return -1;	}    // ヘッダの矢机误チェック  read(songfd, Header.Text, 32);  u_long n;#ifdef SHOW_HEADER  for(n=0;n<28;n++)	{	  cout << Header.Text[n];	}  cout << endl;#endif  if(strncmp(Header.Text, "RCM-PC98V2.0(C)COME ON MUSIC", 28)!=0)	{	  if (filename==NULL)		close(songfd);	  return -2;	}    // ヘッダデ〖タ粕み哈み  char buffer[80];  int timebase;  read(songfd, Header.Title, 64);  read(songfd, Header.Memo, 336);  read(songfd, buffer, 16 );  read(songfd, buffer, 1 );  timebase = buffer[0]&0xff;  read(songfd, buffer, 1 );  Header.Tempo = buffer[0]&0xff;  aSequencer->set_tempo (60*1000000/Header.Tempo);  read(songfd, Header.TimeSignature, 2);  read(songfd, &Header.Key, 1);  read(songfd, &Header.PlayBIAS, 1);  read(songfd, Header.CM6file, 14);  read(songfd, Header.GSDfile, 14);  read(songfd, buffer, 4);  read(songfd, buffer, 1 );  Header.NumOfTrack = buffer[0]&0xff;  read(songfd, buffer, 1);  aSequencer->set_timebase (timebase + buffer[0]*256);  read(songfd, buffer, 30);  if(Header.NumOfTrack==0) Header.NumOfTrack=18;#ifdef SHOW_HEADER  cout << endl	   << "Title   :" << (u_int)Header.Title << endl	   << "Timebase:" << (u_int)aSequencer->show_timebase () << endl	   << "Tempo   :" << Header.Tempo << endl	   << "BIAS    :" << (int)Header.PlayBIAS << endl	   << "TimeSignature:" << (int) Header.TimeSignature[0]	   << "/" << (int) Header.TimeSignature[1] << endl	   << "Track   :" << (u_int)Header.NumOfTrack << endl;#endif#if defined(SHOW_RYTHM) || defined(SHOW_USEREX) || defined(SHOW_THEADER)  int name;#endif  // リズム不富年盗の粕み哈み  for(n=0;n<32;n++)	{	  read(songfd, Rythm.Name[n], 14);	  read(songfd, &Rythm.Key[n], 1);	  read(songfd, &Rythm.GateTime[n], 1);#ifdef SHOW_RYTHM	  cout << "RythmDefine read:";	  for(name=0;name<14;name++) cout << Rythm.Name[n][name];	  cout << " key:" << (int)Rythm.Key[n]		   << " GT:" << (int)Rythm.GateTime[n] << endl;  #endif	}    // ユ〖ザエクスクル〖シブ年盗の粕み哈み  for(n=0;n<8;n++)	{	  read(songfd, Exclusive.Memo[n], 24);	  if (read(songfd, Exclusive.Data[n], 24)<24)		{ 		  if (filename==NULL)			close (songfd);		  return -3;		}#ifdef SHOW_USEREX	  cout << "UserExclusiveDefine read :";	  for(name=0;name<24;name++) cout << Exclusive.Memo[n][name];	  cout << endl; #endif	}    Track = new R36_Track [Header.NumOfTrack];  if(!Track)	{	  if (filename==NULL)		close(songfd);	  return -4;	}    // トラックデ〖タの粕み哈み  for(n=0;n<Header.NumOfTrack;n++)	{	  read(songfd, buffer, 2);	  Track[n].DataLength =(u_long) (buffer[1]&0xff)<<8 | (buffer[0]&0xff);	  read(songfd, &Track[n].Number, 1);	  read(songfd, &Track[n].RythmFlag, 1);	  read(songfd, &Track[n].Channel, 1);	  read(songfd, &Track[n].Key_Bias, 1);	  read(songfd, &Track[n].ST_Bias, 1);	  read(songfd, &Track[n].Mode, 1);	  if (read(songfd, Track[n].Comment, 36)<36)		{		  Header.NumOfTrack = n;		  continue;		}	  if(Track[n].Number!=n+1)		{		  //		  cout <<  "warning: broken file?" << endl;		  Track[n].Number=n+1;		}#ifdef SHOW_THEADER	  cout << endl		   << "Ch+Dev(0xff:off):" << hex << (int)Track[n].Channel << dec;#endif	  if(Track[n].Channel==0xff) Track[n].Mute=TRUE;	  Track[n].Port = (Track[n].Channel&0xf0)>>4;	  Track[n].Channel = Track[n].Channel & 0xf;	  Track[n].Version = V_RCP;#ifdef SHOW_THEADER	  cout << endl		   <<"Track :" << (int)Track[n].Number << endl		   << "RythmFlag:" << (int)Track[n].RythmFlag << endl;	  if(Track[n].Mute==FALSE)		{		  cout << "Port:" << (int)Track[n].Port << endl			   << "Channel:" << (int)Track[n].Channel+1 << endl;		}	  else		{		  cout << "Port: OFF" << endl << "Channel: OFF" << endl;		}	  cout << "DataLength:" << Track[n].DataLength << endl		   << "Key+:" << (int)Track[n].Key_Bias << endl 		   << "ST:" << (int)Track[n].ST_Bias << endl 		   << "Mode:" << (int)Track[n].Mode << endl 		   << endl		   << "Comment:";	  for(name=0;name<36;name++) cout << Track[n].Comment[name];	  cout << endl;#endif	  	  Track[n].Data = new u_char [ Track[n].DataLength-44 ];	  if(!(Track[n].Data))		{		  delete [] Track;		  Track = NULL;		  if (filename==NULL)			close(songfd);		  return -4;		}	  if (read (songfd, Track[n].Data, Track[n].DataLength-44)		  <Track[n].DataLength-44)		{		  if (filename==NULL)			close (songfd);		  return -3;		}	}  if (filename==NULL)	close (songfd);  return 0;}

⌨️ 快捷键说明

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