亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? midi.cpp

?? 在vc 6.0環境下的一個坦克小游戲
?? CPP
?? 第 1 頁 / 共 3 頁
字號:

	return dwVolume / GetChannelCount();
}


void CMIDI :: SetChannelVolume(DWORD dwChannel, DWORD dwPercent) {
	ASSERT(dwChannel < m_Volumes.size());

	if( !m_bPlaying )
		return;

	m_Volumes[dwChannel] = (dwPercent > 100) ? 100 : dwPercent;
	DWORD dwEvent = MIDI_CTRLCHANGE | dwChannel | ((DWORD)MIDICTRL_VOLUME << 8) | ((DWORD)(m_Volumes[dwChannel]*VOLUME_MAX/100) << 16);
	MMRESULT mmrRetVal;
	if(( mmrRetVal = midiOutShortMsg((HMIDIOUT)m_hStream, dwEvent)) != MMSYSERR_NOERROR ) {
		MidiError(mmrRetVal);
		return;
	}
}


DWORD CMIDI :: GetChannelVolume(DWORD dwChannel) const {
	ASSERT(dwChannel < GetChannelCount());
	return m_Volumes[dwChannel];
}


void CMIDI :: SetTempo(DWORD dwPercent) {
	m_dwTempoMultiplier = dwPercent ? dwPercent : 1;
	m_bInsertTempo = TRUE;
}


DWORD CMIDI :: GetTempo() const {
	return m_dwTempoMultiplier;
}


void CMIDI :: SetInfinitePlay(BOOL bSet) {
	m_bLooped = bSet;
}

//////////////////////////////////////////////////////////////////////
// CMIDI -- implementation
//////////////////////////////////////////////////////////////////////

// This function converts MIDI data from the track buffers setup by a
// previous call to ConverterInit().  It will convert data until an error is
// encountered or the output buffer has been filled with as much event data
// as possible, not to exceed dwMaxLength. This function can take a couple
// bit flags, passed through dwFlags. Information about the success/failure
// of this operation and the number of output bytes actually converted will
// be returned in the CONVERTINFO structure pointed at by lpciInfo.
int CMIDI :: ConvertToBuffer(DWORD dwFlags, CONVERTINFO * lpciInfo) {
	int	    nChkErr;

	lpciInfo->dwBytesRecorded = 0;

	if( dwFlags & CONVERTF_RESET ) {
		m_dwProgressBytes = 0;
		m_dwStatus = 0;
		memset( &m_teTemp, 0, sizeof(TEMPEVENT));
		m_ptsTrack = m_ptsFound = 0;
	}

	// If we were already done, then return with a warning...
	if( m_dwStatus & CONVERTF_STATUS_DONE ) {
		if( m_bLooped ) {
			Rewind();
			m_dwProgressBytes = 0;
			m_dwStatus = 0;
		} else
			return CONVERTERR_DONE;
	} else if( m_dwStatus & CONVERTF_STATUS_STUCK ) {
		// The caller is asking us to continue, but we're already hosed because we
		// previously identified something as corrupt, so complain louder this time.
		return( CONVERTERR_STUCK );
	} else if( m_dwStatus & CONVERTF_STATUS_GOTEVENT ) {
		// Turn off this bit flag
		m_dwStatus ^= CONVERTF_STATUS_GOTEVENT;

		// The following code for this case is duplicated from below, and is
		// designed to handle a "straggler" event, should we have one left over
		// from previous processing the last time this function was called.

		// Don't add end of track event 'til we're done
		if( m_teTemp.byShortData[0] == MIDI_META && m_teTemp.byShortData[1] == MIDI_META_EOT ) {
			if( m_dwMallocBlocks ) {
				delete [] m_teTemp.pLongData;
				--m_dwMallocBlocks;
			}
		} else if(( nChkErr = AddEventToStreamBuffer( &m_teTemp, lpciInfo )) != CONVERTERR_NOERROR ) {
			if( nChkErr == CONVERTERR_BUFFERFULL ) {
				// Do some processing and tell caller that this buffer's full
				m_dwStatus |= CONVERTF_STATUS_GOTEVENT;
				return CONVERTERR_NOERROR;
			} else if( nChkErr == CONVERTERR_METASKIP ) {
				// We skip by all meta events that aren't tempo changes...
			} else {
				TRACE0("Unable to add event to stream buffer.\n");
				if( m_dwMallocBlocks ) {
					delete [] m_teTemp.pLongData;
					m_dwMallocBlocks--;
				}
				return( TRUE );
			}
		}
	}

	for(;;) {
		m_ptsFound = 0;
		m_tkNext = 0xFFFFFFFFL;
		// Find nearest event due
		for( register DWORD idx = 0; idx < m_Tracks.size(); ++idx ) {
			m_ptsTrack = &m_Tracks[idx];
			if( !(m_ptsTrack->fdwTrack & ITS_F_ENDOFTRK) && (m_ptsTrack->tkNextEventDue < m_tkNext) ) {
				m_tkNext = m_ptsTrack->tkNextEventDue;
				m_ptsFound = m_ptsTrack;
			}
		}

		// None found?  We must be done, so return to the caller with a smile.
		if( !m_ptsFound ) {
			m_dwStatus |= CONVERTF_STATUS_DONE;
			// Need to set return buffer members properly
			return CONVERTERR_NOERROR;
		}

		// Ok, get the event header from that track
		if( !GetTrackEvent( m_ptsFound, &m_teTemp )) {
			// Warn future calls that this converter is stuck at a corrupt spot
			// and can't continue
			m_dwStatus |= CONVERTF_STATUS_STUCK;
			return CONVERTERR_CORRUPT;
		}

		// Don't add end of track event 'til we're done
		if( m_teTemp.byShortData[0] == MIDI_META && m_teTemp.byShortData[1] == MIDI_META_EOT ) {
			if( m_dwMallocBlocks ) {
				delete [] m_teTemp.pLongData;
				--m_dwMallocBlocks;
			}
			continue;
		}

		if(( nChkErr = AddEventToStreamBuffer( &m_teTemp, lpciInfo )) != CONVERTERR_NOERROR ) {
			if( nChkErr == CONVERTERR_BUFFERFULL ) {
				// Do some processing and tell somebody this buffer is full...
				m_dwStatus |= CONVERTF_STATUS_GOTEVENT;
				return CONVERTERR_NOERROR;
			} else if( nChkErr == CONVERTERR_METASKIP ) {
				// We skip by all meta events that aren't tempo changes...
			} else {
				TRACE0("Unable to add event to stream buffer.\n");
				if( m_dwMallocBlocks ) {
					delete [] m_teTemp.pLongData;
					m_dwMallocBlocks--;
				}
				return TRUE;
			}
		}
	}	

	return CONVERTERR_NOERROR;
}

