2007年12月2日星期日

rm文件格式

rm文件格式

RealMedia File Format (RMFF)
RealSystem Architecture introduces RealMedia File Format (RMFF), which lets RealSystem deliver high-quality multimedia
content over a variety of network bandwidths. Third-party developers can convert their media formats into RMFF, enabling
RealServer to deliver the files to RealPlayer or other applications built with the RealSystem SDK. Third-party developers
can thereby use RealSystem to transport content over the Internet to their own applications.

RealMedia File Format is a standard tagged file format that uses Four-Character codes to identify file elements. These codes
are 32-bit, represented by a sequence of one to four ASCII alphanumeric characters, padded on the right with space
characters. The data type for four-character codes is FOURCC. Use the PN_FOURCC macro to convert four characters into
a four-character code.

The basic building block of a RealMedia File is a chunk, which is a logical unit of data, such as a stream header or a packet of
data. Each chunk contains the following fields:

four-character code specifying the chunk identifier 32-bit value specifying the size of the data member in the chunk
blob of opaque chunk data Depending on its type, a top-level chunk can contain subobjects. This document describes the
tagged chunks contained in RMFF, as well as the format of the data stored in each type of tagged chunk.

Tagged File Formats:

Header Section Because RMFF is a tagged file format, the order of the chunks is not explicit, except that the RealMedia File
Header must be the first chunk in the file. However, most applications write the standard headers into the file's header
section. The following chunks are typically found in the header section of RMFF:
1.RealMedia File Header (This must be the first chunk of the file)
2.Properties Header
3.Media Properties Header
4.Content Description Header After the RealMedia File Header object, the other headers may appear in any order. All headers
are required except the Index Header. The following sections describe the individual header objects .
RealMedia File Header Each RealMedia file begins with the RealMedia File Header, which identifies the file as RMFF. There
is only one RealMedia File Header in a RealMedia file. Because the contents of the RealMedia File Header may change with
different versions of RMFF, the header structure supports an object version field for determining what additional fields
exists. The following pseudo-structure describes the RealMedia File Header:

RealMedia_File_Header
{
UINT32 object_id;
UINT32 size;
UINT16 object_version;
if (object_version == 0)
{ UINT32 file_version;
UINT32 num_headers;
}
}

The RealMedia File Header contains the following fields:

1. object_id: 32 bits The unique object ID for a RealMedia File (.RMF). All RealMedia files begin with this identifier.
2. size: 32 bits The size of the RealMedia header section in bytes.
3. object_version: 16 bits The version of the RealMedia File Header object. All files created according to this specification
have an object_version number of 0 (zero).
4. file_version: 32 bits The version of the RealMedia file in PN Version format. All files created according to this specification
have a major version number of 1. This member is present on all RealMedia_File_Header objects with an object_version
of 0 (zero).
5. num_headers: 32 bits The number of headers in the header section that follow the RealMedia File Header. This member
is present on all RealMedia_File_Header objects with an object_version of 0 (zero).

Properties Header The Properties Header describes the general media properties of the RealMedia File. Components of the
RealMedia system use this object to configure themselves for handling the data in the RealMedia file or stream. There is only
one Properties Header in a RealMedia file. The following pseudo-structure describes the Properties header:

Properties
{
UINT32 object_id;
UINT32 size;
UINT16 object_version;
if (object_version == 0)
{
UINT32 max_bit_rate;
UINT32 avg_bit_rate;
UINT32 max_packet_size;
UINT32 avg_packet_size;
UINT32 num_packets;
UINT32 duration;
UINT32 preroll;
UINT32 index_offset;
UINT32 data_offset;
UINT16 num_streams;
UINT16 flags;
}
}

The Properties Header contains the following fields:
1. object_id: 32 bits The unique object ID for a Properties Header ('PROP').
2. size: 32 bits The size of the Properties Header in bytes.
3. object_version: 16 bits The version of the RealMedia File Header object. All files created according to this specification
have an object_version number of 0 (zero).
4. max_bit_rate: 32 bits The maximum bit rate required to deliver this file over a network. This member is present on all
Properties objects with an object_version of 0 (zero).
5. avg_bit_rate: 32 bits The average bit rate required to deliver this file over a network. This member is present on all
Properties objects with an object_version of 0 (zero).
6. max_packet_size: 32 bits The largest packet size (in bytes) in the media data. This member is present on all Properties
objects with an object_version of 0 (zero).
7. avg_packet_size: 32 bits The average packet size (in bytes) in the media data. This member is present on all Properties
objects with an object_version of 0 (zero).
8. num_packets: 32 bits The number of packets in the media data. This member is present on all Properties objects with an
object_version of 0 (zero).
9. duration: 32 bits The duration of the file in milliseconds. This member is present on all Properties objects with an
object_version of 0 (zero).
10. preroll: 32 bits The number of milliseconds to pre-buffer before starting playback. This member is present on all
Properties objects with an object_version of 0 (zero).
11. index_offset: 32 bits The offset in bytes from the start of the file to the start of the index header object. This member is
present on all Properties objects with an object_version of 0 (zero).
12. data_offset: 32 bits The offset in bytes from the start of the file to the start of the Data Section. This member is present
on all Properties objects with an object_version of 0 (zero).
13. num_streams: 16 bits The number of media streams contained in the file. This member is present on all Properties
objects with an object_version of 0 (zero).
14. flags: 16 bits Flags indicating characteristics of the RealMedia file. The following flags are defined:

#define PN_SAVE_ENABLED 0x0001 Allows clients to save a copy of the RealMedia file to disk.
#define PN_PERFECT_PLAY_ENABLED 0x0002 Allows clients to use extra buffering to ensure Perfect Play.
#define PN_LIVE_BROADCAST 0x0004 The RealMedia file is being generated by a live broadcast.

Media Properties Header The Media Properties Header describes the specific media properties of each stream in a
RealMedia File. Components of the RealMedia system use this object to configure themselves for handling the media data
in each stream. There is one Media Properties Header for each media stream in a RealMedia file. The following
pseudo-structure describes the Media Properties header:

Media_Properties
{
UINT32 object_id;
UINT32 size;
UINT16 object_version;
if (object_version == 0)
{
UINT16 stream_number;
UINT32 max_bit_rate;
UINT32 avg_bit_rate;
UINT32 max_packet_size;
UINT32 avg_packet_size;
UINT32 start_time;
UINT32 preroll;
UINT32 duration;
UINT8 stream_name_size;
UINT8[stream_name_size] stream_name;
UINT8 mime_type_size;
UINT8[mime_type_size] mime_type;
UINT32 type_specific_len;
UINT8[type_specific_len] type_specific_data;
}
}

The Media Properties Header contains the following fields:
1. object_id: 32 bits The unique object ID for a Media Properties Header ("MDPR").
2. size: 32 bits The size of the Media Properties Header in bytes.
3. object_version: 16 bits The version of the Media Properties Header object.
4. stream_number: 32 bits The stream_number (synchronization source identifier) is a unique value that identifies a media
stream. Every data packet that belongs to a media stream contains the same STREAM_NUMBER. The STREAM_NUMBER
enables a receiver of multiple media streams to distinguish which packets belong to each media stream. This member is
present on all MediaProperties objects with an object_version of 0 (zero).
5. max_bit_rate: 32 bits The maximum bit rate required to deliver this stream over a network. This member is present on all
MediaProperties objects with an object_version of 0 (zero).
6. avg_bit_rate: 32 bits The average bit rate required to deliver this stream over a network. This member is present on all
MediaProperties objects with an object_version of 0 (zero).
7. max_packet_size: 32 bits The largest packet size (in bytes) in the stream of media data. This member is present on all
MediaProperties objects with an object_version of 0 (zero).
8. avg_packet_size: 32 bits The average packet size (in bytes) in the stream of media data. This member is present on all
MediaProperties objects with an object_version of 0 (zero).
9. start_time: 32 bits The time offset in milliseconds to add to the timestamp of each packet in a media stream. This member
is present on all MediaProperties objects with an object_version of 0 (zero).
10. preroll: 32 bits The time offset in milliseconds to subtract to the timestamp of each packet in a media stream. This member
is present on all MediaProperties objects with an object_version of 0 (zero).
11. duration: 32 bits The duration of the stream in milliseconds. This member is present on all MediaProperties objects with
an object_version of 0 (zero).
12. stream_name_size: 8 bits The length of the following stream_name field in bytes. This member is present on all
MediaProperties objects with an object_version of 0 (zero).
13. stream_name: variable length A non-unique alias or name for the stream. This member is present on all MediaProperties
objects with an object_version of 0 (zero).
14. mime_type_size: 8 bits The length of the following mime_type field in bytes. This member is present on all MediaProperties
objects with an object_version of 0 (zero).
15. mime_type: variable length A non-unique MIME style type/subtype string for data associated with the stream. This member
is present on all MediaProperties objects with an object_version of 0 (zero).
16. type_specific_len: 32 bits The length of the following type_specific_data in bytes. The type_specific_data is typically used
by the datatype renderer to initialize itself in order to process the media stream. This member is present on all
MediaProperties objects with an object_version of 0 (zero).
17. type_specific_data: variable length The type_specific_data is typically used by the data-type renderer to initialize itself in
order to process the media stream. This member is present on all MediaProperties objects with an object_version of 0 (zero).

