詳しく説明しますと、
①カメラの画像からある特徴量を得る。
②特徴量を用いて、音声出力に反映する。(例えば、画像の輝度値を用いて音声のボリュームを変える。)
③音声出力
以上の①~③をループさせたいのです。
しかし、今のままだと、下記のソースコード100行目~122行目のループ内にある110行目のPlayPCM関数219行目~230行目(この関数は、MicrosoftのWindows DirectX SDK内であったものを使っています。)でループしてしまいます。
音声を出力しながら、他の処理をするプログラム(例えばゲームなどはそうだとおもうのですが)は、一般的にどう作ればよいのでしょうか。
詳しい方、教えていただけでしょうか。
よろしくお願いします。
#pragma comment(lib, "winmm.lib")
#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#include <xaudio2.h>
#include <strsafe.h>
#include <shellapi.h>
#include <mmsystem.h>
#include <conio.h>
#include "SDKwavefile.h"
#include <vector>
#include <cmath>
#include <iostream>
#include <time.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
//--------------------------------------------------------------------------------------
// Helper macros
//--------------------------------------------------------------------------------------
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
#endif
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#endif
//-----------------------------------------------------------------
// Global Variables.
//-----------------------------------------------------------------
#define WIDTH 640
#define HEIGHT 480
IXAudio2* pXAudio2 = NULL;
IXAudio2MasteringVoice* pMasteringVoice = NULL;
//-----------------------------------------------------------------
// Prototypes.
//-----------------------------------------------------------------
unsigned char getPixel(IplImage *image, int x, int y, int index);
int getFeature(IplImage *img);
HRESULT PlayPCM( IXAudio2* pXaudio2, LPCWSTR szFilename );
HRESULT FindMediaFileCch( WCHAR* strDestPath, int cchDest, LPCWSTR strFilename );
//-----------------------------------------------------------------
// Main.
//-----------------------------------------------------------------
int main()
{
//画像処理
CvCapture *capture = cvCreateCameraCapture(0);
CvSize size = cvSize(WIDTH, HEIGHT);
IplImage *sourceImage = cvCreateImage(size, IPL_DEPTH_8U,3);
IplImage *grayImage = cvCreateImage(size, IPL_DEPTH_8U,1);
IplImage *grayLastImage = cvCreateImage(size, IPL_DEPTH_8U,1);
IplImage *TimeSubImage = cvCreateImage(size, IPL_DEPTH_8U,1);
char windowNameCapture[] = "Capture";
cvNamedWindow(windowNameCapture, CV_WINDOW_AUTOSIZE);
//音声処理
HRESULT hr;
//*********初期化***************
CoInitializeEx( NULL, COINIT_MULTITHREADED );
UINT32 flags = 0;
#ifdef _DEBUG
flags |= XAUDIO2_DEBUG_ENGINE;
#endif
//**********XAudio2作成**************
if( FAILED( hr = XAudio2Create( &pXAudio2, flags ) ) )
{
wprintf( L"Failed to init XAudio2 engine: %#X\n", hr );
CoUninitialize();
return 0;
}
//**********マスタリングボイスの作成*************
if( FAILED( hr = pXAudio2->CreateMasteringVoice( &pMasteringVoice ) ) )
{
wprintf( L"Failed creating mastering voice: %#X\n", hr );
SAFE_RELEASE( pXAudio2 );
CoUninitialize();
return 0;
}
while (1)
{
sourceImage = cvQueryFrame(capture);
cvFlip(sourceImage,sourceImage,0);//画面反転
cvCvtColor(sourceImage, grayImage, CV_BGR2GRAY); // グレースケールへ変換
cvAbsDiff(grayImage, grayLastImage, TimeSubImage);//フレーム間差分
cvThreshold(TimeSubImage, TimeSubImage, 30, 255, CV_THRESH_BINARY); //2値化処理(閾値10)
cvShowImage(windowNameCapture, TimeSubImage);
//*********** WAV再生 **************************
if( FAILED( hr = PlayPCM( pXAudio2, L"flute1.wav" ) ) )
{
wprintf( L"Failed creating source voice: %#X\n", hr );
SAFE_RELEASE( pXAudio2 );
CoUninitialize();
return 0;
}
if (cvWaitKey(33) == 'q') break;
cvCopy(grayImage, grayLastImage);
}
//リソースを開放
cvReleaseCapture(&capture);
cvReleaseImage(&grayImage);
cvReleaseImage(&grayLastImage);
cvReleaseImage(&TimeSubImage);
cvDestroyWindow(windowNameCapture);
// All XAudio2 interfaces are released when the engine is destroyed, but being tidy
//**********終了処理*************
pMasteringVoice->DestroyVoice();
SAFE_RELEASE( pXAudio2 );
CoUninitialize();
return 0;
}
//--------------------------------------------------------------------------------------
// Name: PlayPCM
// Desc: Plays a wave and blocks until the wave finishes playing
//--------------------------------------------------------------------------------------
HRESULT PlayPCM( IXAudio2* pXaudio2, LPCWSTR szFilename )
{
HRESULT hr = S_OK;
//
// Locate the wave file
//
WCHAR strFilePath[MAX_PATH];
if( FAILED( hr = FindMediaFileCch( strFilePath, MAX_PATH, szFilename ) ) )
{
wprintf( L"Failed to find media file: %s\n", szFilename );
return hr;
}
//
// Read in the wave file
//
CWaveFile wav;
if( FAILED( hr = wav.Open( strFilePath, NULL, WAVEFILE_READ ) ) )
{
wprintf( L"Failed reading WAV file: %#X (%s)\n", hr, strFilePath );
return hr;
}
// Get format of wave file
WAVEFORMATEX* pwfx = wav.GetFormat();
// Calculate how many bytes and samples are in the wave
DWORD cbWaveSize = wav.GetSize();
// Read the sample data into memory
BYTE* pbWaveData = new BYTE[ cbWaveSize ];
if( FAILED( hr = wav.Read( pbWaveData, cbWaveSize, &cbWaveSize ) ) )
{
wprintf( L"Failed to read WAV data: %#X\n", hr );
SAFE_DELETE_ARRAY( pbWaveData );
return hr;
}
//
// Play the wave using a XAudio2SourceVoice
//
// Create the source voice
IXAudio2SourceVoice* pSourceVoice;
if( FAILED( hr = pXaudio2->CreateSourceVoice( &pSourceVoice, pwfx ) ) )
{
wprintf( L"Error %#X creating source voice\n", hr );
SAFE_DELETE_ARRAY( pbWaveData );
return hr;
}
// Submit the wave sample data using an XAUDIO2_BUFFER structure
XAUDIO2_BUFFER buffer = {0};
buffer.pAudioData = pbWaveData;
buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer
buffer.LoopCount = XAUDIO2_LOOP_INFINITE;//繰り返しの再生回数
buffer.AudioBytes = cbWaveSize;
if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) )
{
wprintf( L"Error %#X submitting source buffer\n", hr );
pSourceVoice->DestroyVoice();
SAFE_DELETE_ARRAY( pbWaveData );
return hr;
}
hr = pSourceVoice->Start( 0 );
// Let the sound play
BOOL isRunning = TRUE;
while( SUCCEEDED( hr ) && isRunning )
{
XAUDIO2_VOICE_STATE state;
pSourceVoice->GetState( &state );
isRunning = ( state.BuffersQueued > 0 ) != 0;
// Wait till the escape key is pressed
if( GetAsyncKeyState( VK_ESCAPE ) )
break;
Sleep( 10 );
}
// Wait till the escape key is released
while( GetAsyncKeyState( VK_ESCAPE ) )
Sleep( 10 );
pSourceVoice->DestroyVoice();
SAFE_DELETE_ARRAY( pbWaveData );
return hr;
}
//--------------------------------------------------------------------------------------
// Helper function to try to find the location of a media file
//--------------------------------------------------------------------------------------
HRESULT FindMediaFileCch( WCHAR* strDestPath, int cchDest, LPCWSTR strFilename )
{
bool bFound = false;
if( NULL == strFilename || strFilename[0] == 0 || NULL == strDestPath || cchDest < 10 )
return E_INVALIDARG;
// Get the exe name, and exe path
WCHAR strExePath[MAX_PATH] = {0};
WCHAR strExeName[MAX_PATH] = {0};
WCHAR* strLastSlash = NULL;
GetModuleFileName( NULL, strExePath, MAX_PATH );
strExePath[MAX_PATH - 1] = 0;
strLastSlash = wcsrchr( strExePath, TEXT( '\\' ) );
if( strLastSlash )
{
wcscpy_s( strExeName, MAX_PATH, &strLastSlash[1] );
// Chop the exe name from the exe path
*strLastSlash = 0;
// Chop the .exe from the exe name
strLastSlash = wcsrchr( strExeName, TEXT( '.' ) );
if( strLastSlash )
*strLastSlash = 0;
}
wcscpy_s( strDestPath, cchDest, strFilename );
if( GetFileAttributes( strDestPath ) != 0xFFFFFFFF )
return S_OK;
// Search all parent directories starting at .\ and using strFilename as the leaf name
WCHAR strLeafName[MAX_PATH] = {0};
wcscpy_s( strLeafName, MAX_PATH, strFilename );
WCHAR strFullPath[MAX_PATH] = {0};
WCHAR strFullFileName[MAX_PATH] = {0};
WCHAR strSearch[MAX_PATH] = {0};
WCHAR* strFilePart = NULL;
GetFullPathName( L".", MAX_PATH, strFullPath, &strFilePart );
if( strFilePart == NULL )
return E_FAIL;
while( strFilePart != NULL && *strFilePart != '\0' )
{
swprintf_s( strFullFileName, MAX_PATH, L"%s\\%s", strFullPath, strLeafName );
if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF )
{
wcscpy_s( strDestPath, cchDest, strFullFileName );
bFound = true;
break;
}
swprintf_s( strFullFileName, MAX_PATH, L"%s\\%s\\%s", strFullPath, strExeName, strLeafName );
if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF )
{
wcscpy_s( strDestPath, cchDest, strFullFileName );
bFound = true;
break;
}
swprintf_s( strSearch, MAX_PATH, L"%s\\..", strFullPath );
GetFullPathName( strSearch, MAX_PATH, strFullPath, &strFilePart );
}
if( bFound )
return S_OK;
// On failure, return the file as the path but also return an error code
wcscpy_s( strDestPath, cchDest, strFilename );
return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
}