MIDI.H
上传用户:lianyisd
上传日期:2019-11-03
资源大小:5188k
文件大小:10k
源码类别:

midi

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1998 by J鰎g K鰊ig
  3. // All rights reserved
  4. //
  5. // This file is part of the completely free tetris clone "CGTetris".
  6. //
  7. // This is free software.
  8. // You may redistribute it by any means providing it is not sold for profit
  9. // without the authors written consent.
  10. //
  11. // No warrantee of any kind, expressed or implied, is included with this
  12. // software; use at your own risk, responsibility for damages (if any) to
  13. // anyone resulting from the use of this software rests entirely with the
  14. // user.
  15. //
  16. // Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  17. // I'll try to keep a version up to date.  I can be reached as follows:
  18. //    J.Koenig@adg.de                 (company site)
  19. //    Joerg.Koenig@rhein-neckar.de    (private site)
  20. /////////////////////////////////////////////////////////////////////////////
  21. // Midi.h : main header file for the MIDI application
  22. //
  23. // This class is based on the DirectX sample "mstream".
  24. #ifndef MIDI_h
  25. #define MIDI_h
  26. #if _MSC_VER >= 1000
  27. #pragma once
  28. #endif // _MSC_VER >= 1000
  29. #include <mmsystem.h>
  30. #pragma message("linking with multimedia library")
  31. #pragma comment(lib, "winmm.lib")
  32. #include <vector>
  33. using namespace std;
  34. // This message is sent to the controlling window, if the volume changes in
  35. // another way than explicitly set by the owner of the CMIDI object.
  36. // WPARAM the pointer to the MIDI object
  37. // LPARAM lo-word: the number of the channel that changed volume
  38. // hi-word: the new volume in percent
  39. #define WM_MIDI_VOLUMECHANGED WM_USER+23
  40. #define MIDI_CTRLCHANGE ((BYTE)0xB0) // + ctrlr + value
  41. #define MIDI_PRGMCHANGE ((BYTE)0xC0) // + new patch
  42. #define MIDI_CHANPRESS ((BYTE)0xD0) // + pressure (1 byte)
  43. #define MIDICTRL_VOLUME ((BYTE)0x07)
  44. #define MIDIEVENT_CHANNEL(dw) (dw & 0x0000000F)
  45. #define MIDIEVENT_TYPE(dw) (dw & 0x000000F0)
  46. #define MIDIEVENT_DATA1(dw) ((dw & 0x0000FF00) >> 8)
  47. #define MIDIEVENT_VOLUME(dw) ((dw & 0x007F0000) >> 16)
  48. #define MIDI_SYSEX ((BYTE)0xF0) // SysEx begin
  49. #define MIDI_SYSEXEND ((BYTE)0xF7) // SysEx end
  50. #define MIDI_META ((BYTE)0xFF) // Meta event begin
  51. #define MIDI_META_TEMPO ((BYTE)0x51) // Tempo change
  52. #define MIDI_META_EOT ((BYTE)0x2F) // End-of-track
  53. // flags for the ConvertToBuffer() method
  54. #define CONVERTF_RESET 0x00000001
  55. #define CONVERTF_STATUS_DONE 0x00000001
  56. #define CONVERTF_STATUS_STUCK 0x00000002
  57. #define CONVERTF_STATUS_GOTEVENT 0x00000004
  58. // Return values from the ConvertToBuffer() method
  59. #define CONVERTERR_NOERROR 0 // No error occured
  60. #define CONVERTERR_CORRUPT -101 // The input file is corrupt
  61. // The converter has already encountered a corrupt file and cannot convert any
  62. // more of this file -- must reset the converter
  63. #define CONVERTERR_STUCK -102
  64. #define CONVERTERR_DONE -103 // Converter is done
  65. #define CONVERTERR_BUFFERFULL -104 // The buffer is full
  66. #define CONVERTERR_METASKIP -105 // Skipping unknown meta event
  67. #define STATUS_KILLCALLBACK 100 // Signals that the callback should die
  68. #define STATUS_CALLBACKDEAD 200 // Signals callback is done processing
  69. #define STATUS_WAITINGFOREND 300 // Callback's waiting for buffers to play
  70. // Description of a track
  71. //
  72. struct TRACK
  73. {
  74. DWORD fdwTrack; // Track's flags
  75. DWORD dwTrackLength; // Total bytes in track
  76. LPBYTE pTrackStart; // -> start of track data buffer
  77. LPBYTE pTrackCurrent; // -> next byte to read in buffer
  78. DWORD tkNextEventDue; // Absolute time of next event in track
  79. BYTE byRunningStatus;// Running status from last channel msg
  80. TRACK()
  81. : fdwTrack(0)
  82. , dwTrackLength(0)
  83. , pTrackStart(0)
  84. , pTrackCurrent(0)
  85. , tkNextEventDue(0)
  86. , byRunningStatus(0)
  87. {
  88. }
  89. };
  90. #define ITS_F_ENDOFTRK 0x00000001
  91. // This structure is used to pass information to the ConvertToBuffer()
  92. // system and then internally by that function to send information about the
  93. // target stream buffer and current state of the conversion process to internal
  94. // lower level conversion routines.
  95. struct CONVERTINFO
  96. {
  97.     MIDIHDR mhBuffer; // Standard Windows stream buffer header
  98.     DWORD dwStartOffset; // Start offset from mhStreamBuffer.lpStart
  99.     DWORD dwMaxLength; // Max length to convert on this pass
  100.     DWORD dwBytesRecorded;
  101.     DWORD tkStart;
  102.     BOOL bTimesUp;
  103. CONVERTINFO()
  104. : dwStartOffset(0)
  105. , dwMaxLength(0)
  106. , dwBytesRecorded(0)
  107. , tkStart(0)
  108. , bTimesUp(FALSE)
  109. {
  110. memset(&mhBuffer, 0, sizeof(MIDIHDR));
  111. }
  112. };
  113. // Temporary event structure which stores event data until we're ready to
  114. // dump it into a stream buffer
  115. struct TEMPEVENT
  116. {
  117. DWORD tkEvent; // Absolute time of event
  118. BYTE byShortData[4]; // Event type and parameters if channel msg
  119. DWORD dwEventLength; // Length of data which follows if meta or sysex
  120. LPBYTE pLongData; // -> Event data if applicable
  121. };
  122. class CMIDI  
  123. {
  124. protected:
  125. typedef vector<TRACK> TrackArray_t;
  126. typedef vector<DWORD> VolumeArray_t;
  127. typedef vector<CONVERTINFO> ConvertArray_t;
  128. enum {
  129. NUM_CHANNELS = 16, // 16 volume channels
  130. VOLUME_INIT = 100, // 100% volume by default
  131. NUM_STREAM_BUFFERS = 2,
  132. OUT_BUFFER_SIZE = 1024, // Max stream buffer size in bytes
  133. DEBUG_CALLBACK_TIMEOUT = 2000,
  134. VOLUME_MIN = 0,
  135. VOLUME_MAX = 127 // == 100%
  136. };
  137. public:
  138. CMIDI();
  139. virtual ~CMIDI();
  140. BOOL Create(LPVOID pSoundData, DWORD dwSize, CWnd * pParent = 0);
  141. BOOL Create(LPCTSTR pszResID, CWnd * pParent = 0);
  142. BOOL Create(UINT uResID, CWnd * pParent = 0);
  143. BOOL Play(BOOL bInfinite = FALSE);
  144. BOOL Stop(BOOL bReOpen = TRUE);
  145. BOOL IsPlaying() const { return m_bPlaying; }
  146. BOOL Pause();
  147. BOOL Continue();
  148. BOOL IsPaused() const { return m_bPaused; }
  149. // Set playback position back to the start
  150. BOOL Rewind();
  151. // Get the number of volume channels
  152. DWORD GetChannelCount() const;
  153. // Set the volume of a channel in percent. Channels are from 0 to (GetChannelCount()-1)
  154. void SetChannelVolume(DWORD channel, DWORD percent);
  155. // Get the volume of a channel in percent
  156. DWORD GetChannelVolume(DWORD channel) const;
  157. // Set the volume for all channels in percent
  158. void SetVolume(DWORD percent);
  159. // Get the average volume for all channels
  160. DWORD GetVolume() const;
  161. // Set the tempo of the playback. Default: 100%
  162. void SetTempo(DWORD percent);
  163. // Get the current tempo in percent (usually 100)
  164. DWORD GetTempo() const;
  165. // You can (un)set an infinite loop during playback.
  166. // Note that "Play()" resets this setting!
  167. void SetInfinitePlay(BOOL bSet = TRUE);
  168. protected: // implementation
  169. // This function converts MIDI data from the track buffers.
  170. int ConvertToBuffer(DWORD dwFlags, CONVERTINFO * lpciInfo);
  171. // Fills in the event struct with the next event from the track
  172. BOOL GetTrackEvent(TRACK * ptsTrack, TEMPEVENT * pteTemp);
  173. // Retrieve the next byte from the track buffer, refilling the buffer from
  174. // disk if necessary.
  175. BOOL GetTrackByte(TRACK * ptsTrack, LPBYTE lpbyByte) {
  176. if( DWORD(ptsTrack->pTrackCurrent - ptsTrack->pTrackStart) == ptsTrack->dwTrackLength )
  177. return FALSE;
  178. *lpbyByte = *ptsTrack->pTrackCurrent++;
  179. return TRUE;
  180. }
  181. // Attempts to parse a variable length DWORD from the given track.
  182. BOOL GetTrackVDWord(TRACK * ptsTrack, LPDWORD lpdw);
  183. // Put the given event into the given stream buffer at the given location.
  184. int AddEventToStreamBuffer( TEMPEVENT * pteTemp, CONVERTINFO * lpciInfo );
  185. // Opens a MIDI stream. Then it goes about converting the data into a midiStream buffer for playback.
  186. BOOL StreamBufferSetup();
  187. void FreeBuffers();
  188. protected: // error handling
  189. // The default implementation writes the error message in the
  190. // debuggers output window. Override if you want a different
  191. // behavior.
  192. virtual void MidiError(MMRESULT Result);
  193. // Failure in converting track into stream.
  194. // The default implementation displays the offset and the total
  195. // number of bytes of the failed track and the error message in
  196. // the debuggers output window. 
  197. virtual void TrackError(TRACK *, LPSTR ErrMsg);
  198. protected: // overridables
  199. // NOTE THAT, IF YOU OVERRIDE ONE OF THESE METHODS, YOU MUST CALL
  200. // THE BASE CLASS IMPLEMENTATION TOO!
  201. // called when a MIDI output device is opened
  202. virtual void OnMidiOutOpen();
  203. // called when the MIDI output device is closed
  204. virtual void OnMidiOutClose();
  205. // called when the specified system-exclusive or stream buffer
  206. // has been played and is being returned to the application
  207. virtual void OnMidiOutDone(MIDIHDR &);
  208. // called when a MEVT_F_CALLBACK event is reached in the MIDI output stream
  209. virtual void OnMidiOutPositionCB(MIDIHDR &, MIDIEVENT &);
  210. private: // callback procedure
  211. // This procedure calls the overridables above.
  212. static void CALLBACK MidiProc(HMIDIOUT, UINT, DWORD, DWORD, DWORD);
  213. protected: // data members
  214. DWORD m_dwSoundSize;
  215. LPVOID m_pSoundData;
  216. DWORD m_dwFormat;
  217. DWORD m_dwTrackCount;
  218. DWORD m_dwTimeDivision;
  219. BOOL m_bPlaying;
  220. HMIDISTRM m_hStream;
  221. DWORD m_dwProgressBytes;
  222. BOOL m_bLooped;
  223. DWORD m_tkCurrentTime;
  224. DWORD m_dwBufferTickLength;
  225. DWORD m_dwCurrentTempo;
  226. DWORD m_dwTempoMultiplier;
  227. BOOL m_bInsertTempo;
  228. BOOL m_bBuffersPrepared;
  229. int m_nCurrentBuffer;
  230. UINT m_uMIDIDeviceID;
  231. int m_nEmptyBuffers;
  232. BOOL m_bPaused;
  233. UINT m_uCallbackStatus;
  234. HANDLE m_hBufferReturnEvent;
  235. CWnd * m_pWndParent;
  236. TrackArray_t m_Tracks;
  237. VolumeArray_t m_Volumes;
  238. ConvertArray_t m_StreamBuffers;
  239. // data members especially for ConvertToBuffer()
  240.     TRACK * m_ptsTrack;
  241. TRACK * m_ptsFound;
  242.     DWORD m_dwStatus;
  243.     DWORD m_tkNext;
  244. DWORD m_dwMallocBlocks;
  245.     TEMPEVENT m_teTemp;
  246. };
  247. //{{AFX_INSERT_LOCATION}}
  248. // Microsoft Developer Studio will insert additional declarations immediately before the previous line.
  249. #endif // MIDI_h