Content Description Header The Content Description Header contains the title, author, copyright, and comments information
for the RealMedia File. All text data is in ASCII format. The following pseudo-structure describes the Content Description
Header:

Content_Description
{
UINT32 object_id;
UINT32 size;
UINT16 object_version;
if (object_version == 0)
{
UINT16 title_len;
UINT8[title_len] title;
UINT16 author_len;
UINT8[author_len] author;
UINT16 copyright_len;
UINT8[copyright_len] copyright;
UINT16 comment_len;
UINT8[comment_len] comment;
}
}

The Content Description Header contains the following fields:
1. object_id: 32 bits The unique object ID for the Content Description Header ('CONT').
2. size: 32 bits The size of the Content Description Header in bytes.
3. object_version: 16 bits The version of the Content Description Header object.
4. title_len: 16 bits The length of the title data in bytes. Note that the title data is not null terminated. This member is present
on all Content Description Header objects with an object_version of 0 (zero).
5. title: variable length An array of ASCII characters that represents the title information for the RealMedia file. This member
is present on all Content Description Header objects with an object_version of 0 (zero).
6. author_len: 16 bits The length of the author data in bytes. Note that the author data is not null terminated. This member is
present on all Content Description Header objects with an object_version of 0 (zero).
7. author: variable length An array of ASCII characters that represents the author information for the RealMedia file. This
member is present on all Content Description Header objects with an object_version of 0 (zero).
8. copyright_len: 16 bits The length of the copyright data in bytes. Note that the copyright data is not null terminated. This
member is present on all Content Description Header objects with an object_version of 0 (zero).
9. copyright: variable length An array of ASCII characters that represents the copyright information for the RealMedia file. this
member is present on all Content Description Header objects with an object_version of 0 (zero).
10. comment_len: 16 bits The length of the comment data in bytes. Note that the comment data is not null terminated. this
member is present on all Content Description Header objects with an object_version of 0 (zero).
11. comment: variable length An array of ASCII characters that represents the comment information for the RealMedia file.
This member is present on all Content Description Header objects with an object_version of 0 (zero).

Data Section The data section of the RealMedia file consists of a Data Section Header that describes the contents of the data
section, followed by a series of interleaved media data packets. Note that the size field of the Data Chunk Header is the size
of the entire data chunk, including the media data packets.

Data Chunk Header The Data Chunk Header marks the start of the data chunk. There is usually only one data chunk in a
RealMedia file, however for extremely large files there may be multiple data chunks. The following pseudo-structure
describes the Data chunk header:

Data_Chunk_Header
{
UINT32 object_id;
UINT32 size;
UINT16 object_version;
if (object_version == 0)
{
UINT32 num_packets;
UINT32 next_data_header;
}
}

The Data Chunk Header contains the following fields:
1. object_id: 32 bits The unique object ID for the Data Chunk Header ('DATA').
2. size: 32 bits The size of the Data Chunk in bytes.
3. object_version: 16 bits The version of the Data Chunk Header object.
4. num_packets: 32 bits Number of packets in the data chunk. This member is present on all Data Chunk Header objects with
an object_version of 0 (zero).
5. next_data_header: 32 bits Offset from start of file to the next data chunk. This field is not typically used. This member is
present on all Data Chunk Header objects with an object_version of 0 (zero).

Data Packet Header The data section of a RealMedia file consists of a series of interleaved data objects. Each data object
contains a packet of data for a media stream. Because a RealMedia file can contain numerous media streams, data objects
for each stream are interleaved. The following pseudo-structure describes the details of each interleaved packet:

Media_Packet_Header
{
UINT16 object_version;
if (object_version == 0)
{
UINT16 length;
UINT16 stream_number;
UINT32 timestamp;
UINT8 reserved;
UINT8 flags;
UINT8[length] data;
}
}

The Media Packet Header contains the following fields:
1. object_version: 16 bits The version of the Media Packet Header object.
2. length: 16 bits The length of the packet in bytes. This member is present on all Media Packet Header objects with an
object_version of 0 (zero).
3. stream_number: 16 bits The 16-bit alias used to associate data packets with their associated Media Properties Header.
this member is present on all Media Packet Header objects with an object_version of 0 (zero).
4. timeStamp: 32 bits The timestamp of the packet in milliseconds This member is present on all Media Packet Header objects
with an object_version of 0 (zero).
5. reserved: 8 bits This is not used. This member is present on all Media Packet Header objects with an object_version of 0 (zero).
6. flags: 16 bits Flags describing the properties of the packet. The following flags are defined:
#define PN_RELIABLE_FLAG 0x0001 If this flag is set, the packet is delivered reliably.
#define PN_KEYFRAME_FLAG 0x0002 If this flag is set, the packet is part of a key frame or in some way marks a boundary in
your data stream.this member is present on all Media Packet Header objects with an object_version of 0 (zero).
7. data: variable length The application-specific media data. This member is present on all Media Packet Header objects with
an object_version of 0 (zero).

Index Section The index section of the RealMedia file consists of a Index Chunk Header that describes the contents of the
index section, followed by a series of index records. Note that the size field of the Index Chunk Header is the size of the
entire index chunk, including the index records.

Index Section Header The Index Chunk Header marks the start of the index chunk. There is usually one index chunk per
stream in a RealMedia file. The following pseudo-structure describes the Index chunk header.

Index_Chunk_Header
{
u_int32 object_id;
u_int32 size;
u_int16 object_version;
if (object_version == 0)
{
u_int32 num_indices;
u_int16 stream_number;
u_int32 next_index_header;
}
}

The Index Chunk Header contains the following fields:
1. object_id: 32 bits The unique object ID for the Index Chunk Header ('INDX').
2. size: 32 bits The size of the Index Chunk in bytes.
3. object_version: 16 bits The version of the Index Chunk Header object.
4. num_indices: 32 bits Number of index records in the index chunk. This member is present on all Index Chunk Header
objects with an object_version of 0 (zero).
5. stream_number: 16 bits The stream number for which the index records in this index chunk are associated. This member
is present on all Index Chunk Header objects with an object_version of 0 (zero).
6. next_index_header: 32 bits Offset from start of file to the next index chunk. This field lets RealMedia file format readers
find all the index chunks quickly. This member is present on all Index Chunk Header objects with an object_version of 0 (zero).

Index Record The index section of a RealMedia file consists of a series of index record objects. Each index record contains
information for quickly finding a packet of a particular time stamp for a media stream. The following pseudo-structure describes
the details of each index record:

IndexRecord
{
UINT16 object_version;
if (object_version == 0)
{
u_int32 timestamp;
u_int32 offset;
u_int32 packet_count_for_this_packet;
}
}

An Index Record contains the following fields:
1. object_version: 16 bits The version of the Index Record object.
2. timestamp: 32 bits The timestamp in milliseconds associated with this record. This member is present on all Index Record
objects with an object_version of 0 (zero).
3. offset: 32 bits The offset from the start of the file at which this packet can be found. This member is present on all Index
Record objects with an object_version of 0 (zero).
4. packet_count_for_this_packet: 32 bits The packet number of the packet for this record. This is the same number of packets
that would have been seen had the file been played from the beginning to this point. This member is present on all Index
Record objects with an object_version of 0 (zero).

2007年11月27日星期二

arm realview 2.2 注册方法及license

arm realview 2.2 注册方法及license
作者:佚名 文章来源:www.mcu123.net

点击数: 更新时间:2006-8-26
下载带有 Google 工具栏的 Firefox

经验转载:

arm realview 2.2下载试了一下。但是我发现使用不了,好多人也提出了疑问。今天

刚弄完已经正常使用。让我浪费了好多时间让我很愤怒。

我不清楚上传这个东西的人是出于什么目的?为什么要修改说明里的东西,以至于下载了朋友空欢喜呢

既然做就做彻底,要不就不要拿出来共享。潜水也有忍不了的时候,论坛质量很差。

操作方法

1)用generate产生license file (注意自己的系统时间 最好是真实的当前时间,如果时间比较旧的话,产生的license file 将不能注册。license file 和系统时间、网卡物理地址、硬盘的序列号有关)
2)安装软件
3)license Wizard 选 Install Wizard ... 选择license file 目录
4)应用补丁注入工具Patch.exe给下边列出的文件注入校验和。文件目录见下边。 从这个论坛下载说明少了4个文件路径,导致的结果就是无法启动调试部分。

关于 no license check out 以上作完了就加载一个*.axf文件实验吧,看看还有没有no license check out ,这时你在看软件注册信息 Enjoy ;-)

Install, apply our patch then generate license file with the keygen.
-------------
the files need to be patched:

