描画ができたら次は音を再生したいと思うのが自然な流れです
サウンドを扱う場合は「winmm.lib」をリンクさせる必要があります

#pragma comment(lib,"winmm.lib") 

ただ鳴らすだけなら
PlaySound関数一行で鳴らせますが・・・

PlaySound(WAVEファイル名, NULL, SND_FILENAME | SND_ASYNC);

ファイルの読み込みを毎回行うせいで遅い上
Waveファイル(.wav)しか読めません
細かい制御も利きません

細かい制御やmp3やAVIなどのマルチメディアを取り扱うには
MCI(Media Control Interface / Multimedia Control Interface)を使います
今回はメディアをオブジェクトとして扱いため、クラス化しています
今回以降はクラスを積極的に使っていく(というか使わざるを得ない)ので
不安な人はC++のクラスを勉強してください
すでに講座も作ってあります

今回は3つのコードファイルが必要です
・MCI.h
・MCI.cpp
・main.cpp


MCI.hです
WAV,MP3,MIDI,CD_AUDIO,AVI
の読み込みと再生、停止などを扱うことができます

	//--------------------------------------------//
	//	ファイル名:MCI.h
	//	概要:	音ファイル再生関係
	//
	//	作成者:Daiki Terai
	//	作成日:2010/10/23
	//	修正履歴:
	//--------------------------------------------//
	#ifndef _MCI_H_
	#define _MCI_H_

	#include <windows.h>
	#include <tchar.h>
	#pragma comment(lib, "winmm.lib") 

	// メディアタイプ
	enum EMEDIA
	{
		WAVE,
		MIDI,
		MP3,
		CD_AUDIO,
		AVI
	};

	// MCIクラス
	class CMCI
	{
	private:
		MCIDEVICEID		m_ID;	// ID
	public:
		CMCI();
		virtual ~CMCI();

		// メディアを開く
		bool Open(const TCHAR* FileName,EMEDIA Media);

		//-------------------------------------------------------------------//
		//	再生
		//	ループ再生するときは通知メッセージ処理するので
		//	ウィンドウハンドルを渡すこと
		//
		//	引数:	bLoop	ループ再生フラグ
		//			hWnd	処理終了通知メッセージを受け取るウィンドウハンドル
		//-------------------------------------------------------------------//
		void Play(bool bLoop = false,HWND hWnd = NULL);
		// 停止
		void Stop();
		// 巻き戻し
		void Rewind();
		// 一時停止
		void Pause();
		// 一時停止解除
		void Resume();

		// 現在位置取得
		DWORD GetPos();
		// 再生時間取得
		DWORD GetLength();

		// 閉じる
		void Close();
	};
	#endif

MCI.cppです
ファイルオープン、(ループ)再生、停止などの基本的な機能の実装をしています

       // MCI.cpp
	#define _CRT_SECURE_NO_WARNINGS // 警告抑制用
	#define _CRT_NON_CONFORMING_SWPRINTFS // 警告抑制用
	#include "MCI.h"

	CMCI::CMCI():m_ID(0)
	{}
	CMCI::~CMCI(){
		this->Stop();
		this->Close();
	}

	// メディアを開く
	bool CMCI::Open(const TCHAR* FileName,EMEDIA Media){
		
		MCI_OPEN_PARMS	MCIOpen = {};		// 開く用
		switch(Media){
			case WAVE:
				{
					MCIOpen.lpstrDeviceType = _T("WaveAudio");
					break;
				}
			case MIDI:
				{
					MCIOpen.lpstrDeviceType = _T("Sequencer");
					break;
				}
			case MP3:
				{
					MCIOpen.lpstrDeviceType = _T("MPEGVideo");
					break;
				}
			case CD_AUDIO:
				{
					MCIOpen.lpstrDeviceType = _T("CDAudio");
					break;
				}
			case AVI:
				{
					MCIOpen.lpstrDeviceType = _T("avivideo");
					break;
				}
		}
		MCIOpen.lpstrElementName = FileName;
		if(mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD_PTR)&MCIOpen) != 0){
			TCHAR Buf[MAX_PATH] = {};
			_stprintf(Buf,_T("%sが開けませんでした"),FileName);
			MessageBox(NULL,Buf,NULL,MB_OK);
			return false;
		}
		m_ID = MCIOpen.wDeviceID;
		
		// ミリ秒単位に設定
		MCI_SET_PARMS	MCISet = {};		
		MCISet.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
		mciSendCommand(m_ID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&MCISet);

		return true;
	}

	//-------------------------------------------------------------------//
	//	再生
	//	ループ再生するときは通知メッセージ処理するので
	//	ウィンドウハンドルを渡すこと
	//
	//	引数:	bLoop	ループ再生フラグ
	//			hWnd	処理終了通知メッセージを受け取るウィンドウハンドル
	//-------------------------------------------------------------------//
	void CMCI::Play(bool bLoop,HWND hWnd)
	{
		if(bLoop){
			MCI_PLAY_PARMS	MCIPlay = {};		// MCI再生設定
			MCIPlay.dwCallback = (DWORD_PTR)hWnd;// MM_NOTIFYメッセージを受け取るウィンドウ
			mciSendCommand(m_ID,MCI_PLAY, MCI_NOTIFY,(DWORD_PTR)&MCIPlay);
		}
		else{
			mciSendCommand(m_ID,MCI_PLAY, 0,0);
		}
	}
	// 停止
	void CMCI::Stop(){
		mciSendCommand(m_ID,MCI_STOP,0,0);
	}
	// 巻き戻し
	void CMCI::Rewind(){
		mciSendCommand(m_ID,MCI_SEEK,MCI_SEEK_TO_START,0);
	}
	// 一時停止
	void CMCI::Pause(){
		mciSendCommand(m_ID,MCI_PAUSE,0,0);
	}
	// 一時停止解除
	void CMCI::Resume(){
		mciSendCommand(m_ID,MCI_RESUME,0,0);
	}
	// 閉じる
	void CMCI::Close(){
		MCI_GENERIC_PARMS	MCIGeneric = {};	// データ
		mciSendCommand( m_ID, MCI_CLOSE, 0, (DWORD_PTR)&MCIGeneric);
	}