// GetTrackEvent
//
// Fills in the event struct with the next event from the track
//
// pteTemp->tkEvent will contain the absolute tick time of the event
// pteTemp->byShortData[0] will contain
//  MIDI_META if the event is a meta event;
//   in this case pteTemp->byShortData[1] will contain the meta class
//  MIDI_SYSEX or MIDI_SYSEXEND if the event is a SysEx event
//  Otherwise, the event is a channel message and pteTemp->byShortData[1]
//   and pteTemp->byShortData[2] will contain the rest of the event.
//
// pteTemp->dwEventLength will contain
//  The total length of the channel message in pteTemp->byShortData if
//   the event is a channel message
//  The total length of the paramter data pointed to by
//   pteTemp->pLongData otherwise
//
// pteTemp->pLongData will point at any additional paramters if the 
//  event is a SysEx or meta event with non-zero length; else
//  it will contain NULL
//
// Returns TRUE on success or FALSE on any kind of parse error
// Prints its own error message ONLY in the debug version
//
// Maintains the state of the input track (i.e. 
// ptsTrack->pTrackPointers, and ptsTrack->byRunningStatus).
//
BOOL CMIDI :: GetTrackEvent(TRACK * ptsTrack, TEMPEVENT * pteTemp) {
	DWORD   idx;
	UINT    dwEventLength;

	// Clear out the temporary event structure to get rid of old data...
	memset( pteTemp, 0, sizeof(TEMPEVENT));

	// Already at end of track? There's nothing to read.
    if( ptsTrack->fdwTrack & ITS_F_ENDOFTRK )
		return FALSE;

	// Get the first byte, which determines the type of event.
	BYTE byByte;
	if( !GetTrackByte(ptsTrack, &byByte) )
		return FALSE;

	// If the high bit is not set, then this is a channel message
	// which uses the status byte from the last channel message
	// we saw. NOTE: We do not clear running status across SysEx or
	// meta events even though the spec says to because there are
	// actually files out there which contain that sequence of data.
	if( !(byByte & 0x80) ) {
		// No previous status byte? We're hosed.
		if( !ptsTrack->byRunningStatus ) {
			TrackError(ptsTrack, gteBadRunStat);
			return FALSE;
		}

		pteTemp->byShortData[0] = ptsTrack->byRunningStatus;
		pteTemp->byShortData[1] = byByte;

		byByte = pteTemp->byShortData[0] & 0xF0;
		pteTemp->dwEventLength = 2;

		// Only program change and channel pressure events are 2 bytes long;
		// the rest are 3 and need another byte
		if(( byByte != MIDI_PRGMCHANGE ) && ( byByte != MIDI_CHANPRESS )) {
			if( !GetTrackByte( ptsTrack, &pteTemp->byShortData[2] ))
				return FALSE;
			++pteTemp->dwEventLength;
		}
	} else if(( byByte & 0xF0 ) != MIDI_SYSEX ) {
		// Not running status, not in SysEx range - must be
		// normal channel message (0x80-0xEF)
		pteTemp->byShortData[0] = byByte;
		ptsTrack->byRunningStatus = byByte;

		// Strip off channel and just keep message type
		byByte &= 0xF0;

		dwEventLength = ( byByte == MIDI_PRGMCHANGE || byByte == MIDI_CHANPRESS ) ? 1 : 2;
		pteTemp->dwEventLength = dwEventLength + 1;

		if( !GetTrackByte( ptsTrack, &pteTemp->byShortData[1] ))
			return FALSE;
		if( dwEventLength == 2 )
			if( !GetTrackByte( ptsTrack, &pteTemp->byShortData[2] ))
				return FALSE;
	} else if(( byByte == MIDI_SYSEX ) || ( byByte == MIDI_SYSEXEND )) {
		// One of the SysEx types. (They are the same as far as we're concerned;
		// there is only a semantic difference in how the data would actually
		// get sent when the file is played. We must take care to put the proper
		// event type back on the output track, however.)
		//
		// Parse the general format of:
		//  BYTE 	bEvent (MIDI_SYSEX or MIDI_SYSEXEND)
		//  VDWORD 	cbParms
		//  BYTE   	abParms[cbParms]
		pteTemp->byShortData[0] = byByte;
		if( !GetTrackVDWord( ptsTrack, &pteTemp->dwEventLength )) {
			TrackError( ptsTrack, gteSysExLenTrunc );
			return FALSE;
		}

		// Malloc a temporary memory block to hold the parameter data
		pteTemp->pLongData = new BYTE [pteTemp->dwEventLength];
		if( pteTemp->pLongData == 0 ) {
			TrackError( ptsTrack, gteNoMem );
			return FALSE;
		}
		// Increment our counter, which tells the program to look around for
		// a malloc block to free, should it need to exit or reset before the
		// block would normally be freed
		++m_dwMallocBlocks;

		// Copy from the input buffer to the parameter data buffer
		for( idx = 0; idx < pteTemp->dwEventLength; idx++ )
			if( !GetTrackByte( ptsTrack, pteTemp->pLongData + idx )) {
				TrackError( ptsTrack, gteSysExTrunc );
				return FALSE;
			}
	} else if( byByte == MIDI_META ) {
		// It's a meta event. Parse the general form:
		//  BYTE	bEvent	(MIDI_META)
		//  BYTE	bClass
		//  VDWORD	cbParms
		//  BYTE	abParms[cbParms]
		pteTemp->byShortData[0] = byByte;

		if( !GetTrackByte( ptsTrack, &pteTemp->byShortData[1] ))
			return FALSE;

		if( !GetTrackVDWord( ptsTrack, &pteTemp->dwEventLength )) {	
			TrackError( ptsTrack, gteMetaLenTrunc );
			return FALSE;
		}

		// NOTE: It's perfectly valid to have a meta with no data
		// In this case, dwEventLength == 0 and pLongData == NULL
		if( pteTemp->dwEventLength ) {		
			// Malloc a temporary memory block to hold the parameter data
			pteTemp->pLongData = new BYTE [pteTemp->dwEventLength];
			if( pteTemp->pLongData == 0 ) {
				TrackError( ptsTrack, gteNoMem );
				return FALSE;
			}
			// Increment our counter, which tells the program to look around for
			// a malloc block to free, should it need to exit or reset before the
			// block would normally be freed
			++m_dwMallocBlocks;

			// Copy from the input buffer to the parameter data buffer
			for( idx = 0; idx < pteTemp->dwEventLength; idx++ )
				if( !GetTrackByte( ptsTrack, pteTemp->pLongData + idx )) {
					TrackError( ptsTrack, gteMetaTrunc );
					return FALSE;
				}
		}

		if( pteTemp->byShortData[1] == MIDI_META_EOT )
			ptsTrack->fdwTrack |= ITS_F_ENDOFTRK;
	} else {
		// Messages in this range are system messages and aren't supposed to
		// be in a normal MIDI file. If they are, we've either misparsed or the
		// authoring software is stupid.
		return FALSE;
	}

	// Event time was already stored as the current track time
	pteTemp->tkEvent = ptsTrack->tkNextEventDue;

	// Now update to the next event time. The code above MUST properly
	// maintain the end of track flag in case the end of track meta is
	// missing.  NOTE: This code is a continuation of the track event
	// time pre-read which is done at the end of track initialization.
	if( !( ptsTrack->fdwTrack & ITS_F_ENDOFTRK )) {
		DWORD	tkDelta;

		if( !GetTrackVDWord( ptsTrack, &tkDelta ))
			return FALSE;

		ptsTrack->tkNextEventDue += tkDelta;
	}

	return TRUE;
}