%Install Path%\IDEs\CodeWarrior\CodeWarrior\5.6.1\1592\win_32-pentium\bin\Plugins\License\oemlicense.dll
%Install Path%\IDEs\CodeWarrior\RVPlugins\1.0\86\win_32-pentium\oemlicense\oemlicense.dll
%Install Path%\RDI\armsd\1.3.1\66\win_32-pentium\armsd.exe
%Install Path%\RDI\AXD\1.3.1\98\win_32-pentium\axd.exe
%Install Path%\RVCT\Programs\2.2\349\win_32-pentium\armasm.exe
%Install Path%\RVCT\Programs\2.2\349\win_32-pentium\armcc.exe
%Install Path%\RVCT\Programs\2.2\349\win_32-pentium\armcpp.exe
%Install Path%\RVCT\Programs\2.2\349\win_32-pentium\armlink.exe
%Install Path%\RVCT\Programs\2.2\349\win_32-pentium\fromelf.exe
%Install Path%\RVCT\Programs\2.2\349\win_32-pentium\tcc.exe
%Install Path%\RVCT\Programs\2.2\349\win_32-pentium\tcpp.exe
%Install Path%\RVD\Core\1.8\734\win_32-pentium\bin\tvs.exe
%Install Path%\RVD\Core\1.8\734\win_32-pentium\bin\xry100.dll

这几个为后添加的 原说明里没有所以无法调试
%Install Path%\RVARMulator\ARMulator\1.4.1\206\win_32-pentium\armiss.sdi
%Install Path%\RVARMulator\ARMulator\1.4.1\206\win_32-pentium\armulate.sdi
%Install Path%\RVARMulator\ARMulator\1.4.1\206\win_32-pentium\v6armiss.sdi
%Install Path%\RVARMulator\v6ARMulator\1.4.1\238\win_32-pentium\v6thumb2.sdi
%Install Path%\RVARMulator\v6ARMulator\1.4.1\238\win_32-pentium\v6trustzone.sdi

2007年11月18日星期日

Midi文件解码器(8052)

Midi文件解码器(8052)

下面的程序是可以播放midi音乐的。并且有3个灯用来和音乐中的小节同步(三个等依次为 强,次强,弱)。该程序只对单轨音乐进行解码。从开始做到调通灯光,我花了1周的时间。

希望有用的到的朋友。

 

#i nclude "reg52.h"
/**********************************************************************
     Name:  Midi_Player
     Version: 1.0
     hardware: 8052
     Author:  jiangkeqiang
     Email:  brave_man.student#sina.com.cn
     comment: hoping you can benifit from these code
/*********************************************************************/
#define BUFFER_LEN 528

void send_data(unsigned char *dat,unsigned int len);
unsigned long read4byte();
unsigned short read2byte();
unsigned char read1byte();
unsigned int get_wait_time(unsigned long wait);
unsigned char do_event();
unsigned long GetVLE ();
void led_blink();
unsigned long get_different(unsigned long begin,unsigned long end);
void loadsongtobuffer();


unsigned char code song[] =//this is a midi file
{
0x4d,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x00,
0x00,0x01,0x00,0x78,0x4d,0x54,0x72,0x6b,0x00,0x00,
0x3a,0x71,0x00,0xff,0x58,0x04,0x01,0x02,0x18,0x08,
0x00,0xff,0x59,0x02,0x00,0x00,0x00,0xff,0x51,0x03,
0x03,0xa9,0x80,0x00,0xc0,0x49,0x00,0xb0,0x07,0x7f,
0x00,0xc1,0x21,0x00,0xb1,0x07,0x54,0x00,0xc2,0x00,
0x00,0xb2,0x07,0x5f,0x00,0xc3,0x2e,0x00,0xb3,0x07,
0x5b,0x00,0x0a,0x62,0x00,0xc4,0x19,0x00,0xb4,0x07,
0x64,0x00,0x0a,0x34,0x00,0xc5,0x68,0x00,0xb5,0x07
};//由于减少没用信息,这里的内容不足一首歌曲。使用时

//只需要把这里替换成你想换的歌曲

//unsigned long idata time_wait=0xffff;
unsigned long idata  overflow_count=0;

unsigned short idata tempo;
//unsigned long idata  byte_of_track;
unsigned char idata  com_data[4];
unsigned char idata  last_command;
unsigned char idata  paizi=4;
unsigned char idata  jie_len;
unsigned char idata  ledsqu[6];
unsigned char idata  ledindex;

unsigned char xdata song_buffer[BUFFER_LEN];
unsigned char xdata * idata ptr=song_buffer;

unsigned short idata counter=0;
//unsigned long led_count=0;
bit next_is_begin = 0;
bit load = 1;

//0---2/4
//1---3/4
//2---4/4
//3---6/8
unsigned short base_count=0;//1/4音符需要的overflow_count数

void timer1_ISR (void) interrupt 3
{
//中断一次经历1/1800秒
 TF1 = 0;            /* Clear the interrupt request */
 TH1 = 0xFB;
 TL1 = 0x73;
 overflow_count++;
// led_count++;
}
void close_led()
{
 P1 = 0xFF;
}

void led_blink()
{
//2/4拍是"强、弱";
//3/4拍是"强、弱、弱";
//4/4拍是"强、弱、次强、弱",
//8/6拍是"强、弱、弱、次强、弱、弱",
 unsigned char max;
 
 max = paizi;
 
 if(paizi == 5)
 {
  max = 3;//3/8拍
 }
 
 if(max == 0)//程序不认识该节拍
 {
  //关灯
  P1 = 0xFF;
  return;
 }
 

 if(ledindex >= max)
  ledindex =0 ;
  
 if(ledsqu[ledindex] == 0)
 {
  P1 = 0xFB;
 }
 else if(ledsqu[ledindex] == 1)
 {
  P1 = 0xEF;
 }
 else if(ledsqu[ledindex] == 2)
 {
  P1 = 0xBF; 
 }
 
 ledindex ++;
}

void ChangeSpeed (unsigned long mydata)
{
 base_count = mydata*1800/1000000;
}

unsigned int get_wait_time(unsigned long wait)
{
 if(wait == 0)
  return 0; 
 else
  return 1.00*base_count*wait/tempo;
}


void com_init()
{
 //8位UART.可变波特率
 SCON |= 0x40;
 
 //使用Timer2
 TCLK = 1;
 
 //24M focs,31250Hz 
 RCAP2H = 0xFF;
 RCAP2L = 0xE8;
 
 //run timer2
 TR2 = 1;
}
void timer1_init()
{
 TH1 = 0x00;
 TL1 = 0x00;
 
 TMOD |= 0x10;
 
 //enable timer1 interrupts
 ET1 = 1;
 //globle interrupts enable
 EA = 1;
 
 //run timer1
 TR1 = 1;
}

void send_char(unsigned char c)
{

 SBUF = c;
 
 while(!TI);
 
 TI=0;

}

void send_data(unsigned char *dat,unsigned int len)
{
 unsigned int i;
 for(i=0;i<len;i++)
  send_char(dat[i]);
}
/*
unsigned long get_different(unsigned long begin,unsigned long end)
{
 if(end>=begin)
  return (end-begin);
 else
  return (0xFFFFFFFF-begin+end);
}
*/
unsigned long get_end(unsigned long begin,unsigned long wait)
{
 unsigned long end;
 
 end = begin + wait;
 
 return end;
}

void begin_play()
{
 unsigned long begin1=0;
 unsigned long begin2=0;
 unsigned long wait1;
 unsigned long wait2;
 unsigned long end1;
 unsigned long end2;
 unsigned char flag=0;
 unsigned char thing_index=0x00;
 unsigned short idata jie_click; 

 //默认是4/4拍
  paizi = 4;
 ledsqu[0] =0;
  ledsqu[1] =2;       
  ledsqu[2] =1;      
  ledsqu[3] =2;
 ledindex = 0;
 //亮红灯。

 //给base_count附上初值,假设每拍0.5s
 ChangeSpeed (1000000*60/tempo);
 jie_click = 4*tempo;
 jie_len = 4;
 
 wait1 = GetVLE();
 counter += wait1;
 wait1 = get_wait_time(wait1);
 end1 = get_end(begin1,wait1);

 wait2 = get_wait_time(tempo/2);
 end2 = get_end(begin2,wait2);
 


 while(1)
 {
  while(1)
  {
   if(end1 <= overflow_count )
   {
    thing_index |= 1;    
    begin1 = end1;
   }
   if(end2 <= overflow_count)
   {
    thing_index |= 2;
    flag = !flag;
    begin2 = end2;
   }  

   if(thing_index)
    break;   
       
  }


  if(thing_index&0x01)
  { 

   next_is_begin = 0;
   if( do_event() ==0)
   {
    close_led();
    break;
   }
  
   wait1 = GetVLE();   
   if(counter % (tempo*jie_len) == 0)
   {
    counter = 0;
    ledindex = 0;
    led_blink();
    flag = 0;
   
    begin2 = begin1;
    wait2 = get_wait_time(tempo/2);
    end2 = get_end(begin2,wait2); 
    
    thing_index = 0x01;//不再进行亮灯程序
   }
    
   counter += wait1;
   if(next_is_begin == 1)
   {
    counter = 0;
    ledindex = 0;
    led_blink();   
   }

   
   wait1 = get_wait_time(wait1);
   end1 = get_end(begin1,wait1);   
  }      
  if(thing_index&0x02)
  {
   if(flag == 0)
    led_blink();
   else
    close_led();
   wait2 = get_wait_time(tempo/2);
   end2 = get_end(begin2,wait2);    
  }  
  thing_index = 0;
 }
}