MCIを制御するにはmciSendCommand関数を使います

MCIERROR mciSendCommand(
  MCIDEVICEID IDDevice,  // デバイス識別子
  UINT uMsg,             // コマンドメッセージ
  DWORD fdwCommand,      // フラグ
  DWORD dwParam          // パラメータを保持している構造体
);

デバイス識別子というのはメディアのIDのことです
コマンドメッセージはMCIの処理の種類を決めます
MCI_OPENを指定するとメディアを開きます
MCI_PLAYを指定するとメディアを再生します
MCI_STOPを指定するとメディアを停止します
MCI_SEEKを指定するとメディアのシークバー位置を変更します
MCI_PAUSEを指定するとメディアを一時停止します
MCI_RESUMEを指定するとメディアの一時停止を解除します
フラグはコマンドメッセージによって異なります
パラメータ構造体もコマンドメッセージによって異なります

メディアを開くには
MCI_OPEN_PARMS構造体を使います
lpstrDeviceTypeには開くメディアのタイプを文字列で指定します
lpstrElementNameにはファイル名を指定します
実際にメディアを開いているのはこの箇所です

		if(mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD_PTR)&MCIOpen) != 0){
			TCHAR Buf[MAX_PATH] = {};
			_stprintf(Buf,_T("%sが開けませんでした"),FileName);
			MessageBox(NULL,Buf,NULL,MB_OK);
			return false;
		}

オープンに成功したら一意なIDが
wDeviceIDに格納されています
このIDは再生、停止などの制御に使うので覚えておきます

m_ID = MCIOpen.wDeviceID;

時間の単位をミリ秒に設定します
特に設定しなくても再生などはできますが設定すると制御がしやすくなります

// ミリ秒単位に設定
MCI_SET_PARMS	MCISet = {};		
MCISet.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
mciSendCommand(m_ID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&MCISet);

再生箇所は次のようになっています

//-------------------------------------------------------------------//
//	再生
//	ループ再生するときは通知メッセージ処理するので
//	ウィンドウハンドルを渡すこと
//
//	引数:	bLoop	ループ再生フラグ
//			hWnd	処理終了通知メッセージを受け取るウィンドウハンドル
//-------------------------------------------------------------------//
void CMCI::Play(bool bLoop,HWND hWnd)
{
	if(bLoop){
		MCI_PLAY_PARMS	MCIPlay = {};		// MCI再生設定
		MCIPlay.dwCallback = (DWORD_PTR)hWnd;// MM_NOTIFYメッセージを受け取るウィンドウ
		mciSendCommand(m_ID,MCI_PLAY, MCI_NOTIFY,(DWORD_PTR)&MCIPlay);
	}
	else{
		mciSendCommand(m_ID,MCI_PLAY, 0,0);
	}
}

ここでループ再生させるときは、ウィンドウにメディアの再生が終了したときを知らせなければなりません
MCI_PLAY_PARMS構造体のdwCallbackに処理終了メッセージを受け取るウィンドウのハンドルを指定します


main.cppです
メインコードに自作のMCI.hをインクルードさせる必要があります
また、CMCIクラス変数もグローバル変数として作成しておきましょう
(本当はグローバル変数は使いたくないんですが・・・
ウィンドウをクラス化すればこの問題は解決できます)

