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

📄 midi.h

📁 软件类别:多 媒 体 软件大小:12KB 运行环境:windows/ 软件 类别:多 媒 体 软件大小:12KB 运行环境:windows/
💻 H
字号:
/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1998 by J鰎g K鰊ig
// All rights reserved
//
// This file is part of the completely free tetris clone "CGTetris".
//
// This is free software.
// You may redistribute it by any means providing it is not sold for profit
// without the authors written consent.
//
// No warrantee of any kind, expressed or implied, is included with this
// software; use at your own risk, responsibility for damages (if any) to
// anyone resulting from the use of this software rests entirely with the
// user.
//
// Send bug reports, bug fixes, enhancements, requests, flames, etc., and
// I'll try to keep a version up to date.  I can be reached as follows:
//    J.Koenig@adg.de                 (company site)
//    Joerg.Koenig@rhein-neckar.de    (private site)
/////////////////////////////////////////////////////////////////////////////


// Midi.h : main header file for the MIDI application
//

// This class is based on the DirectX sample "mstream".

#ifndef MIDI_h
#define MIDI_h

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#include <mmsystem.h>
#pragma message("linking with multimedia library")
#pragma comment(lib, "winmm.lib")

#include <vector>
using namespace std;


// This message is sent to the controlling window, if the volume changes in
// another way than explicitly set by the owner of the CMIDI object.
// WPARAM	the pointer to the MIDI object
// LPARAM	lo-word: the number of the channel that changed volume
//			hi-word: the new volume in percent
#define	WM_MIDI_VOLUMECHANGED	WM_USER+23


#define MIDI_CTRLCHANGE			((BYTE)0xB0)		// + ctrlr + value
#define MIDI_PRGMCHANGE			((BYTE)0xC0)		// + new patch
#define MIDI_CHANPRESS			((BYTE)0xD0)		// + pressure (1 byte)

#define MIDICTRL_VOLUME			((BYTE)0x07)

#define MIDIEVENT_CHANNEL(dw)	(dw & 0x0000000F)
#define MIDIEVENT_TYPE(dw)		(dw & 0x000000F0)
#define MIDIEVENT_DATA1(dw)		((dw & 0x0000FF00) >> 8)
#define MIDIEVENT_VOLUME(dw)	((dw & 0x007F0000) >> 16)

#define MIDI_SYSEX				((BYTE)0xF0)		// SysEx begin
#define MIDI_SYSEXEND			((BYTE)0xF7)		// SysEx end
#define MIDI_META				((BYTE)0xFF)		// Meta event begin
#define MIDI_META_TEMPO			((BYTE)0x51)		// Tempo change
#define MIDI_META_EOT			((BYTE)0x2F)		// End-of-track


// flags for the ConvertToBuffer() method
#define CONVERTF_RESET				0x00000001
#define CONVERTF_STATUS_DONE		0x00000001
#define CONVERTF_STATUS_STUCK		0x00000002
#define CONVERTF_STATUS_GOTEVENT	0x00000004

// Return values from the ConvertToBuffer() method
#define CONVERTERR_NOERROR		0		// No error occured
#define CONVERTERR_CORRUPT		-101	// The input file is corrupt
// The converter has already encountered a corrupt file and cannot convert any
// more of this file -- must reset the converter
#define CONVERTERR_STUCK		-102
#define CONVERTERR_DONE			-103	// Converter is done
#define CONVERTERR_BUFFERFULL	-104	// The buffer is full
#define CONVERTERR_METASKIP		-105	// Skipping unknown meta event

#define STATUS_KILLCALLBACK		100		// Signals that the callback should die
#define STATUS_CALLBACKDEAD		200		// Signals callback is done processing
#define STATUS_WAITINGFOREND	300		// Callback's waiting for buffers to play