unsigned char do_event()
{
 unsigned char MIDIByte,MetaEvent,MIDICommand,MIDIChannel;
 unsigned long DataLength,Counter1;
 unsigned long mydata;
 unsigned char n1,n2;
 
 
 MIDIByte = read1byte();
 if((MIDIByte & 0x80) == 0x00)
 {
  MIDIByte = last_command;
  ptr--;
  load = 0;
 }
 else
 {
  last_command = MIDIByte;
 }
 
 if (MIDIByte == 0xFF)
 {
     MetaEvent  = read1byte();
     DataLength = GetVLE();
     if (MetaEvent == 0x2F) //End of track}
      return 0;
     else if (MetaEvent == 0x51)
     { //Tempo change
       mydata = read1byte();
       mydata = (mydata << 8) + read1byte();
       mydata = (mydata << 8) + read1byte();
      
       ChangeSpeed (mydata);
     }
     else if(MetaEvent == 0x58)
     {
      n1 = read1byte();
      n2 = read1byte();
      mydata = read1byte();
      mydata = read1byte();
      
      if(n1 == 6 && n2 ==3)//6/8拍
      {
       jie_len = 6;     
       paizi = 6;
       ledsqu[0] =0;
       ledsqu[1] =2;       
       ledsqu[2] =2;      
       ledsqu[3] =1;
       ledsqu[4] =2;       
       ledsqu[5] =2;             
      }
      else if(n1 == 3 && n2 ==3)//3/8拍
      {
       jie_len = 3;          
       paizi = 5;
       ledsqu[0] =0;
       ledsqu[1] =2;       
       ledsqu[2] =2;      
      }      
      else if(n1 == 4 && n2 == 2)//4/4拍
      {
       jie_len = 4;         
       paizi = 4;
       ledsqu[0] =0;
       ledsqu[1] =2;       
       ledsqu[2] =1;      
       ledsqu[3] =2;       
      }
      else if(n1 ==3 && n2 == 2)//3/4拍
      {
       jie_len = 3;           
       paizi = 3;
       ledsqu[0] =0;
       ledsqu[1] =2;       
       ledsqu[2] =2;      
      }
      else if( (n1 == 2 && n2 == 2) || (n1 == 2 && n2 == 1) )//2/4拍,2/2拍
      {
       jie_len = 2;      
       paizi = 2;
       ledsqu[0] =0;
       ledsqu[1] =2;       
      }
      else if(n1 == 1 && n2 == 2)//1/4拍
      {
       jie_len = 1;           
       paizi = 1;
       ledsqu[0] =0;
      }
      else
      {
       paizi = 0;
      }
      ledindex = 0;
      counter = 0;
      next_is_begin = 1;//下下一个event开始计拍
     }
     else
     {
        //Others (text events, track sequence numbers etc. - ignore
        for (Counter1 = 1; Counter1 <= DataLength; Counter1++)
          read1byte();
     }    
 }
 
   /*
     CHANNEL COMMANDS
     ================
     Upper nibble contains command, lower contains channel
   */
   MIDIChannel = MIDIByte & 0xF;
 MIDICommand = MIDIByte >> 4;
 if (MIDICommand == 8 || MIDICommand == 9 || MIDICommand == 0x0a)
 { //Note off
  n1 = read1byte();
      n2 = read1byte();
      /*This allows the use of a wavetable General MIDI instrument (such
      as the Roland SCC1 (or an emulation thereof) or the FM synthesizer*/
      if(n2 > 127)
       n2 = 127;
  com_data[0] = MIDIByte;
  com_data[1] = n1;
  com_data[2] = n2;
  send_data(com_data,3);
     }
 if(MIDICommand == 0x0b || MIDICommand == 0x0e)     
 {
  n1 = read1byte();
      n2 = read1byte();
      /*This allows the use of a wavetable General MIDI instrument (such
      as the Roland SCC1 (or an emulation thereof) or the FM synthesizer*/
     
  com_data[0] = MIDIByte;
  com_data[1] = n1;
  com_data[2] = n2;
  send_data(com_data,3); 
 }
  if(MIDICommand == 0x0c || MIDICommand == 0x0d)
  {
   n1 = read1byte();
   com_data[0] = MIDIByte;
   com_data[1] = n1;
   send_data(com_data,2); 
  }
  /*
    SYSTEM COMMANDS
    ===============
    These are ignored.
  */
 if (MIDICommand == 0xF)
 {
      if (MIDIChannel == 0)
      {
   DataLength = GetVLE();      
         for (Counter1 = 1; Counter1 <= DataLength; Counter1++)
           read1byte();
      }
      if (MIDIChannel == 2) {read2byte();} //Song Position Pointer
      if (MIDIChannel == 3) { read1byte(); } // Song Select
   }
 
 return 1;
}

int read_track_header()
{
//0x4d,0x54,0x72,0x6b,0x00,0x00,
//0x00,0xa4,0x00,0xff,0x03,0x08,0x75,0x6e,0x74,0x69,
//0x74,0x6c,0x65,0x64,0x00,0xff,0x58,0x04,0x04,0x02,
 unsigned long x;

 x = read4byte();
 if(x != 0x4d54726b)
  return 0;
 read4byte();
}