#include "MCI.h"
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#pragma comment(lib,"comctl32.lib")
#pragma comment(lib,"winmm.lib") 

// MCI
CMCI g_Media[2];

メッセージ処理部分です

	//------------------------------------------------------//
	//	ウィンドウ作成メッセージ処理
	//
	//	引数:	hWnd			ウィンドウハンドル
	//			lpCreateStruct	ウィンドウ作成情報
	//------------------------------------------------------//
	BOOL OnCreate(HWND hWnd,LPCREATESTRUCT lpCreateStruct){
		g_Media[0].Open(_T("あぶないおにいちゃんです.mp3"),MP3);
		g_Media[1].Open(_T("ゆっくりしていってね.wav"),WAVE);
		g_Media[0].Play(true,hWnd);
		g_Media[1].Play();
		return TRUE;
	}

	//------------------------------------------------------//
	//	ウィンドウ破棄メッセージ処理
	//
	//	引数:	hWnd	ウィンドウハンドル
	//------------------------------------------------------//
	void OnDestroy(HWND hWnd){
		PostQuitMessage(0); 
	}

	//-----------------------------------------------------//
	//	ウィンドウプロシージャ
	//	デフォルトの処理はDefWindowProc関数で行う
	//
	//	引数:	hWnd	ウィンドウハンドル
	//			msg		メッセージ
	//			wParam	パラメータ
	//			lParam	パラメータ
	//
	//	戻り値:処理結果
	//-----------------------------------------------------//
	LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
	
		switch(msg){
			HANDLE_MSG(hWnd,WM_CREATE,OnCreate);
 
			// MCI処理終了通知メッセージ
			case MM_MCINOTIFY:{ 
				MCI_PLAY_PARMS mciPlay;
				// 通知メッセージ失敗
				if (wParam != MCI_NOTIFY_SUCCESSFUL)
					return 0;
				
				// 初期位置に戻す
				mciSendCommand((MCIDEVICEID)lParam, MCI_SEEK, MCI_SEEK_TO_START, 0);
				mciPlay.dwCallback = (DWORD_PTR)hWnd;
				// ループ再生
				mciSendCommand((MCIDEVICEID)lParam, MCI_PLAY, MCI_NOTIFY, (DWORD_PTR)&mciPlay);
				return 0;
			}
			HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy);
		}
		return DefWindowProc(hWnd, msg, wParam, lParam);
	}

ウィンドウ作成時にWM_CREATEというメッセージが1度だけ送られてきます
ウィンドウに依存する変数の初期化などの処理を行います
メッセージクラッカーでOnCreate関数で初期化処理をします

	HANDLE_MSG(hWnd,WM_CREATE,OnCreate);

今回は初期化時にメディアをオープンし、再生してます
Openメソッドの第2引数は、適切なメディアタイプを指定してください。MCI.hで定義しています
ループ再生にはPlayメソッドに、ウィンドウハンドルを渡す必要があります

	g_Media[0].Open(_T("あぶないおにいちゃんです.mp3"),MP3);
	g_Media[1].Open(_T("ゆっくりしていってね.wav"),WAVE);
	g_Media[0].Play(true,hWnd);
	g_Media[1].Play();

再生終了したときループ再生フラグを立てているメディアには
MM_MCINOTIFYメッセージが送られてきます
これに関してはメッセージクラッカーは用意されていないので
ウィンドウプロシージャで直接処理しています
ループ処理自体はシークバー位置を初期位置に戻し
再び再生終了時にMM_MCINOTIFYメッセージを送ることで無限に再生ループをつくっています

	// MCI処理終了通知メッセージ
	case MM_MCINOTIFY:{ 
		MCI_PLAY_PARMS mciPlay;
		// 通知メッセージ失敗
		if (wParam != MCI_NOTIFY_SUCCESSFUL)
			return 0;
				
		// 初期位置に戻す
		mciSendCommand((MCIDEVICEID)lParam, MCI_SEEK, MCI_SEEK_TO_START, 0);
		mciPlay.dwCallback = (DWORD_PTR)hWnd;
		// ループ再生
		mciSendCommand((MCIDEVICEID)lParam, MCI_PLAY, MCI_NOTIFY, (DWORD_PTR)&mciPlay);
		return 0;
	}
	

全ソースコードと音ファイルは下からダウンロードしてください
filemain.zip

ソースファイルと音ファイルは
作成したプロジェクトと同じ場所においてください

(^ω^)やったお8
何これwww意味不すぎwww8
。(`ω´#)。あぁん?最近、だらしねぇな3

添付ファイル: filemain.zip 737件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2017-09-06 (水) 17:46:47