/////////////////////////////////////////////////////////////////////////////
// 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.
/////////////////////////////////////////////////////////////////////////////
// Midi.cpp
//
// The CMIDI class is based on a sample in the DirectX SDK (mstream)
#include "stdafx.h"
#include "Midi.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define MThd 0x6468544D // Start of file
#define MTrk 0x6B72544D // Start of track
#define BUFFER_TIME_LENGTH 60 // Amount to fill in milliseconds
// These structures are stored in MIDI files; they need to be byte aligned.
//
#pragma pack(1)
// Contents of MThd chunk.
struct MIDIFILEHDR
{
WORD wFormat; // Format (hi-lo)
WORD wTrackCount; // # tracks (hi-lo)
WORD wTimeDivision; // Time division (hi-lo)
};
#pragma pack() // End of need for byte-aligned structures
// Macros for swapping hi/lo-endian data
//
#define WORDSWAP(w) (((w) >> 8) | \
(((w) << 8) & 0xFF00))
#define DWORDSWAP(dw) (((dw) >> 24) | \
(((dw) >> 8) & 0x0000FF00) | \
(((dw) << 8) & 0x00FF0000) | \
(((dw) << 24) & 0xFF000000))
static char gteBadRunStat[] = "Reference to missing running status.";
static char gteRunStatMsgTrunc[]= "Running status message truncated";
static char gteChanMsgTrunc[] = "Channel message truncated";
static char gteSysExLenTrunc[] = "SysEx event truncated (length)";
static char gteSysExTrunc[] = "SysEx event truncated";
static char gteMetaNoClass[] = "Meta event truncated (no class byte)";
static char gteMetaLenTrunc[] = "Meta event truncated (length)";
static char gteMetaTrunc[] = "Meta event truncated";
static char gteNoMem[] = "Out of memory during malloc call";
//////////////////////////////////////////////////////////////////////
// CMIDI -- Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMIDI::CMIDI()
: m_dwSoundSize(0)
, m_pSoundData(0)
, m_dwFormat(0)
, m_dwTrackCount(0)
, m_dwTimeDivision(0)
, m_bPlaying(FALSE)
, m_hStream(0)
, m_dwProgressBytes(0)
, m_bLooped(FALSE)
, m_tkCurrentTime(0)
, m_dwBufferTickLength(0)
, m_dwCurrentTempo(0)
, m_dwTempoMultiplier(100)
, m_bInsertTempo(FALSE)
, m_bBuffersPrepared(FALSE)
, m_nCurrentBuffer(0)
, m_uMIDIDeviceID(MIDI_MAPPER)
, m_nEmptyBuffers(0)
, m_bPaused(FALSE)
, m_uCallbackStatus(0)
, m_hBufferReturnEvent(0)
, m_ptsTrack(0)
, m_ptsFound(0)
, m_dwStatus(0)
, m_tkNext(0)
, m_dwMallocBlocks(0)
{
m_hBufferReturnEvent = ::CreateEvent(0, FALSE, FALSE, TEXT("Wait For Buffer Return"));
ASSERT(m_hBufferReturnEvent != 0);
}
CMIDI::~CMIDI()
{
Stop(FALSE);
if(m_hBufferReturnEvent)
::CloseHandle(m_hBufferReturnEvent);
}
BOOL CMIDI::Create(UINT uResID, CWnd * pWndParent /* = NULL */)
{
return Create(MAKEINTRESOURCE(uResID), pWndParent);
}
BOOL CMIDI::Create(LPCTSTR pszResID, CWnd * pWndParent /* = NULL */)
{
//////////////////////////////////////////////////////////////////
// load resource
HINSTANCE hApp = ::GetModuleHandle(0);
ASSERT(hApp);
HRSRC hResInfo = ::FindResource(hApp, pszResID, TEXT("MIDI"));
if(hResInfo == 0)
return FALSE;
HGLOBAL hRes = ::LoadResource(hApp, hResInfo);
if(hRes == 0)
return FALSE;
LPVOID pTheSound = ::LockResource(hRes);
if(pTheSound == 0)
return FALSE;
DWORD dwTheSound = ::SizeofResource(hApp, hResInfo);
return Create(pTheSound, dwTheSound, pWndParent);
}
BOOL CMIDI::Create(LPVOID pSoundData, DWORD dwSize, CWnd * pWndParent /* = NULL */)
{
if( m_pSoundData ) {
// already created
ASSERT(FALSE);
return FALSE;
}
ASSERT(pSoundData != 0);
ASSERT(dwSize > 0);
register LPBYTE p = LPBYTE(pSoundData);
// check header of MIDI
if(*(DWORD*)p != MThd) {
ASSERT(FALSE);
return FALSE;
}
p += sizeof(DWORD);
// check header size
DWORD dwHeaderSize = DWORDSWAP(*(DWORD*)p);
if( dwHeaderSize != sizeof(MIDIFILEHDR) ) {
ASSERT(FALSE);
return FALSE;
}
p += sizeof(DWORD);
// get header
MIDIFILEHDR hdr;
::CopyMemory(&hdr, p, dwHeaderSize);
m_dwFormat = DWORD(WORDSWAP(hdr.wFormat));
m_dwTrackCount = DWORD(WORDSWAP(hdr.wTrackCount));
m_dwTimeDivision = DWORD(WORDSWAP(hdr.wTimeDivision));
p += dwHeaderSize;
// create the array of tracks
m_Tracks.resize(m_dwTrackCount);
for(register DWORD i = 0; i < m_dwTrackCount; ++i) {
// check header of track
if(*(DWORD*)p != MTrk) {
ASSERT(FALSE);
return FALSE;
}
p += sizeof(DWORD);
m_Tracks[i].dwTrackLength = DWORDSWAP(*(DWORD*)p);
p += sizeof(DWORD);
m_Tracks[i].pTrackStart = m_Tracks[i].pTrackCurrent = p;
p += m_Tracks[i].dwTrackLength;
// Handle bozo MIDI files which contain empty track chunks
if( !m_Tracks[i].dwTrackLength ) {
m_Tracks[i].fdwTrack |= ITS_F_ENDOFTRK;
continue;
}
// We always preread the time from each track so the mixer code can
// determine which track has the next event with a minimum of work
if( !GetTrackVDWord( &m_Tracks[i], &m_Tracks[i].tkNextEventDue )) {
TRACE0("Error in MIDI data\n");
ASSERT(FALSE);
return FALSE;
}
}
m_pSoundData = pSoundData;
m_dwSoundSize = dwSize;
m_pWndParent = pWndParent;
// allocate volume channels and initialise them
m_Volumes.resize(NUM_CHANNELS, VOLUME_INIT);
if( ! StreamBufferSetup() ) {
ASSERT(FALSE);
return FALSE;
}
return TRUE;
}
BOOL CMIDI :: Play(BOOL bInfinite /* = FALSE */) {
if( IsPaused() ) {
Continue();
return TRUE;
}
// calling Play() while it is already playing will restart from scratch
if( IsPlaying() )
Stop();
// Clear the status of our callback so it will handle
// MOM_DONE callbacks once more
m_uCallbackStatus = 0;
MMRESULT mmResult;
if( (mmResult = midiStreamRestart(m_hStream)) != MMSYSERR_NOERROR ) {
MidiError(mmResult);
return FALSE;
}
m_bPlaying = TRUE;
m_bLooped = bInfinite;
return m_bPlaying;
}
BOOL CMIDI :: Stop(BOOL bReOpen /*=TRUE*/) {
MMRESULT mmrRetVal;
if( IsPlaying() || (m_uCallbackStatus != STATUS_CALLBACKDEAD) ) {
m_bPlaying = m_bPaused = FALSE;
if( m_uCallbackStatus != STATUS_CALLBACKDEAD && m_uCallbackStatus != STATUS_WAITINGFOREND )
m_uCallbackStatus = STATUS_KILLCALLBACK;
if( (mmrRetVal = midiStreamStop(m_hStream) ) != MMSYSERR_NOERROR ) {
MidiError(mmrRetVal);
return FALSE;
}
if( (mmrRetVal = midiOutReset((HMIDIOUT)m_hStream)) != MMSYSERR_NOERROR ) {
MidiError(mmrRetVal);
return FALSE;
}
// Wait for the callback thread to release this thread, which it will do by
// calling SetEvent() once all buffers are returned to it
if( WaitForSingleObject( m_hBufferReturnEvent, DEBUG_CALLBACK_TIMEOUT ) == WAIT_TIMEOUT ) {
// Note, this is a risky move because the callback may be genuinely busy, but
// when we're debugging, it's safer and faster than freezing the application,
// which leaves the MIDI device locked up and forces a system reset...
TRACE0("Timed out waiting for MIDI callback\n");
m_uCallbackStatus = STATUS_CALLBACKDEAD;
}
}
if( m_uCallbackStatus == STATUS_CALLBACKDEAD ) {
m_uCallbackStatus = 0;
FreeBuffers();
if( m_hStream ) {
if( (mmrRetVal = midiStreamClose(m_hStream) ) != MMSYSERR_NOERROR ) {
MidiError(mmrRetVal);
}
m_hStream = 0;
}
if( bReOpen ) {
if( !StreamBufferSetup() )
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
带音效和高级设置的VC俄罗斯方块游戏 (121个子文件)
TETRIS.001 11KB
TETRIS.APS 1.07MB
STRING~1.APS 36KB
BITMAP1.BMP 576KB
TETRIS.BMP 249KB
REDPLACE.BMP 51KB
SHIELD.BMP 11KB
KEYBOARD.BMP 5KB
PARAGR~1.BMP 2KB
0.BMP 302B
1.BMP 302B
BLACK.BMP 302B
9.BMP 302B
8.BMP 302B
4.BMP 302B
3.BMP 302B
6.BMP 302B
2.BMP 302B
7.BMP 302B
5.BMP 302B
MIDI.CPP 35KB
CREDIT~1.CPP 28KB
GAMEBO~1.CPP 17KB
ROUNDB~2.CPP 17KB
DIB256.CPP 14KB
TETRIS~1.CPP 8KB
DIRECT~1.CPP 8KB
OPTION~1.CPP 6KB
SCOREDLG.CPP 6KB
TETRIS.CPP 5KB
MAINDLG.CPP 5KB
BITMAP~1.CPP 5KB
BITMAP~2.CPP 4KB
PIECEP~1.CPP 4KB
LANGUAGE.CPP 4KB
DIGIDI~1.CPP 4KB
BITMAP~3.CPP 3KB
SOUND.CPP 3KB
ABOUTDLG.CPP 3KB
SPLASH~1.CPP 3KB
HELPDLG.CPP 3KB
ROUNDB~1.CPP 3KB
VOLUME~1.CPP 3KB
GAMEOV~1.CPP 2KB
DIBPAL.CPP 2KB
PROPSH~1.CPP 2KB
STDAFX.CPP 823B
TETRIS.DSP 11KB
TETRIS.DSW 537B
CGTETRIS.EXE 2.79MB
CGTETRIS.EXE 2.79MB
MIDI.H 9KB
PIECE.H 7KB
GAMEBO~1.H 5KB
RESOURCE.H 4KB
CREDIT~1.H 3KB
TETRIS~1.H 3KB
SCOREDLG.H 3KB
OPTION~1.H 3KB
DIB256.H 3KB
MAINDLG.H 3KB
BITMAP~1.H 3KB
DIRECT~1.H 3KB
BITMAP~2.H 3KB
TETRIS.H 3KB
ROUNDB~2.H 2KB
BITMAP~3.H 2KB
PIECEP~1.H 2KB
STRING~1.H 2KB
ABOUTDLG.H 2KB
HELPDLG.H 2KB
DIGIDI~1.H 2KB
VOLUME~1.H 2KB
GAMEOV~1.H 2KB
SPLASH~1.H 2KB
MEMDC.H 2KB
PROPSH~1.H 2KB
STDAFX.H 2KB
ROUNDB~1.H 2KB
LANGUAGE.H 1KB
SOUND.H 1KB
DIBPAL.H 767B
TETRIS.ICO 766B
BOOM_4.ICO 318B
BOOM_9.ICO 318B
BOOM_10.ICO 318B
BOOM_3.ICO 318B
BOOM_8.ICO 318B
BOOM_5.ICO 318B
BOOM_6.ICO 318B
BOOM_7.ICO 318B
BOOM_1.ICO 318B
BOOM_2.ICO 318B
MOVERIGH.ICO 246B
PLACE1.ICO 246B
MOVELEFT.ICO 246B
ICON1.ICO 246B
09_08.JPG 61KB
09_02.JPG 60KB
09_10.JPG 45KB
共 121 条
- 1
- 2
资源评论
- yanxiaoshuai20092012-09-28不错,可以运行
- bing_luo_182012-09-18不错,可以用 ,但不是我想要的。
codeenter
- 粉丝: 9
- 资源: 132
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- Video_1732514072178.mp4
- yolo算法-手套-无手套-人数据集-14163张图像带标签-手套-无手套.zip
- WordPress主题 多本小说阅读模板
- yolo算法-道路损伤检测数据集-17145张图像带标签-纵向的-坑洼.zip
- yolo算法-猴子-大象-猪动物数据集-6229张图像带标签-猴子-大象-猪-牛-鹿-熊-棕熊-老虎.zip
- yolo算法-动物数据集-8944张图像带标签-自行车-背景-大象-豹-牛-熊-鹿-马-摩托车-猎豹-福克斯-猴子-美洲虎-太阳能电池板-老虎-犀牛-狮子-山羊-人-狗-天鱼-鸟.zip
- WordPress在线社交问答社区主题Discy V3.8.1
- 公开整理-农业科技创新数据集(2010-2022).xlsx
- 基于Python卷积神经网络人脸识别驾驶员疲劳检测与预警系统设计毕业源码案例设计
- yolo算法-麻将数据集-2205张图像带标签-绿色-北-南方-西-白色-万-东-红色.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功