int read_midi_header()
{
//0x4d,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x00,
//0x00,0x01,0x00,0x78, 
 unsigned long x;
 unsigned short y;
 
 x = read4byte();
 if(x != 0x4d546864)
  return 0;
  
 x = read4byte();
 if(x != 0x00000006)
  return 0;
   
 //format
 y = read2byte();
 if(y != 0x00)
  return 0;
 
 //number of tracks  
 y = read2byte();
 if(y != 0x01)
  return 0;
 tempo = read2byte();
  
 return 1;
}
unsigned char read1byte()
{
 unsigned char ret;
 
 if( (ptr-song_buffer) % BUFFER_LEN ==0) && load==1 )
 {
  loadsongtobuffer();
  ptr = song_buffer;
 }
 
 ret = *ptr++;
 load = 1;
 return ret;
}
unsigned short read2byte()
{
 unsigned short ret;
 ret = read1byte();
 ret = ret << 8;
 ret |= read1byte();
 
 return ret;
}
unsigned long read4byte()
{
 unsigned long ret;
 ret = read1byte();
 ret = ret<<8;
 
 ret |= read1byte();
 ret = ret<<8;
 
 ret |= read1byte();
 ret = ret<<8;
 
 ret |= read1byte();
 
 return ret; 
}
unsigned long GetVLE ()
{
  unsigned char ByteRead;
  long Result;

  //Assume zero
  Result = 0;
  do {
    //Read first byte
    ByteRead = read1byte();
    //Store 7bit part
    Result = (Result << 7) + (ByteRead & 0x7F);
  } while ((ByteRead & 0x80) != 0);
  return Result;

static unsigned char *song_ptr=song;//改变量为了调试.
void loadsongtobuffer()
{
 int i;
 for(i=0;i<BUFFER_LEN;i++)
 {
  song_buffer[i] = *song_ptr++;
 }
 
}


main()
{
 com_init();
 timer1_init();
 

 if(read_midi_header() == 0)
  goto end;
 
 if(read_track_header() == 0)
  goto end;
  
 begin_play();
end: 
 for(;;);
}

2007年11月15日星期四

FW: [嘻嘻哈哈] 标准MIDI文件格式

标准MIDI文件格式  
  达思挺・考德威尔  
   
   
  标准的MIDI文件格式就像奇异的兽。总体看来,它是那样的让你无法抗拒。当然,你怎样看它无关紧要,可是用足够多的描述符描述一段音乐并使它能够重现,可不是很少的工作就可以完成的。然而,它虽然复杂,但是真正理解之后,MIDI文件格式的结构还是很直观明了的。  
   
  在这里我必须放弃一些东西,因为毕竟我不是MIDI也不是MIDI文件专家!最近我为我的PC准备了一块Gravis   超音频音效卡,利用它听完几段MIDI文件(.mid)之后,想:"呵,我要是能够制作自己的MIDI(.mid)文件该多好啊!"嗯,经过烦人的几个小时之后,我发现,那些并不是没有价值的工作。但是,我是不会让一个冗长的文件格式就能够阻止的(此外,我告诉过我的妻子,计算机不是很难用的,而且我十分憎恨当一个伪君子)。那么,在这篇文章中如果发现什么错误,请让我知道,我会修改它的。同时,这份文档的范围并没有提供所有类型的MIDI命令和任何可能的文件配置!这篇基本指南将使读者能够(以中等的时间投资)制作出MIDI类型的文件。  
   
  1.概述:  
   
  一个MIDI文件基本上由两个部分组成,头块和轨道块。第二节讲述头块,第三节讲述轨道块。一个MIDI文件有一个头块用来描述文件的格式、许多的轨道块等内容。一个轨道可以想象为像一个大型多音轨录音机那样,你可以为某种声音、某种乐谱、某种乐器或者你需要的任何东西分配一个轨道。  
   
  2.头块:  
   
  头块出现在文件的开头,有三种方式来描述文件。头块看起来一直是这样的:  
  4D   54   68   64   00   00   00   06   ff   ff   nn   nn   dd   dd  
   
  前4个字节等同于ASCII码MThd,接着MThd之后的4个字节是头的大小。它将一直是00   00   00   00   06,因为现行的头信息将一直是6字节。  
   
  ff   ff是文件的格式,有3种格式:  
  0-单轨  
  1-多规,同步  
  2-多规,异步  
   
  单轨,很显然就只有一个轨道。同步多轨意味着所有轨道都是垂直同步的,或者其他的措辞为他们都在同一时间开始,并且可以表现一首歌的不同部分。异步多轨没有必要同时开始,而且可以完全的不同步。  
   
  nn   nn   是MIDI文件中的轨道数。  
  dd   dd   是每个4分音符delta-time节奏数(这之后将做详细介绍)。  
   
  3.轨道块:  
   
  头块之后剩下的文件部分是轨道块。每一个轨道包含一个头,并且可以包含你所希望的许多MIDI命令。轨道头与文件头及其相似:  
   
  4D   54   72   6B   xx   xx   xx   xx  
   
  与头一致,前4个字节是ASCII吗,这个是MTrk,紧跟MTrk的4个字节给出了以字节为单位的轨道的长度(不包括轨道头)。  
   
  在头之下是MIDI事件,这些事件同现行的可以被带有累加的MIDI合成器端口接受和发送的数据是相同的。一个MIDI   事件先于一个delta-time。一个delta-time是一个MIDI事件被执行后的节奏数,每个四分之一音符的节奏数先前已经定义在了文件的头块中。这个delta-time是一个可变长度的编码值。这种格式虽然混乱,可是允许根据需要利用多位表示较大的数值,这不会因为需求小的数值情况下以添零的方式浪费掉一些字节!数值被转换为7位的字节,并且除了最后一个字节以最高有效位是0外,各个字节最有意义的一位是1,。这就允许一个数值被一次一个字节地读取,你如果发现最高有效位是0,则这就是这个数值的最后一位(意义比较小)。依照MIDI说明,全部delta-time的长度最多超过4字节。  
   
  delta-time   之后就是MIDI事件,每个MIDI事件(除了正在运行的事件外)带有一个最高有效位总是1的命令字节(值将>128)。大部分命令的列表在附录A 中。每个命令都有不同的参数和长度,但是接下来的数据将是最高有效位为零(值将<128)。这里有个例外就是meta-event,最高有效位可以是1。然而,meta-events需要一个长的参数以区分。  
   
  微小失误就可以导致混乱的是运行模式,这是现行MIDI命令所忽略的地方,并且最终发行的MIDI命令是假定的。这就意味这如果包含了命令,那么MIDI事件就是由delta-time与参数组成而转换的。  
   
  4.综述:  
   
  如果这份说明仅仅是使问题更加混乱,那么以下提供的例子可能有助于澄清问题!同时,两个公用程序和一个图解文件包含在这个文档里面:  
   
  DEC.EXE――这个公共程序是将二进制文件(比如.MID)转换成以十进制表示的对应每个字节的有标记界限的文本文件。  
   
  REC.EXE――这个公共程序是将有标记界限的十进制数文本文件对应的每一字节转换成二进制文件。  
   
  MIDINOTE.PS――这是一个对应键盘和五线谱的音符数字附录页。  
  附录A  
   
  1.MIDI事件命令  
   
  每个命令字节有两部分,左nybble(4位)包含现行的命令,右nybble包含将被执行的命令的通道号,这里有16各MIDI通道8个MIDI命令(命令nybble必须最高有效位是1的)。在下表中,X表示MIDI通道号。所有的音符即数据字节都<128(最高有效位是0)。  
   
  十六进制 二进制 数据 描述  
   
  8x             1000xxxx         nn   vv                 音符关闭   (释放键盘)  
                                                                          nn=音符号  
                                                                          vv=速度  
   
  9x             1001xxxx         nn   vv                 音符打开   (按下键盘)  
                                                                          nn=音符号  
                                                                          vv=速度  
   
  Ax             1010xxxx         nn   vv                 触摸键盘以后  
                                                                          nn=音符号  
                                                                          vv=速度  
   
  Bx             1011xxxx         cc   vv                 调换控制  
                                                                          cc=控制号  
                                                                          vv=新值  
   
  Cx             1100xxxx         pp                         改变程序(片断)  
                                                                          pp=新的程序号  
   
  Dx             1101xxxx         cc                         在通道后接触  
  cc=管道号  
   
  Ex             1110xxxx         bb   tt                 改变互相咬和的齿轮   (2000H   表明缺省或没有改变)(什么意思搞不懂:)  
                                                                          bb=值的低7位(least   sig)    
                                                                          tt=值的高7位   (most   sig)    
   
  下表是没有通道的   meta-events列表   ,他们的格式是:  
   
  FF   xx   nn   dd  
   
  所有的   meta-events   是以   FF   开头的命令   (xx),长度,或者含在数据的字节数(nn),现行的数据(dd)  
   
  十六进制 二进制 数据 描述  
  00             00000000         nn   ssss             设定轨道的序号  
                                                                          nn=02   (两字节长度的序号)  
                                                                          ssss=序号  
   
  01             00000001         nn   tt   ..             你需要的所有文本事件  
                                                                          nn=以字节为单位的文本长度  
                                                                          tt=文本字符  
   
  02             00000010         nn   tt   ..             同文本的事件,   但是用于版权信息  
                                                                          nn   tt=同文本事件  
   
  03             00000011       nn   tt   ..             序列或者轨道名  
                                                                          nn   tt=同文本事件  
   
  04             00000100         nn   tt   ..             轨道乐器名  
                                                                          nn   tt=同文本事件  
   
  05             00000101         nn   tt   ..             歌词  
                                                          nn   tt=同文本事件  
   
  06             00000110         nn   tt   ..             标签  
                                                                          nn   tt=同文本事件  
   
  07             00000111         nn   tt   ..             浮点音符  
                                                                          nn   tt=同文本事件  
   
  2F             00101111         00                         这个事件一定在每个轨道的结尾出现  
   
  51             01010001         03   tttttt         设定拍子  
                                                                          tttttt=微秒/四分音符  
   
  58             01011000         04   nn   dd   cc   bb   拍子记号  
                                                                          nn=拍子记号分子  
                                                                          dd=拍子记号分母2=四分之一  
                                                                          3=8分拍,   等等.  
                                                                          cc=节拍器的节奏  
                                                                          bb=对四分之一音符标注的第32号数字  
   
  59             01011001         02   sf   mi             音调符号  
                                                                          sf=升调/降调(-7=7   降调,   0=基准C调,7=7   升调)  
                                                                          mi=大调/小调(0=大调,   1=小调)  
   
  7F             01111111         xx   dd   ..             音序器的详细信息  
                                                                          xx=被发送的字节数  
                                                                          dd=数据  
     
  下表列出了控制整个系统的系统消息。这里没有MIDI通道数   (这些一般仅应用于MIDI键盘等.)  
   
  十六进制             二进制       数据                     描述  
   
  F8             11111000                                     同步所必须的计时器  
  FA             11111010                                     开始当前的队列  
  FB             11111011                                     从停止的地方继续一个队列  
  FC             11111100                                     停止一个队列  
   
  下表列出的是与音符相对应的命令标记。  
  八度音阶||                                         音符号  
      #     ||  
              ||   C     |   C#     |   D     |   D#     |   E     |   F     |   F#     |   G     |   G#     |   A     |   A#     |   B  
  -----------------------------------------------------------------------------  
      0     ||     0   |     1   |     2   |     3   |     4   |     5   |     6   |     7   |     8   |     9   |     10   |   11  
      1     ||     12   |     13   |     14   |     15   |     16   |     17   |     18   |     19   |     20   |     21   |     22   |   23  
      2     ||     24   |     25   |     26   |     27   |     28   |     29   |     30   |     31   |     32   |     33   |     34   |   35  
      3     ||     36   |     37   |     38   |     39   |     40   |     41   |     42   |     43   |     44   |     45   |     46   |   47  
      4     ||     48   |     49   |     50   |     51   |     52   |     53   |     54   |     55   |     56   |     57   |     58   |   59  
      5     ||     60   |     61   |     62   |     63   |     64   |     65   |     66   |     67   |     68   |     69   |     70   |   71  
      6     ||     72   |     73   |     74   |     75   |     76   |     77   |     78   |     79   |     80   |     81   |     82   |   83  
      7     ||     84   |     85   |     86   |     87   |     88   |     89   |     90   |     91   |     92   |     93   |     94   |   95  
      8     ||     96   |     97   |     98   |     99   |   100   |   101   |   102   |   103   |   104   |   105   |   106   |   107  
      9     ||   108   |   109   |   110   |   111   |   112   |   113   |   114   |   115   |   116   |   117   |   118   |   119  
      10     ||   120   |   121   |   122   |   123   |   124   |   125   |   126   |   127   |  
   
  参考资料:  
  "MIDI   Systems   and   Control"   Francis   Rumsey     1990   Focal   Press  
  "MIDI   and   Sound   Book   for   the   Atari   ST"   Bernd   Enders   and   Wolfgang   Klem   1989   M&T   Publishing,   Inc.  
  MIDI   file   specs   and   general   MIDI   specs   were   also   obtained   by   sending   e-mail   to   LISTSERV@AUVM.AMERICAN.EDU   with   the   phrase   GET   MIDISPEC   PACKAGE   in   the   message.  


--
由 Pegasus 于 11/12/2007 11:26:00 下午 在 嘻嘻哈哈 上发表

2007年11月13日星期二

C++编译中经常遇到的错误

C++编译中经常遇到的错误
 
 
1、fatal error C1010: unexpected end of
file while looking for precompiled header directive。
 

寻找预编译头文件路径时遇到了不该遇到的文件尾。(一般是没有#include
"stdafx.h")
 
2、fatal error C1083: Cannot open
include file: 'R…….h': No such file or directory
 

不能打开包含文件"R…….h":没有这样的文件或目录。
 
3、error C2011: 'C……': 'class' type
redefinition
 
类"C……"重定义。
 
4、error C2018: unknown character
'0xa3'
 

不认识的字符'0xa3'。(一般是汉字或中文标点符号)
 
5、error C2057: expected constant
expression
 

希望是常量表达式。(一般出现在switch语句的case分支中)
 
6、error C2065: 'IDD_MYDIALOG' :
undeclared identifier
 

"IDD_MYDIALOG":未声明过的标识符。
 
7、error C2082: redefinition of formal
parameter 'bReset'
 

函数参数"bReset"在函数体中重定义。
 
8、error C2143: syntax error: missing
':' before '{'
 
句法错误:"{"前缺少";"。
 
9、error C2146: syntax error : missing
';' before identifier 'dc'
 
句法错误:在"dc"前丢了";"。
 
10、error C2196: case value '69'
already used
 

值69已经用过。(一般出现在switch语句的case分支中)
 
11、error C2509: 'OnTimer' : member
function not declared in 'CHelloView'
 

成员函数"OnTimer"没有在"CHelloView"中声明。
 
12、error C2511: 'reset': overloaded
member function 'void (int)' not found in 'B'
 
重载的函数"void
reset(int)"在类"B"中找不到。
 
13、error C2555: 'B::f1': overriding
virtual function differs from 'A::f1' only by return type or
calling convention
 

类B对类A中同名函数f1的重载仅根据返回值或调用约定上的区别。
 
14、error C2660: 'SetTimer' : function
does not take 2 parameters
 
"SetTimer"函数不传递2个参数。
 
15、warning C4035: 'f……': no return
value
 
"f……"的return语句没有返回值。
 
16、warning C4553: '= =' : operator has
no effect; did you intend '='?
 
没有效果的运算符"=
=";是否改为"="?
 
17、warning C4700: local variable
'bReset' used without having been initialized
 

局部变量"bReset"没有初始化就使用。
 
18、error C4716: 'CMyApp::InitInstance'
: must return a value
 

"CMyApp::InitInstance"函数必须返回一个值。
 
19、LINK : fatal error LNK1168: cannot
open Debug/P1.exe for writing
 

连接错误:不能打开P1.exe文件,以改写内容。(一般是P1.Exe还在运行,未关闭)
 
20、error LNK2001: unresolved external
symbol "public: virtual _ _thiscall C……::~C……(void)"
 

连接时发现没有实现的外部符号(变量、函数等)。
 
Best Regards
Miao Jia Hong
 

MIDI编曲

MIDI编曲
低阶MIDI的API包括字首为midiIn和midiOut的函式,它们分别用於读取来自外部控制器的MIDI序列和在内部或外部的合成器上播放音乐。尽管其名称为「低阶」,但使用这些函式时并不需要了解MIDI卡上的硬体介面。

要在播放音乐的准备期间打开一个MIDI输出设备,可以呼叫midiOutOpen函式:

error = midiOutOpen (&hMidiOut, wDeviceID, dwCallBack,
                             dwCallBackData, dwFlags) ;
如果呼叫成功,则函式传回0,否则传回错误代码。如果参数设定正确,则常见的一种错误就是MIDI设备已被其他程式使用。

该函式的第一个参数是指向HMIDIOUT型态变数的指标,它接收後面用於MIDI输出函式的MIDI输出代号。第二个参数是设备ID。要使用真实的 MIDI设备,这个参数范围可以是从0到小於由midiOutGetNumDevs传回的数值。您还可以使用MIDIMAPPER,它在 MMSYSTEM.H中定义为-1。大多数情况下,函式的後三个参数设定为NULL或0。

一旦打开一个MIDI输出设备并获得了其代号,您就可以向该设备发送MIDI讯息。此时可以呼叫:

error = midiOutShortMsg (hMidiOut, dwMessage) ;
第一个参数是从midiOutOpen函式获得的代号。第二个参数是包装在32位元DWORD中的1位元组、2位元组或者3位元组的讯息。我在前面讨论过,MIDI讯息以状态位元组开始,後面是0、1或2位元组的资料。在dwMessage中,状态位元组是最不重要的,第一个资料位元组次之,第二个资料位元组再次之,最重要的位元组是0。

例如,要在MIDI通道5上以0x7F的速度演奏中音C(音符是0x3C),则需要3位元组的Note On讯息:

0x95 0x3C 0x7F
midiOutShortMsg的参数dwMessage等于0x007F3C95。

三个基础的MIDI讯息是Program Change(可为某一特定通道而改变乐器声音)、Note On和Note Off。打开一个MIDI输出设备後,应该从一条Program Change讯息开始,然後发送相同数量的Note On和Note Off讯息。

当您一直演奏您想演奏的音乐时,您可以重置MIDI输出设备以确保关闭所有的音符:

midiOutReset (hMidiOut) ;
然後关闭设备:

midiOutClose (hMidiOut) ;
使用低阶的MIDI输出API时,midiOutOpen、midiOutShortMsg、midiOutReset和midiOutClose是您需要的四个基础函式。

现在让我们演奏一段音乐。BACHTOCC,如程式22-8所示,演奏了J. S. Bach著名的风琴演奏的D小调《Toccata and Fugue》中托卡塔部分的第一小节。

2007年11月11日星期日

Standard MIDI File Format


                                                        Standard   MIDI   File   Format  
                                                                  Dustin   Caldwell  
   
              The   standard   MIDI   file   format   is   a   very   strange   beast.   When   viewed   as   a  
    whole,   it   can   be   quite   overwhelming.   Of   course,   no   matter   how   you   look   at   it,  
  describing   a   piece   of   music   in   enough   detail   to   be   able   to   reproduce   it  
  accurately   is   no   small   task.   So,   while   complicated,   the   structure   of   the   midi  
  file   format   is   fairly   intuitive   when   understood.    
              I   must   insert   a   disclaimer   here   that   I   am   by   no   means   an   expert   with  
    midi   nor   midi   files.   I   recently   obtained   a   Gravis   UltraSound   board   for   my   PC,  
  and   upon   hearing   a   few   midi   files   (.MID)   thought,   "Gee,   I'd   like   to   be   able   to  
  make   my   own   .MID   files."   Well,   many   aggravating   hours   later,   I   discovered   that  
  this   was   no   trivial   task.   But,   I   couldn't   let   a   stupid   file   format   stop   me.  
  (besides,   I   once   told   my   wife   that   computers   aren't   really   that   hard   to   use,  
  and   I'd   hate   to   be   a   hypocrite)   So   if   any   errors   are   found   in   this  
  information,   please   let   me   know   and   I   will   fix   it.   Also,   this   document's   scope  
  does   not   extend   to   EVERY   type   of   midi   command   and   EVERY   possible   file  
  configuration.   It   is   a   basic   guide   that   should   enable   the   reader   (with   a  
  moderate   investment   in   time)   to   generate   a   quality   midi   file.  
   
  1.   Overview  
   
              A   midi   (.MID)   file   contains   basically   2   things,   Header   chunks   and   Track  
  chunks.   Section   2   explains   the   header   chunks,   and   Section   3   explains   the   track  
  chunks.   A   midi   file   contains   ONE   header   chunk   describing   the   file   format,  
  etc.,   and   any   number   of   track   chunks.   A   track   may   be   thought   of   in   the   same  
  way   as   a   track   on   a   multi-track   tape   deck.   You   may   assign   one   track   to   each  
  voice,   each   staff,   each   instrument   or   whatever   you   want.    
   
  2.   Header   Chunk  
   
              The   header   chunk   appears   at   the   beginning   of   the   file,   and   describes   the  
  file   in   three   ways.   The   header   chunk   always   looks   like:  
   
  4D   54   68   64   00   00   00   06   ff   ff   nn   nn   dd   dd  
   
  The   ascii   equivalent   of   the   first   4   bytes   is   MThd.   After   MThd   comes   the   4-byte  
  size   of   the   header.   This   will   always   be   00   00   00   06,   because   the   actual   header  
  information   will   always   be   6   bytes.    
   
  ff   ff   is   the   file   format.   There   are   3   formats:  
   
  0   -   single-track    
  1   -   multiple   tracks,   synchronous  
  2   -   multiple   tracks,   asynchronous  
   
  Single   track   is   fairly   self-explanatory   -   one   track   only.   Synchronous   multiple  
  tracks   means   that   the   tracks   will   all   be   vertically   synchronous,   or   in   other  
  words,   they   all   start   at   the   same   time,   and   so   can   represent   different   parts  
  in   one   song.   Asynchronous   multiple   tracks   do   not   necessarily   start   at   the   same  
  time,   and   can   be   completely   asynchronous.    
   
  nn   nn   is   the   number   of   tracks   in   the   midi   file.  
   
  dd   dd   is   the   number   of   delta-time   ticks   per   quarter   note.   (More   about   this  
  later)  
   
   
  3.   Track   Chunks  
   
  The   remainder   of   the   file   after   the   header   chunk   consists   of   track   chunks.  
  Each   track   has   one   header   and   may   contain   as   many   midi   commands   as   you   like.  
  The   header   for   a   track   is   very   similar   to   the   one   for   the   file:  
   
  4D   54   72   6B   xx   xx   xx   xx  
   
  As   with   the   header,   the   first   4   bytes   has   an   ascii   equivalent.   This   one   is  
  MTrk.   The   4   bytes   after   MTrk   give   the   length   of   the   track   (not   including   the  
  track   header)   in   bytes.    
              Following   the   header   are   midi   events.   These   events   are   identical   to   the  
  actual   data   sent   and   received   by   MIDI   ports   on   a   synth   with   one   addition.   A  
  midi   event   is   preceded   by   a   delta-time.   A   delta   time   is   the   number   of   ticks  
  after   which   the   midi   event   is   to   be   executed.   The   number   of   ticks   per   quarter  
  note   was   defined   previously   in   the   file   header   chunk.   This   delta-time   is   a  
  variable-length   encoded   value.   This   format,   while   confusing,   allows   large  
  numbers   to   use   as   many   bytes   as   they   need,   without   requiring   small   numbers   to  
  waste   bytes   by   filling   with   zeros.   The   number   is   converted   into   7-bit   bytes,  
  and   the   most-significant   bit   of   each   byte   is   1   except   for   the   last   byte   of   the  
  number,   which   has   a   msb   of   0.   This   allows   the   number   to   be   read   one   byte   at   a  
  time,   and   when   you   see   a   msb   of   0,   you   know   that   it   was   the   last   (least  
  significant)   byte   of   the   number.   According   to   the   MIDI   spec,   the   entire   delta-  
  time   should   be   at   most   4   bytes   long.    
              Following   the   delta-time   is   a   midi   event.   Each   midi   event   (except   a  
  running   midi   event)   has   a   command   byte   which   will   always   have   a   msb   of   1   (the  
  value   will   be   >=   128).   A   list   of   most   of   these   commands   is   in   appendix   A.   Each  
  command   has   different   parameters   and   lengths,   but   the   data   that   follows   the  
  command   will   have   a   msb   of   0   (less   than   128).   The   exception   to   this   is   a   meta-  
  event,   which   may   contain   data   with   a   msb   of   1.   However,   meta-events   require   a  
  length   parameter   which   alleviates   confusion.    
              One   subtlety   which   can   cause   confusion   is   running   mode.   This   is   where  
  the   actual   midi   command   is   omitted,   and   the   last   midi   command   issued   is  
  assumed.   This   means   that   the   midi   event   will   consist   of   a   delta-time   and   the  
  parameters   that   would   go   to   the   command   if   it   were   included.    
   
  4.   Conclusion  
   
              If   this   explanation   has   only   served   to   confuse   the   issue   more,   the  
  appendices   contain   examples   which   may   help   clarify   the   issue.   Also,   2  
  utilities   and   a   graphic   file   should   have   been   included   with   this   document:    
   
  DEC.EXE   -   This   utility   converts   a   binary   file   (like   .MID)   to   a   tab-delimited  
  text   file   containing   the   decimal   equivalents   of   each   byte.  
   
  REC.EXE   -   This   utility   converts   a   tab-delimited   text   file   of   decimal   values  
  into   a   binary   file   in   which   each   byte   corresponds   to   one   of   the   decimal  
  values.  
   
  MIDINOTE.PS   -   This   is   the   postscript   form   of   a   page   showing   note   numbers   with  
  a   keyboard   and   with   the   standard   grand   staff.  
                                                                                                                                                    Appendix   A  
   
  1.   MIDI   Event   Commands  
   
  Each   command   byte   has   2   parts.   The   left   nybble   (4   bits)   contains   the   actual  
  command,   and   the   right   nybble   contains   the   midi   channel   number   on   which   the  
  command   will   be   executed.   There   are   16   midi   channels,   and   8   midi   commands   (the  
  command   nybble   must   have   a   msb   of   1).  
  In   the   following   table,   x   indicates   the   midi   channel   number.   Note   that   all  
  data   bytes   will   be   <128   (msb   set   to   0).  
   
  Hex             Binary               Data                     Description  
  8x               1000xxxx           nn   vv                   Note   off   (key   is   released)  
                                                                          nn=note   number  
                                                                          vv=velocity  
   
  9x               1001xxxx           nn   vv                   Note   on   (key   is   pressed)  
                                                                          nn=note   number  
                                                                          vv=velocity  
   
  Ax               1010xxxx           nn   vv                   Key   after-touch  
                                                                          nn=note   number  
                                                                          vv=velocity  
   
  Bx               1011xxxx           cc   vv                   Control   Change  
                                                                          cc=controller   number  
                                                                          vv=new   value  
   
  Cx               1100xxxx           pp                         Program   (patch)   change  
                                                                          pp=new   program   number  
   
  Dx               1101xxxx           cc                         Channel   after-touch  
                                                                          cc=channel   number  
   
  Ex               1110xxxx           bb   tt                   Pitch   wheel   change   (2000H   is   normal   or   no  
                                                                          change)  
                                                                          bb=bottom   (least   sig)   7   bits   of   value  
                                                                          tt=top   (most   sig)   7   bits   of   value  
  The   following   table   lists   meta-events   which   have   no   midi   channel   number.   They  
  are   of   the   format:  
   
  FF   xx   nn   dd  
   
  All   meta-events   start   with   FF   followed   by   the   command   (xx),   the   length,   or  
  number   of   bytes   that   will   contain   data   (nn),   and   the   actual   data   (dd).  
   
  Hex             Binary               Data                     Description  
  00               00000000           nn   ssss               Sets   the   track's   sequence   number.  
                                                                          nn=02   (length   of   2-byte   sequence   number)  
                                                                          ssss=sequence   number  
   
  01               00000001           nn   tt   ..             Text   event-   any   text   you   want.  
                                                                          nn=length   in   bytes   of   text  
                                                                          tt=text   characters  
   
  02               00000010           nn   tt   ..             Same   as   text   event,   but   used   for  
                                                                          copyright   info.  
                                                                          nn   tt=same   as   text   event  
   
  03               00000011           nn   tt   ..             Sequence   or   Track   name  
                                                                          nn   tt=same   as   text   event  
   
  04               00000100           nn   tt   ..             Track   instrument   name  
                                                                          nn   tt=same   as   text   event  
   
  05               00000101           nn   tt   ..             Lyric  
                                                                          nn   tt=same   as   text   event  
   
  06               00000110           nn   tt   ..             Marker  
                                                                          nn   tt=same   as   text   event  
   
  07               00000111           nn   tt   ..             Cue   point  
                                                                          nn   tt=same   as   text   event  
   
  2F               00101111           00                         This   event   must   come   at   the   end   of   each  
                                                                          track  
   
  51               01010001           03   tttttt           Set   tempo  
                                                                          tttttt=microseconds/quarter   note  
   
  58               01011000           04   nn   dd   ccbb   Time   Signature  
                                                                          nn=numerator   of   time   sig.  
                                                                          dd=denominator   of   time   sig.   2=quarter  
                                                                          3=eighth,   etc.  
                                                                          cc=number   of   ticks   in   metronome   click  
                                                                          bb=number   of   32nd   notes   to   the   quarter  
                                                                          note  
   
  59               01011001           02   sf   mi             Key   signature  
                                                                          sf=sharps/flats   (-7=7   flats,   0=key   of   C,  
                                                                          7=7   sharps)  
                                                                          mi=major/minor   (0=major,   1=minor)  
   
  7F               01111111           xx   dd   ..             Sequencer   specific   information  
                                                                          xx=number   of   bytes   to   be   sent  
                                                                          dd=data  
  The   following   table   lists   system   messages   which   control   the   entire   system.  
  These   have   no   midi   channel   number.   (these   will   generally   only   apply   to  
  controlling   a   midi   keyboard,   etc.)  
   
  Hex             Binary               Data                     Description  
  F8               11111000                                       Timing   clock   used   when   synchronization   is  
                                                                          required.  
   
  FA               11111010                                       Start   current   sequence  
   
  FB               11111011                                       Continue   a   stopped   sequence   where   left  
                                                                          off  
   
  FC               11111100                                       Stop   a   sequence  
   
   
  The   following   table   lists   the   numbers   corresponding   to   notes   for   use   in   note    
  on   and   note   off   commands.  
   
   
  Octave||                                           Note   Numbers  
        #     ||  
              ||   C       |   C#     |   D       |   D#     |   E       |   F       |   F#     |   G       |   G#     |   A       |   A#     |   B  
  -----------------------------------------------------------------------------  
        0     ||       0   |       1   |       2   |       3   |       4   |       5   |       6   |       7   |       8   |       9   |     10   |   11  
        1     ||     12   |     13   |     14   |     15   |     16   |     17   |     18   |     19   |     20   |     21   |     22   |   23  
        2     ||     24   |     25   |     26   |     27   |     28   |     29   |     30   |     31   |     32   |     33   |     34   |   35  
        3     ||     36   |     37   |     38   |     39   |     40   |     41   |     42   |     43   |     44   |     45   |     46   |   47  
        4     ||     48   |     49   |     50   |     51   |     52   |     53   |     54   |     55   |     56   |     57   |     58   |   59  
        5     ||     60   |     61   |     62   |     63   |     64   |     65   |     66   |     67   |     68   |     69   |     70   |   71  
        6     ||     72   |     73   |     74   |     75   |     76   |     77   |     78   |     79   |     80   |     81   |     82   |   83  
        7     ||     84   |     85   |     86   |     87   |     88   |     89   |     90   |     91   |     92   |     93   |     94   |   95  
        8     ||     96   |     97   |     98   |     99   |   100   |   101   |   102   |   103   |   104   |   105   |   106   |   107  
        9     ||   108   |   109   |   110   |   111   |   112   |   113   |   114   |   115   |   116   |   117   |   118   |   119  
      10     ||   120   |   121   |   122   |   123   |   124   |   125   |   126   |   127   |  
   
   
                                                                  BIBLIOGRAPHY  
   
      "MIDI   Systems   and   Control"   Francis   Rumsey     1990   Focal   Press  
   
      "MIDI   and   Sound   Book   for   the   Atari   ST"   Bernd   Enders   and   Wolfgang   Klemme  
                      1989   M&T   Publishing,   Inc.  
   
      MIDI   file   specs   and   general   MIDI   specs   were   also   obtained   by   sending   e-mail  
                    to   LISTSERV@AUVM.AMERICAN.EDU   with   the   phrase   GET   MIDISPEC   PACKAGE  
                    in   the   message.  
   
   
  -------------------------------   DEC.CPP   ------------------------------------  
   
  /*     file     dec.cpp  
   
  by     Dustin   Caldwell         (dustin@gse.utah.edu)  
   
  */  
   
   
  #include   <dos.h>  
  #include   <stdio.h>  
  #include   <stdlib.h>  
   
  void   helpdoc();  
   
  main()  
  {  
                  FILE   *fp;  
   
                  unsigned   char   ch,   c;  
   
                  if((fp=fopen(_argv[1],   "rb"))==NULL)                         /*   open   file   to   read   */  
                  {  
                                  printf("cannot   open   file   %s\n",_argv[1]);  
                                  helpdoc();  
                                  exit(-1);  
                  }  
   
                  c=0;  
                  ch=fgetc(fp);  
   
                  while(!feof(fp))                                                 /*   loop   for   whole   file   */  
                  {  
                                  printf("%u\t",   ch);                           /*   print   every   byte's   decimal   equiv.   */  
                                  c++;  
                                  if(c>8)                                                                   /*   print   8   numbers   to   a   line   */  
                                  {  
                                                  c=0;  
                                                  printf("\n");  
                                  }  
   
                                  ch=fgetc(fp);  
                  }  
   
                  fclose(fp);                                           /*   close   up   */  
  }  
   
  void   helpdoc()                                     /*   print   help   message   */  
  {  
                  printf("\n       Binary   File   Decoder\n\n");  
   
                  printf("\n   Syntax:     dec   binary_file_name\n\n");  
   
                  printf("by   Dustin   Caldwell     (dustin@gse.utah.edu)\n\n");  
                  printf("This   is   a   filter   program   that   reads   a   binary   file\n");  
                  printf("and   prints   the   decimal   equivalent   of   each   byte\n");  
                  printf("tab-separated.   This   is   mostly   useful   when   piped   \n");  
                  printf("into   another   file   to   be   edited   manually.     eg:\n\n");  
                  printf("c:\>dec   sonata3.mid   >   son3.txt\n\n");  
                  printf("This   will   create   a   file   called   son3.txt   which   can\n");  
                  printf("be   edited   with   any   ascii   editor.   \n\n");  
                  printf("(rec.exe   may   also   be   useful,   as   it   reencodes   the   \n");  
                  printf("ascii   text   file).\n\n");  
                  printf("Have   Fun!!\n");  
  }  
   
  ----------------------------   REC.CPP   ----------------------------------  
   
  /*     File     rec.cpp  
                  by   Dustin   Caldwell       (dustin@gse.utah.edu)  
  */  
   
  #include   <dos.h>  
  #include   <stdio.h>  
  #include   <ctype.h>  
  #include   <stdlib.h>  
   
  void   helpdoc();  
   
  main()  
  {  
                  FILE   *rfp,   *wfp;  
   
                  unsigned   char   ch,   c;  
                  char   s[20];  
   
                  if((rfp=fopen(_argv[1],   "r"))==NULL)                                         /*   open   the   read   file   */  
                  {  
                                  printf("cannot   open   file   %s   \n",_argv[1]);  
                                  helpdoc();  
                                  exit(-1);  
                  }  
   
                  if((wfp=fopen(_argv[2],   "wb"))==NULL)                                       /*   open   the   write   file   */  
                  {  
                                  printf("cannot   open   file   %s   \n",_argv[1]);  
                                  helpdoc();  
                                  exit(-1);  
                  }  
   
                  c=0;  
   
                  ch=fgetc(rfp);  
   
                  while(!feof(rfp))                                               /*   loop   for   whole   file   */  
                  {  
   
                                  if(isalnum(ch))                                   /*   only   'see'   valid   ascii   chars   */  
                                  {  
                                                  c=0;  
                                                  while(isdigit(ch))             /*   only   use   decimal   digits   (0-9)   */  
                                                  {  
                                                                  s[c]=ch;                 /*   build   a   string   containing   the   number   */  
                                                                  c++;  
                                                                  ch=fgetc(rfp);  
                                                  }  
                                                  s[c]=NULL;                                             /*   must   have   NULL   terminator   */  
   
                                                  fputc(atoi(s),   wfp);/*   write   the   binary   equivalent   to   file   */  
   
                                  }  
   
                                  ch=fgetc(rfp);                                     /*   loop   until   next   number   starts   */  
   
   
                  }  
   
                  fclose(rfp);                                         /*   close   up   */  
                  fclose(wfp);  
  }  
   
   
  void   helpdoc()                     /*   print   help   message   */  
  {  
                  printf("\n       Text   File   Encoder\n\n");  
   
                  printf("\n   Syntax:     rec   text_file_name   binary_file_name\n\n");  
   
                  printf("by   Dustin   Caldwell     (dustin@gse.utah.edu)\n\n");  
                  printf("This   is   a   program   that   reads   an   ascii   tab-\n");  
                  printf("delimited   file   and   builds   a   binary   file   where\n");  
                  printf("each   byte   of   the   binary   file   is   one   of   the   decimal\n");  
                  printf("digits   in   the   text   file.\n");  
                  printf("   eg:\n\n");  
                  printf("c:\>rec   son3.txt   son3.mid\n\n");  
                  printf("(This   will   create   a   file   called   son3.mid   which   is\n");  
                  printf("a   valid   binary   file)\n\n");  
                  printf("(dec.exe   may   also   be   useful,   as   it   decodes   binary   files)\n\n");  
                  printf("Have   Fun!!\n");  
  }