// Description of a track
//
struct TRACK
{
	DWORD	fdwTrack;		// Track's flags
	DWORD	dwTrackLength;	// Total bytes in track
	LPBYTE	pTrackStart;	// -> start of track data buffer
	LPBYTE	pTrackCurrent;	// -> next byte to read in buffer
	DWORD	tkNextEventDue;	// Absolute time of next event in track
	BYTE	byRunningStatus;// Running status from last channel msg

	TRACK()
		: fdwTrack(0)
		, dwTrackLength(0)
		, pTrackStart(0)
		, pTrackCurrent(0)
		, tkNextEventDue(0)
		, byRunningStatus(0)
	{
	}
};

#define ITS_F_ENDOFTRK		0x00000001


// This structure is used to pass information to the ConvertToBuffer()
// system and then internally by that function to send information about the
// target stream buffer and current state of the conversion process to internal
// lower level conversion routines.
struct CONVERTINFO
{
    MIDIHDR	mhBuffer;			// Standard Windows stream buffer header
    DWORD	dwStartOffset;		// Start offset from mhStreamBuffer.lpStart
    DWORD	dwMaxLength;		// Max length to convert on this pass
    DWORD	dwBytesRecorded;
    DWORD	tkStart;
    BOOL	bTimesUp;

	CONVERTINFO()
		: dwStartOffset(0)
		, dwMaxLength(0)
		, dwBytesRecorded(0)
		, tkStart(0)
		, bTimesUp(FALSE)
	{
		memset(&mhBuffer, 0, sizeof(MIDIHDR));
	}
};

// Temporary event structure which stores event data until we're ready to
// dump it into a stream buffer
struct TEMPEVENT
{
	DWORD	tkEvent;		// Absolute time of event
	BYTE	byShortData[4];	// Event type and parameters if channel msg
	DWORD	dwEventLength;	// Length of data which follows if meta or sysex
	LPBYTE	pLongData;		// -> Event data if applicable
};

class CMIDI  
{
protected:
	typedef vector<TRACK>		TrackArray_t;
	typedef vector<DWORD>		VolumeArray_t;
	typedef vector<CONVERTINFO>	ConvertArray_t;

	enum {
		NUM_CHANNELS = 16,		// 16 volume channels
		VOLUME_INIT = 100,		// 100% volume by default
		NUM_STREAM_BUFFERS = 2,
		OUT_BUFFER_SIZE = 1024,	// Max stream buffer size in bytes
		DEBUG_CALLBACK_TIMEOUT = 2000,
		VOLUME_MIN = 0,
		VOLUME_MAX = 127		// == 100%
	};

public:
	CMIDI();
	virtual ~CMIDI();

	BOOL	Create(LPVOID pSoundData, DWORD dwSize, CWnd * pParent = 0);
	BOOL	Create(LPCTSTR pszResID, CWnd * pParent = 0);
	BOOL	Create(UINT uResID, CWnd * pParent = 0);

	BOOL	Play(BOOL bInfinite = FALSE);
	BOOL	Stop(BOOL bReOpen = TRUE);
	BOOL	IsPlaying() const { return m_bPlaying; }

	BOOL	Pause();
	BOOL	Continue();
	BOOL	IsPaused() const { return m_bPaused; }

		// Set playback position back to the start
	BOOL	Rewind();

		// Get the number of volume channels
	DWORD	GetChannelCount() const;

		// Set the volume of a channel in percent. Channels are from 0 to (GetChannelCount()-1)
	void	SetChannelVolume(DWORD channel, DWORD percent);

		// Get the volume of a channel in percent
	DWORD	GetChannelVolume(DWORD channel) const;
	
		// Set the volume for all channels in percent
	void	SetVolume(DWORD percent);

		// Get the average volume for all channels
	DWORD	GetVolume() const;

		// Set the tempo of the playback. Default: 100%
	void	SetTempo(DWORD percent);

		// Get the current tempo in percent (usually 100)
	DWORD	GetTempo() const;

		// You can (un)set an infinite loop during playback.
		// Note that "Play()" resets this setting!
	void	SetInfinitePlay(BOOL bSet = TRUE);

protected:	// implementation
		// This function converts MIDI data from the track buffers.
	int		ConvertToBuffer(DWORD dwFlags, CONVERTINFO * lpciInfo);