// GetTrackVDWord
//
// Attempts to parse a variable length DWORD from the given track. A VDWord
// in a MIDI file
//  (a) is in lo-hi format 
//  (b) has the high bit set on every byte except the last
//
// Returns the DWORD in *lpdw and TRUE on success; else
// FALSE if we hit end of track first.
BOOL CMIDI :: GetTrackVDWord(TRACK * ptsTrack, LPDWORD lpdw) {
	ASSERT(ptsTrack != 0);
	ASSERT(lpdw != 0);

	if( ptsTrack->fdwTrack & ITS_F_ENDOFTRK )
		return FALSE;

	BYTE	byByte;
	DWORD	dw = 0;

	do {
		if( !GetTrackByte( ptsTrack, &byByte ))
			return FALSE;

		dw = ( dw << 7 ) | ( byByte & 0x7F );
	} while( byByte & 0x80 );

	*lpdw = dw;

	return TRUE;
}


// AddEventToStreamBuffer
//
// Put the given event into the given stream buffer at the given location
// pteTemp must point to an event filled out in accordance with the
// description given in GetTrackEvent
//
// Handles its own error notification by displaying to the appropriate
// output device (either our debugging window, or the screen).
int CMIDI :: AddEventToStreamBuffer( TEMPEVENT * pteTemp, CONVERTINFO *lpciInfo ) {
	MIDIEVENT * pmeEvent = (MIDIEVENT *)( lpciInfo->mhBuffer.lpData
							+ lpciInfo->dwStartOffset

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
午夜视频久久久久久| 精品国产三级电影在线观看| 中文字幕在线观看一区| 国产suv精品一区二区883| 欧美高清在线一区二区| 本田岬高潮一区二区三区| 国产精品日韩精品欧美在线| 成人av动漫网站| 一区二区在线看| 欧美日韩免费高清一区色橹橹| 一区二区三区在线观看欧美| 欧美日韩精品免费观看视频| 天天做天天摸天天爽国产一区| 欧美日本在线一区| 久久福利视频一区二区| 国产欧美视频一区二区| av欧美精品.com| 亚洲成人在线免费| 久久久亚洲精品一区二区三区| 不卡视频一二三| 天天综合网 天天综合色| 精品处破学生在线二十三| 成人动漫一区二区在线| 亚洲精品日韩一| 日韩欧美高清在线| 不卡av免费在线观看| 午夜精品久久久久久久久久久| 久久免费精品国产久精品久久久久| www.视频一区| 天天影视网天天综合色在线播放| 久久精品免视看| 欧美性猛交xxxx乱大交退制版| 奇米在线7777在线精品| 日本一区二区不卡视频| 欧美人伦禁忌dvd放荡欲情| 国产一区二区精品久久99| 亚洲精品高清在线观看| 精品国产髙清在线看国产毛片| 99久久99久久免费精品蜜臀| 日韩精品亚洲一区二区三区免费| 国产日韩欧美电影| 欧美日韩国产三级| 成人美女在线观看| 免费在线成人网| 午夜久久久影院| 欧美极品xxx| 精品少妇一区二区三区在线视频 | 欧美性欧美巨大黑白大战| 麻豆久久一区二区| 一区二区三区日韩在线观看| 久久久精品日韩欧美| 欧美三级日本三级少妇99| 国产一区在线不卡| 午夜精品久久久久久久蜜桃app| 国产精品国产三级国产aⅴ入口| 日韩欧美成人午夜| 欧美午夜寂寞影院| 成人免费毛片片v| 极品少妇xxxx偷拍精品少妇| 亚洲成人动漫在线观看| 中文字幕一区二区三区蜜月| 精品国精品自拍自在线| 在线免费观看日本一区| 不卡av在线网| 国产成人精品亚洲午夜麻豆| 日韩精品欧美精品| 亚洲国产美女搞黄色| 国产精品国产三级国产aⅴ中文| 久久综合av免费| 欧美mv日韩mv国产| 欧美成人激情免费网| 777欧美精品| 欧美亚洲一区二区在线观看| av在线不卡电影| 99久久精品国产精品久久| 国产mv日韩mv欧美| 成人伦理片在线| 高清成人免费视频| 成人一二三区视频| 不卡视频一二三| 91在线视频免费91| 91浏览器入口在线观看| 色综合一个色综合亚洲| 在线中文字幕一区| 欧洲激情一区二区| 色欧美日韩亚洲| 日本精品视频一区二区三区| 色婷婷国产精品| 欧美日韩久久不卡| 欧美日韩一区二区电影| 91精品国产综合久久福利| 欧美电影影音先锋| 欧美r级电影在线观看| 精品国产一区二区三区av性色| 精品国产电影一区二区| 中文字幕久久午夜不卡| 国产精品狼人久久影院观看方式| 亚洲色欲色欲www| 亚洲综合无码一区二区| 亚洲成人先锋电影| 激情深爱一区二区| 成人免费三级在线| 在线精品视频一区二区三四| 欧美一区二区三区免费| 久久久不卡网国产精品二区 | 国产精品视频一二| 亚洲精品国产一区二区精华液| 天天色 色综合| 国产精品一区二区x88av| jizz一区二区| 欧美特级限制片免费在线观看| 日韩免费电影一区| 一区免费观看视频| 日韩精品一级中文字幕精品视频免费观看 | 国产偷国产偷精品高清尤物| 国产精品欧美久久久久无广告| 一区二区三区视频在线看| 美女免费视频一区二区| 国产成人精品一区二区三区四区| 一本大道av伊人久久综合| 欧美一区二区在线免费播放 | 国产精品国产成人国产三级 | 亚洲精品日产精品乱码不卡| 久久精品国产精品亚洲精品| 成人免费看的视频| 欧美日韩精品一区二区三区| 久久久激情视频| 午夜精品免费在线| 成人h动漫精品一区二区| 欧美日韩国产中文| 国产日韩欧美一区二区三区乱码 | 美日韩一区二区| 99vv1com这只有精品| 日韩欧美综合在线| 亚洲欧美日韩人成在线播放| 精品一区二区三区在线观看| 一本一道综合狠狠老| 久久一夜天堂av一区二区三区| 亚洲蜜臀av乱码久久精品| 理论电影国产精品| 欧美日韩亚洲综合| 国产精品美女久久久久高潮| 免费观看久久久4p| 色婷婷亚洲一区二区三区| 国产亚洲综合性久久久影院| 亚洲成人动漫在线免费观看| k8久久久一区二区三区| 精品少妇一区二区三区日产乱码 | 欧美福利视频一区| 自拍偷拍欧美激情| 国产精华液一区二区三区| 欧美一区二区在线免费观看| 一区二区免费视频| 97久久超碰国产精品电影| 精品国产网站在线观看| 五月激情综合网| 欧美中文字幕一区二区三区| 欧美国产丝袜视频| 国产成人啪免费观看软件| 欧美成人国产一区二区| 免费观看成人av| 日韩一区二区三| 蜜臀av一级做a爰片久久| 欧美色精品天天在线观看视频| 亚洲精选免费视频| 99免费精品视频| 国产精品久久二区二区| 丁香婷婷深情五月亚洲| 久久久久综合网| 国产激情精品久久久第一区二区| 欧美xxxxx牲另类人与| 人人狠狠综合久久亚洲| 欧美老女人在线| 日韩av成人高清| 欧美tickling挠脚心丨vk| 久久成人久久爱| 2014亚洲片线观看视频免费| 国产最新精品免费| 久久久激情视频| 成人亚洲一区二区一| 日韩一区日韩二区| 色欧美片视频在线观看 | 国产精品天干天干在观线| 国产91精品在线观看| 中文字幕av资源一区| 99久久777色| 亚洲国产一区二区在线播放| 欧美日韩亚洲丝袜制服| 免费欧美日韩国产三级电影| 久久综合色8888| 成人精品视频.| 一区二区三区日韩在线观看| 91精品国产综合久久久久久 | 色综合久久综合网97色综合 | 国产精品自拍在线| 国产欧美1区2区3区| 色综合天天综合给合国产| 亚洲大片免费看| 久久亚洲二区三区| 91精品91久久久中77777|