Microsoft Visual C++ 2012 Express Direct3D 11.0 Kinect for Windows SDK v1.7 DirectXTex texture processing library |
■Kinect 音源の取得 | Prev Top Next |
関連ページ:Direct3D 自作の共通ライブラリ |
UCommon.h | 共通で使用するヘッダファイル |
UException.h | 例外処理クラスのヘッダファイル |
UDirect3D11.h | Direct3Dクラスのヘッダーファイル |
UDirect3D11.cpp | Direct3Dクラスのソースファイル |
UGraphicsPipeline.h | グラフィックパイプラインクラスのヘッダーファイル |
UGraphicsPipeline.cpp | グラフィックパイプラインクラスのソースファイル |
UMesh.h | メッシュの抽象クラスのヘッダーファイル |
UMesh.cpp | メッシュの抽象クラスのソースファイル |
UDDSLoader.h | DDSファイルをロードしてシェーダーリソースビューを作成するサンプルクラスのヘッダファイル。 R8G8B8A8またはR8G8B8X8のみサポートし、ミップマップ、キューブマップ、ボリュームマップは未対応。 |
UDDSLoader.cpp | DDSファイルをロードしてシェーダーリソースビューを作成するサンプルクラスのソースファイル。 |
UDebugFont.h | デバッグ用のテキストを画面上に表示するためのクラスのヘッダファイル。 |
UDebugFont.cpp | デバッグ用のテキストを画面上に表示するためのクラスのソースファイル。 |
UStaticMediaBuffer.h | IMediaBufferインターフェースを継承する音声入力バッファを保持するクラスのヘッダーファイル。 既出。 |
UKinect07.h | Kinectクラスのヘッダーファイル。既出。 |
UKinect07.cpp | Kinectクラスのソースファイル。既出。 |
UKinectAudio08.h | 音源の取得処理を追加したクラスのヘッダーファイル。 |
UKinectAudio08.cpp | 音源の取得処理を追加したクラスのソースファイル。 |
main.cpp | main関数のソースファイル |
#ifndef KINECTAUDIO08_H #define KINECTAUDIO08_H #include "../../Common/Header/UCommon.h" #include "../../Common/Header/UException.h" #include "UStaticMediaBuffer.h" // INuiAudioBeam #include <NuiApi.h> // IPropertyStore #include <mfapi.h> // WAVEFORMATEXのGUID #include <uuids.h> // MFPKEY_WMAAECMA_SYSTEM_MODE #include <Wmcodecdsp.h> #pragma comment( lib, "Kinect10.lib" ) #pragma comment( lib, "dmoguids.lib" ) #pragma comment( lib, "amstrmid.lib" ) #pragma comment( lib, "Msdmo.lib") class UCKinectAudio08 { private: // 音源の位置と方向を提供する INuiAudioBeam* m_pAudioBeam; // Microsoft DirectX Media Object (DMO) を操作するためのメソッドを提供する IMediaObject* m_pMediaObject; // プロパティを設定するための機能を提供する IPropertyStore* m_pPropertyStore; void GetWaveFormat( WAVEFORMATEX* pFormat ); public: // エコーキャンセラ( AEC ) // 電気信号や音声の出力が入力機器に拾われてエコーやハウリングを起こすのを防止する機器や技術。 // マイクロホンアレイ // 複数のマイクロホンから音声入力を行う。複数のマイクロホンを使用することで音源方向を推定することができる。 // エコーキャンセラとマイクロホンアレイの設定モード enum class AEC_SYSTEM_MODE { SINGLE_CHANNEL_AEC = 0, // エコーキャンセラ( AEC )のみ処理 OPTIBEAM_ARRAY_ONLY = 2, // マイクロホンアレイのみ処理 OPTIBEAM_ARRAY_AND_AEC = 4, // マイクロホンアレー処理とAEC処理 SINGLE_CHANNEL_NSAGC = 5, // マイクロホンアレーなしとAECなし }; // IMediaBufferを継承するバッファ UCStaticMediaBuffer m_StaticMediaBuffer; public: UCKinectAudio08(); ~UCKinectAudio08(); void Invalidate(); void CreateKinectAudio( INuiSensor* pKinectSensor, AEC_SYSTEM_MODE AECSystemMode ); void Read(BYTE **ppBuffer, DWORD *pLength, double* pAngle, double* pConfidence, double* pBeamAngle); }; #endif
#include "../../Common/Header/UKinectAudio08.h" UCKinectAudio08::UCKinectAudio08() { m_pAudioBeam = nullptr; m_pMediaObject = nullptr; m_pPropertyStore = nullptr; } UCKinectAudio08::~UCKinectAudio08() { Invalidate(); } void UCKinectAudio08::Invalidate() { SAFE_RELEASE( m_pPropertyStore ); SAFE_RELEASE( m_pMediaObject ); SAFE_RELEASE( m_pAudioBeam ); } void UCKinectAudio08::CreateKinectAudio( INuiSensor* pKinectSensor, AEC_SYSTEM_MODE AECSystemMode ) { HRESULT hr = E_FAIL; if( FAILED( hr = pKinectSensor->NuiGetAudioSource( &m_pAudioBeam ) ) ) throw( UCException( hr, _T("UCKinectAudio08::CreateKinectAudio()でエラーが発生しました。INuiAudioBeam()インターフェースの取得に失敗しました") ) ); if( FAILED( hr = m_pAudioBeam->QueryInterface( IID_IMediaObject, (void**)&m_pMediaObject ) ) ) throw( UCException( hr, _T("UCKinectAudio08::CreateKinectAudio()でエラーが発生しました。IMediaObject()インターフェースの取得に失敗しました") ) ); if( FAILED( hr = m_pAudioBeam->QueryInterface( IID_IPropertyStore, (void**)&m_pPropertyStore ) ) ) throw( UCException( hr, _T("UCKinectAudio08::CreateKinectAudio()でエラーが発生しました。IPropertyStore()インターフェースの取得に失敗しました") ) ); PROPVARIANT pvSysMode; PropVariantInit(&pvSysMode); pvSysMode.vt = VT_I4; // 4バイト符号ありで設定 pvSysMode.lVal = (LONG)AECSystemMode; // エコーキャンセラとマイクロホンアレイのモード設定する m_pPropertyStore->SetValue(MFPKEY_WMAAECMA_SYSTEM_MODE, pvSysMode); PropVariantClear(&pvSysMode); WAVEFORMATEX format; GetWaveFormat( &format ); // バッファサイズを設定する。必要となるサイズはPCMの場合、1秒間当たりのデータ転送量。 m_StaticMediaBuffer.ResizeBuffer( format.nAvgBytesPerSec ); DMO_MEDIA_TYPE mt = { 0 }; // メディア タイプ構造体を初期化する。よくわかってない。 ::MoInitMediaType( &mt, sizeof( WAVEFORMATEX ) ); mt.majortype = MEDIATYPE_Audio; mt.subtype = MEDIASUBTYPE_PCM; // PCMについてはウィキ参照で mt.bFixedSizeSamples = TRUE; // オーディオの場合通常 TRUE mt.bTemporalCompression = FALSE; // よくわからんが FALSE の場合、オーディオサンプルが時系列 (フレーム間) 圧縮方式で圧縮されていない mt.lSampleSize = 0; // サンプルのサイズ (バイト単位)。未使用? mt.formattype = FORMAT_WaveFormatEx; ::CopyMemory( mt.pbFormat, &format, sizeof( WAVEFORMATEX ) ); // ストリームのメディア タイプを設定する if( FAILED( hr = m_pMediaObject->SetOutputType( 0, &mt, 0 ) ) ) throw( UCException( hr, _T("UCKinectAudio08::Start()でエラーが発生しました。SetOutputType()が失敗しました") ) ); ::MoFreeMediaType(&mt); } void UCKinectAudio08::GetWaveFormat( WAVEFORMATEX* pFormat ) { // この辺はSDKサンプルの通りで pFormat->wFormatTag = WAVE_FORMAT_PCM; pFormat->nChannels = 1; pFormat->nSamplesPerSec = 16000; pFormat->nAvgBytesPerSec = 32000; pFormat->nBlockAlign = 2; pFormat->wBitsPerSample = 16; pFormat->cbSize = 0; } void UCKinectAudio08::Read(BYTE **ppBuffer, DWORD *pLength, double* pAngle, double* pConfidence, double* pBeamAngle) { HRESULT hr = E_FAIL; m_StaticMediaBuffer.SetLength( 0 ); DMO_OUTPUT_DATA_BUFFER outputDataBuffer; ::ZeroMemory( &outputDataBuffer, sizeof( DMO_OUTPUT_DATA_BUFFER ) ); // UCStaticMediaBufferのポインタを設定する outputDataBuffer.pBuffer = &m_StaticMediaBuffer; do { DWORD dwStatus; // 現在の入力データから出力を生成する。 if( FAILED( hr = m_pMediaObject->ProcessOutput( 0, 1, &outputDataBuffer, &dwStatus ) ) ) throw( UCException( hr, _T("UCKinectAudio08::Read()でエラーが発生しました。ProcessOutput()が失敗しました") ) ); }while( outputDataBuffer.dwStatus & DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE ); m_StaticMediaBuffer.GetBufferAndLength( ppBuffer, pLength ); // 音源の方向と信頼性を取得する if( FAILED( hr = m_pAudioBeam->GetPosition( pAngle, pConfidence ) ) ) throw( UCException( hr, _T("UCKinectAudio08::Read()でエラーが発生しました。GetPosition()が失敗しました") ) ); // ビームの方向を取得する if( FAILED( hr = m_pAudioBeam->GetBeam( pBeamAngle ) ) ) throw( UCException( hr, _T("UCKinectAudio08::Read()でエラーが発生しました。GetBeam()が失敗しました") ) ); }
#include "../../Common/Header/UCommon.h" #include "../../Common/Header/UException.h" #include "../../Common/Header/UDirect3D11.h" #include "../../Common/Header/UGraphicsPipeline.h" #include "../../Common/Header/UKinect07.h" #include "../../Common/Header/UKinectAudio08.h" #include "../../Common/Header/UDebugFont.h" #include <NuiApi.h> // アプリケーション名 TCHAR* AppName = _T("Kinect_Tutrial08"); // Direct3D関連の自作クラス UCDirect3D11* g_pDirect3D11 = nullptr; // Kinectセンサーオブジェクト UCKinect07* g_pKinect = nullptr; // Kinect Audio オブジェクト UCKinectAudio08* g_pKinectAudio = nullptr; // デバックフォントクラス UCDebugFont* g_pDebugFont = nullptr; // メモリ解放 void Invalidate() { SAFE_DELETE( g_pDebugFont ); SAFE_DELETE( g_pKinectAudio ); SAFE_DELETE( g_pKinect ); SAFE_DELETE( g_pDirect3D11 ); } // ウィンドウプロシージャ LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam ) { switch( msg ) { case WM_KEYUP: // アプリ終了 if( wParam == VK_ESCAPE ) ::DestroyWindow( hWnd ); break; case WM_KEYDOWN: switch( wParam ) { case VK_UP: if( g_pKinect && g_pKinect->IsReadyKinect() ) g_pKinect->CameraElevationSetAngle( 5 ); break; case VK_DOWN: if( g_pKinect && g_pKinect->IsReadyKinect() ) g_pKinect->CameraElevationSetAngle( -5 ); break; } break; case WM_DESTROY: ::PostQuitMessage(0); break; default: return ::DefWindowProc( hWnd, msg, wParam, lParam ); } return 0L; } // Direct3Dの作成 void CreateDirect3D( HINSTANCE hInstance, DWORD Width, DWORD Height ) { DXGI_MODE_DESC* pModeDescArray = nullptr; __try { DXGI_MODE_DESC ModeDesc; UINT num; // ディスプレイモード一覧の数を取得する g_pDirect3D11->GetDisplayMode( nullptr, &num ); pModeDescArray = NEW DXGI_MODE_DESC[num]; // ディスプレイモード一覧を取得する g_pDirect3D11->GetDisplayMode( pModeDescArray, &num ); bool find = false; for( UINT i=0; i<num; i++ ) { // 適切な解像度のディスプレイモードを検索する if( pModeDescArray[i].Width == Width && pModeDescArray[i].Height == Height ) { find = true; ::CopyMemory( &ModeDesc, &pModeDescArray[i], sizeof( DXGI_MODE_DESC ) ); break; } } if( find == false ) throw( UCException( -1, _T("InitDirect3D()でエラーが発生しました。適切なディスプレイモードの解像度を取得できません。") ) ); // ウィンドウの作成およびDirect3D の作成 g_pDirect3D11->CreateDirect3D11( AppName, hInstance, WndProc, &ModeDesc, TRUE, TRUE ); } __finally { SAFE_DELETE_ARRAY( pModeDescArray ); } } void CreateGraphicePipeline() { } // メッシュを作成する void CreateMesh() { } void CreateResource( HINSTANCE hInstance ) { // Direct3D 関連自作クラスのインスタンスを作成 // CreateDirect3D()関数内でインスタンスの作成を行うと、C2712 エラーが発生するのでここで行う。 g_pDirect3D11 = NEW UCDirect3D11(); g_pKinect = NEW UCKinect07(); g_pKinectAudio = NEW UCKinectAudio08(); g_pDebugFont = NEW UCDebugFont(); DWORD Width = 0, Height = 0; // Kinectセンサーオブジェクトを作成 g_pKinect->CreateKinect( FALSE ); // KinectAudioオブジェクトを作成 g_pKinectAudio->CreateKinectAudio( g_pKinect->m_pKinectSensor, UCKinectAudio08::AEC_SYSTEM_MODE::OPTIBEAM_ARRAY_AND_AEC ); g_pKinect->GetImageResolutionToSize( Width, Height ); // Direct3Dの作成 CreateDirect3D( hInstance, Width, Height ); // グラフィックパイプラインリソースの作成 CreateGraphicePipeline(); // リソースの作成 CreateMesh(); g_pDebugFont->CreateMesh( g_pDirect3D11->m_pD3DDevice, 0.025f, 0.1f ); } void NextFrame() { NUI_LOCKED_RECT* imageDataFromKinect = nullptr; // Kinect側のフレームの更新が完了するまで待つ g_pKinect->WaitForSingleObject(); // Kinect側の次のフレームのイメージフレームの作成 g_pKinect->NextFrameImageData( &imageDataFromKinect ); if( g_pKinect->IsReadyKinect() == TRUE ) { // オーディオを読み込む BYTE* pBuffer = nullptr; DWORD BufferLength = 0; double angle, confidence, beamAngle; g_pKinectAudio->Read( &pBuffer, &BufferLength, &angle, &confidence, &beamAngle ); TCHAR str[512]; _stprintf_s( str, _T("angle:%f, confidence:%f, beamAngle:%f"), angle * 180.0f / 3.141592654f, confidence, beamAngle * 180.0f / 3.141592654f ); XMFLOAT2 pos = XMFLOAT2( -0.98f, 0.95f ); XMFLOAT4 color = XMFLOAT4( 1, 1, 1, 1 ); g_pDebugFont->NextFrame( str, &pos, &color ); } } // 描画処理 HRESULT Render() { HRESULT hr = E_FAIL; float ClearColor[4] = { 0.3f, 0.3f, 1.0f, 1.0f }; // バックバッファをクリアする。 g_pDirect3D11->ClearBackBuffer( ClearColor ); // 深度バッファをクリアする。 g_pDirect3D11->ClearDepthStencilView( D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 ); // レンダリング g_pDebugFont->Render( g_pDirect3D11->m_pD3DDeviceContext ); // レンダリングされたイメージをユーザーに表示。 if( FAILED( hr = g_pDirect3D11->Present( 0, 0 ) ) ) throw( UCException( hr, _T("IDXGISwapChain::Present()が失敗しました") ) ); return hr; } // メイン関数 int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR, INT ) { // メモリリーク検出 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_EVERY_1024_DF); MSG msg = {0}; try { CreateResource( hInstance ); ::ShowWindow( g_pDirect3D11->m_hWnd, SW_SHOW ); ::UpdateWindow( g_pDirect3D11->m_hWnd ); // メッセージループ do { if( ::PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { NextFrame(); Render(); } }while( msg.message != WM_QUIT ); } catch( UCException ex ) { ::MessageBox( nullptr, ex.m_pErrorStr, _T("エラー"), MB_OK ); } Invalidate(); ::UnregisterClass( AppName, hInstance ); return msg.wParam; }