		// Fills in the event struct with the next event from the track
	BOOL	GetTrackEvent(TRACK * ptsTrack, TEMPEVENT * pteTemp);

		// Retrieve the next byte from the track buffer, refilling the buffer from
		// disk if necessary.
	BOOL	GetTrackByte(TRACK * ptsTrack, LPBYTE lpbyByte) {
				if( DWORD(ptsTrack->pTrackCurrent - ptsTrack->pTrackStart) == ptsTrack->dwTrackLength )
					return FALSE;
				*lpbyByte = *ptsTrack->pTrackCurrent++;
				return TRUE;
			}

		// Attempts to parse a variable length DWORD from the given track.
	BOOL	GetTrackVDWord(TRACK * ptsTrack, LPDWORD lpdw);

		// Put the given event into the given stream buffer at the given location.
	int		AddEventToStreamBuffer( TEMPEVENT * pteTemp, CONVERTINFO * lpciInfo );

		// Opens a MIDI stream. Then it goes about converting the data into a midiStream buffer for playback.
	BOOL	StreamBufferSetup();

	void	FreeBuffers();


protected:	// error handling
		// The default implementation writes the error message in the
		// debuggers output window. Override if you want a different
		// behavior.
	virtual void	MidiError(MMRESULT Result);

		// Failure in converting track into stream.
		// The default implementation displays the offset and the total
		// number of bytes of the failed track and the error message in
		// the debuggers output window. 
	virtual void	TrackError(TRACK *, LPSTR ErrMsg);


protected:	// overridables
		// NOTE THAT, IF YOU OVERRIDE ONE OF THESE METHODS, YOU MUST CALL
		// THE BASE CLASS IMPLEMENTATION TOO!

		// called when a MIDI output device is opened
	virtual void	OnMidiOutOpen();
	
		// called when the MIDI output device is closed
	virtual void	OnMidiOutClose();

		// called when the specified system-exclusive or stream buffer
		// has been played and is being returned to the application
	virtual void	OnMidiOutDone(MIDIHDR &);

		// called when a MEVT_F_CALLBACK event is reached in the MIDI output stream
	virtual void	OnMidiOutPositionCB(MIDIHDR &, MIDIEVENT &);


private:	// callback procedure
		// This procedure calls the overridables above.
	static void	CALLBACK	MidiProc(HMIDIOUT, UINT, DWORD, DWORD, DWORD);


protected:	// data members
	DWORD			m_dwSoundSize;
	LPVOID			m_pSoundData;
	DWORD			m_dwFormat;
	DWORD			m_dwTrackCount;
	DWORD			m_dwTimeDivision;
	BOOL			m_bPlaying;
	HMIDISTRM		m_hStream;
	DWORD			m_dwProgressBytes;
	BOOL			m_bLooped;
	DWORD			m_tkCurrentTime;
	DWORD			m_dwBufferTickLength;
	DWORD			m_dwCurrentTempo;
	DWORD			m_dwTempoMultiplier;
	BOOL			m_bInsertTempo;
	BOOL			m_bBuffersPrepared;
	int				m_nCurrentBuffer;
	UINT			m_uMIDIDeviceID;
	int				m_nEmptyBuffers;
	BOOL			m_bPaused;
	UINT			m_uCallbackStatus;
	HANDLE			m_hBufferReturnEvent;
	CWnd *			m_pWndParent;
	TrackArray_t	m_Tracks;
	VolumeArray_t	m_Volumes;
	ConvertArray_t	m_StreamBuffers;

	// data members especially for ConvertToBuffer()
    TRACK *			m_ptsTrack;
	TRACK *			m_ptsFound;
    DWORD			m_dwStatus;
    DWORD			m_tkNext;
	DWORD			m_dwMallocBlocks;
    TEMPEVENT		m_teTemp;
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // MIDI_h

⌨️ 快捷键说明

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