久しくDirectX関連はウォッチしていなかったのだけれど、Windows 7からDirect2Dという2DグラフィックスAPIが搭載されるとのこと。
これはGDI,GDI+に取って代わるもので、D3Dの上で構築されている。
当初DirectXは2Dのゲーム用ビットマップグラフィックスAPIで、それから3D APIが搭載され、2D部分が(名目上)なくなって、ビジネスグラフィックスの置き換えのためにまた復活した。
GDI+と違い、ハードウェアアクセラレーションが効くとのことで普及するのではないかと見られている。
しかし、本当はビデオメモリに余計なオーバーヘッドなく読み書きができるようになれば後はソフトウェアでなんとかなりそうななんだが、そういう風には世の中は流れてはいかないようだ。
2009年10月13日
2009年10月11日
WASAPI(17) - JUCEのWASAPIサポート
JUCEのWASAPIサポートはすでに始まっていて、ソースコードも見ることができる。
http://www.rawmaterialsoftware.com/juceforum/viewtopic.php?t=4404
ただ、いまのところ共有モードのみで、排他モードのサポートはないようだ。おそらくWindows 7が共有モードで低レイテンシ再生・録音が可能になっているためであろうと考える。
http://msdn.microsoft.com/en-us/library/dd756612(VS.85).aspx
とりあえず私は、上記ソースコードも参考にしながら、排他モードでのサポートを目指すことにする。
http://www.rawmaterialsoftware.com/juceforum/viewtopic.php?t=4404
ただ、いまのところ共有モードのみで、排他モードのサポートはないようだ。おそらくWindows 7が共有モードで低レイテンシ再生・録音が可能になっているためであろうと考える。
http://msdn.microsoft.com/en-us/library/dd756612(VS.85).aspx
とりあえず私は、上記ソースコードも参考にしながら、排他モードでのサポートを目指すことにする。
WASAPI(16) - Boost.Assignment
ptr_vectorの初期化にBoost.Assignemntを使ってみようとして午前中四苦八苦していた。
こうしたかったのだ。
四苦八苦した結果、下記のとおりにすればできることがわかった。
(1)WAVEFORMATEXを継承した構造体、sf:WAVEFORMATEXを作成してコンストラクタを実装する。
(2)#define BOOST_ASSIGN_MAX_PARAMS 7をptr_list_of.hppをインクルードする前に入れる。
こうしたかったのだ。
boost::ptr_vector<WAVEFORMATEX> WASAPI::impl::wave_formats_ = ptr_list_of<WAVEFORMATEX< ( WAVE_FORMAT_PCM, 2, 192000,768000, 4, 16, 0 ) ( WAVE_FORMAT_PCM, 2, 96000, 384000, 4, 16, 0 ) // 96-kHz, 16-bit stereo ( WAVE_FORMAT_PCM, 2, 48000, 192000, 4, 16, 0 ) // 48-kHz, 16-bit stereo ( WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0 ) // 44.1-kHz, 16-bit stereo ( WAVE_FORMAT_PCM, 2, 32000, 128000, 4, 16, 0 ) // 32-kHz, 16-bit stereo ( WAVE_FORMAT_PCM, 2, 8000, 32000, 4, 16, 0 ) // 8-kHz, 16-bit stereo ( WAVE_FORMAT_PCM, 2, 48000, 96000, 2, 8, 0 ) // 48-kHz, 8-bit stereo ( WAVE_FORMAT_PCM, 2, 44100, 88200, 2, 8, 0 ) // 44.1-kHz, 8-bit stereo ( WAVE_FORMAT_PCM, 2, 32000, 64000, 2, 8, 0 ) // 32-kHz, 8-bit stereo ( WAVE_FORMAT_PCM, 2, 8000, 16000, 2, 8, 0 );// // 8-kHz, 8-bit stereo
四苦八苦した結果、下記のとおりにすればできることがわかった。
(1)WAVEFORMATEXを継承した構造体、sf:WAVEFORMATEXを作成してコンストラクタを実装する。
(2)#define BOOST_ASSIGN_MAX_PARAMS 7をptr_list_of.hppをインクルードする前に入れる。
#define BOOST_ASSIGN_MAX_PARAMS 7
#include <boost/assign.hpp>
#include <oost/assign/ptr_list_of.hpp>
namespace sf {
struct WAVEFORMATEX : public ::WAVEFORMATEX {
WAVEFORMATEX(
WORD FormatTag = 0, /* format type */
WORD Channels = 0, /* number of channels (i.e. mono, stereo...) */
DWORD SamplesPerSec = 0, /* sample rate */
DWORD AvgBytesPerSec = 0, /* for buffer estimation */
WORD BlockAlign = 0, /* block size of data */
WORD BitsPerSample = 0, /* number of bits per sample of mono data */
WORD Size = sizeof(::WAVEFORMATEX) /* the count in bytes of the size of */
)
{
wFormatTag = FormatTag;
nChannels = Channels;
nSamplesPerSec = SamplesPerSec;
nAvgBytesPerSec = AvgBytesPerSec;
nBlockAlign = BlockAlign;
wBitsPerSample = BitsPerSample;
cbSize = Size;
};
};
boost::ptr_vector<sf::WAVEFORMATEX> WASAPI::impl::wave_formats_ =
ptr_list_of<sf::WAVEFORMATEX>
( WAVE_FORMAT_PCM, 2, 192000,768000, 4, 16, 0 )
( WAVE_FORMAT_PCM, 2, 96000, 384000, 4, 16, 0 ) // 96-kHz, 16-bit stereo
( WAVE_FORMAT_PCM, 2, 48000, 192000, 4, 16, 0 ) // 48-kHz, 16-bit stereo
( WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0 ) // 44.1-kHz, 16-bit stereo
( WAVE_FORMAT_PCM, 2, 32000, 128000, 4, 16, 0 ) // 32-kHz, 16-bit stereo
( WAVE_FORMAT_PCM, 2, 8000, 32000, 4, 16, 0 ) // 8-kHz, 16-bit stereo
( WAVE_FORMAT_PCM, 2, 48000, 96000, 2, 8, 0 ) // 48-kHz, 8-bit stereo
( WAVE_FORMAT_PCM, 2, 44100, 88200, 2, 8, 0 ) // 44.1-kHz, 8-bit stereo
( WAVE_FORMAT_PCM, 2, 32000, 64000, 2, 8, 0 ) // 32-kHz, 8-bit stereo
( WAVE_FORMAT_PCM, 2, 8000, 16000, 2, 8, 0 );// // 8-kHz, 8-bit stereo
2009年10月10日
CComPtr
VC Express EditionにはATLがついてないので、CComPtr(COMスマートポインタ)がない。
boost::intrusive_ptrで代用していた(ちなみに代用方法はこちら参照)のだが、どうにも面倒臭いのでググってみたらやはりCComPtrクローンを作っている人がいた。
http://www.codeproject.com/KB/COM/ccomptr.aspx
http://www.firefly-vj.net/imagery/?itemid=354
上記2つを適当にマージして作ったのが下記コード。
boost::intrusive_ptrで代用していた(ちなみに代用方法はこちら参照)のだが、どうにも面倒臭いのでググってみたらやはりCComPtrクローンを作っている人がいた。
http://www.codeproject.com/KB/COM/ccomptr.aspx
http://www.firefly-vj.net/imagery/?itemid=354
上記2つを適当にマージして作ったのが下記コード。
#ifndef _COMPTR_H_
#define _COMPTR_H_
template<class INTERFACE, const IID* piid = NULL>
class CComPtr
{
public:
CComPtr()
{
interface_ = NULL;
}
CComPtr(INTERFACE* lPtr)
{
interface_ = NULL;
if (lPtr != NULL)
{
interface_ = lPtr;
interface_->AddRef();
}
}
CComPtr(const CComPtr<INTERFACE, piid>& RefComPtr)
{
interface_ = NULL;
interface_ = (INTERFACE*)RefComPtr;
if (interface_)
{
interface_->AddRef();
}
}
CComPtr(IUnknown* pIUnknown, IID iid)
{
interface_ = NULL;
if (pIUnknown != NULL)
{
pIUnknown->QueryInterface(iid, (void**)&interface_);
}
}
~CComPtr()
{
if (interface_)
{
interface_->Release();
interface_ = NULL;
}
}
public:
operator INTERFACE*() const
{
return interface_;
}
INTERFACE& operator*() const
{
return *interface_;
}
INTERFACE** operator&()
{
return &interface_;
}
INTERFACE* operator->() const
{
return interface_;
}
INTERFACE* operator=(INTERFACE* lPtr)
{
if (IsEqualObject(lPtr))
{
return interface_;
}
interface_->Release();
lPtr->AddRef();
interface_ = lPtr;
return interface_;
}
INTERFACE* operator=(IUnknown* pIUnknown)
{
assert(pIUnknown != NULL);
assert(piid != NULL);
pIUnknown->QueryInterface(*piid, (void**)&interface_);
assert(interface_ != NULL);
return interface_;
}
INTERFACE* operator=(const CComPtr<INTERFACE, piid>& RefComPtr)
{
assert(&RefComPtr != NULL);
interface_ = (INTERFACE*)RefComPtr;
if (interface_)
{
interface_->AddRef();
}
return interface_;
}
void Attach(INTERFACE* lPtr)
{
if (interface_)
{
interface_->Release();
}
interface_ = lPtr;
}
INTERFACE* Detach()
{
INTERFACE* lPtr = interface_;
interface_ = NULL;
return lPtr;
}
void Release()
{
if (interface_)
{
interface_->Release();
interface_ = NULL;
}
}
bool IsEqualObject(IUnknown* pOther)
{
assert(pOther != NULL);
IUnknown* pUnknown = NULL;
interface_->QueryInterface(IID_IUnknown, (void**)&pUnknown);
bool Result = (pOther == pUnknown) ? true : false;
pUnknown->Release();
return Result;
}
HRESULT CreateInstance(const GUID &clsid, IID iid=GUID_NULL)
{
if(IsEqualObject(iid, GUID_NULL)) iid=__uuidof(T);
HRESULT hr = ::CoCreateInstance(clsid, NULL
,CLSCTX_INPROC_SERVER
,iid
,(void**)(&interface_));
return hr;
}
private:
INTERFACE* interface_;
};
#endif // _COMPTR_H_
しかし、今頃になってCOM Interfaceラッパを作る羽目になるとは。。。SyntaxHighlighter
SyntaxHighlighterを2.0.320にアップした。
http://alexgorbatchev.com/wiki/SyntaxHighlighter
http://alexgorbatchev.com/wiki/SyntaxHighlighter
WASAPI(15) - MemoryGuared
IMMDeviceのGetId( LPWSTR *ppstrId)で、デバイスIDの文字列が取得できるのだが、この文字列はOSでアロケートされたメモリに格納されるので、不要になったらCoTaskMemFree()しなくてはならない。
こういうのは忘れやすい僕にとっては危険な仕様なので、ラッパクラスを作って確実に解放するようにしたい。
すこしググってみたらやっぱり同じことを考えている人がいて、ポリシーベースの立派なものがすでに作られていたので、早速拝借することにする。
こういうのは忘れやすい僕にとっては危険な仕様なので、ラッパクラスを作って確実に解放するようにしたい。
すこしググってみたらやっぱり同じことを考えている人がいて、ポリシーベースの立派なものがすでに作られていたので、早速拝借することにする。
<元ネタ>https://forums.codegear.com/thread.jspa?messageID=97614𗵎
namespace sf
{
// policy class
struct HeapMemoryFreePolicy
{
template< typename T >
void operator()( const T* AMemory ) const
{
if( NULL != AMemory )
::HeapFree( ::GetProcessHeap(), 0, AMemory );
}
};
// policy class
struct LocalMemoryFreePolicy
{
template< typename T >
void operator()( const T* AMemory ) const
{
if( NULL != AMemory )
::LocalFree( AMemory );
}
};
// policy class
struct CoTaskMemoryFreePolicy
{
template< typename T >
void operator()( const T* AMemory ) const
{
if( NULL != AMemory )
::CoTaskMemFree( AMemory );
}
};
// base guard class
template< typename T,
class TFreePolicy
class BaseMemory
{
private:
T *FMemory;
public:
BaseMemory( T* AMemory = NULL )
: FMemory( AMemory ) {}
virtual ~BaseMemory( void )
{ Reset(); }
T* Release( void )
{
T *tmp = FMemory;
FMemory = NULL;
return tmp;
}
void Reset( T* AMemory = NULL )
{
if( AMemory != FMemory )
{
if( NULL != FMemory )
TFreePolicy( FMemory );
FMemory = AMemory;
}
}
T* Get( void )
{ return FMemory; }
T** operator&( void )
{ return &FMemory; }
};
template< typename T >
class HeapMemory : public BaseMemory< T,
HeapMemoryFreePolicy >
{
public:
HeapMemory( T* AMemory = NULL )
: BaseMemory< T, HeapMemoryFreePolicy >( AMemory )
{ }
};
template< typename T >
class LocalMemory : public BaseMemory< T,
LocalMemoryFreePolicy >
{
public:
LocalMemory( T* AMemory = NULL )
: BaseMemory< T, LocalMemoryFreePolicy >( AMemory )
{ }
};
template< typename T >
class CoTaskMemory : public BaseMemory< T,
CoTaskMemoryFreePolicy >
{
public:
CoTaskMemory( T* AMemory = NULL )
: BaseMemory< T, CoTaskMemoryFreePolicy >( AMemory )
{ }
};
} // end namespace sf
2009年10月09日
WASAPI(14) - IUnknownImpl
小ネタ。
IUnknownを実装するクラス。
template <typename COMInterface>
struct IUnknownImpl : public COMInterface
{
IUnknownImpl() : ref_(1) {};
virtual ~IUnknownImpl() {};
ULONG __stdcall AddRef()
{
return InterlockedIncrement(&ref_);
}
ULONG __stdcall Release()
{
ULONG ref = InterlockedDecrement(&ref_);
if (0 == ref)
{
delete this;
}
return ref;
}
HRESULT __stdcall QueryInterface(REFIID riid, VOID **ppObj)
{
if (IID_IUnknown == riid)
{
AddRef();
*ppObj = (IUnknown*)this;
}
else if (__uuidof(COMInterface) == riid)
{
AddRef();
*ppObj = (COMInterface*)this;
}
else
{
*ppObj = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
private:
LONG ref_;
};
<使い方>
struct MMNotificationClient : public IUnknownImpl<IMMNotificationClient>
{ ... }
2009年10月07日
2009年10月04日
WASAPI(12)
とりあえず、ドライバ設定画面に表示されるようにした。
本格的な実装はこれから。

・DSOUNDではドライバの列挙はコールバック関数で行っていたけれども、WASAPIでは以下のようにドライバを列挙する。
1.IMMDeviceEnumeratorをCoCreateInstanceする
2.IMMDeviceEnumerator->EnumAudioEndpointsでデバイスのコレクション(IMMDeviceCollection)を取得する。
・個々のエンドポイントデバイスを取り出すには、IMMDeviceCollection->Item(DWORD index,IMMDevice**)でデバイス(IMMDevice)を取得する
・デバイスの属性を取得するにはIMMDevice->OpenPropertyStore()でIPropertyStoreを取得する
・各属性を取り出すには、IPropertyStore ->GetValue()で取り出す。
取り出した値はPROPVARIANT型である
とまあ、COM全開でなんとも面倒くさいのである。
本格的な実装はこれから。
・DSOUNDではドライバの列挙はコールバック関数で行っていたけれども、WASAPIでは以下のようにドライバを列挙する。
1.IMMDeviceEnumeratorをCoCreateInstanceする
2.IMMDeviceEnumerator->EnumAudioEndpointsでデバイスのコレクション(IMMDeviceCollection)を取得する。
・個々のエンドポイントデバイスを取り出すには、IMMDeviceCollection->Item(DWORD index,IMMDevice**)でデバイス(IMMDevice)を取得する
・デバイスの属性を取得するにはIMMDevice->OpenPropertyStore()でIPropertyStoreを取得する
・各属性を取り出すには、IPropertyStore ->GetValue()で取り出す。
取り出した値はPROPVARIANT型である
とまあ、COM全開でなんとも面倒くさいのである。
2009年10月03日
JUCEのWDM
JUCEライブラリのコードでWDMAudioを実装してそうな雰囲気のコードを発見。しかし、1.50ではまだ未対応のようだ。WDMのコード自体は発見できなかったので。
extern AudioIODeviceType* juce_createDefaultAudioIODeviceType();
#if JUCE_WIN32 && JUCE_ASIO
extern AudioIODeviceType* juce_createASIOAudioIODeviceType();
#endif
#if JUCE_WIN32 && JUCE_WDM_AUDIO
extern AudioIODeviceType* juce_createWDMAudioIODeviceType();
#endif
void AudioDeviceManager::createAudioDeviceTypes (OwnedArray <AudioIODeviceType>& list)
{
AudioIODeviceType* const defaultDeviceType = juce_createDefaultAudioIODeviceType();
if (defaultDeviceType != 0)
list.add (defaultDeviceType);
#if JUCE_WIN32 && JUCE_ASIO
list.add (juce_createASIOAudioIODeviceType());
#endif
#if JUCE_WIN32 && JUCE_WDM_AUDIO
list.add (juce_createWDMAudioIODeviceType());
#endif
}
2009年10月01日
マスコミ
朝日の一面に、鳩山さんの「小」スキャンダルが大見出しで載っていた。
自民党が与党であったときも散々見てきたこのマスコミによる、「小スキャンダルで民意を煽動し、コロコロ大臣・総理を変えさせる」のは何の目的で行っているのか?
マスコミはその多大なる影響力をもってこの国をどうしたいのだろうか?僕には破滅に導いているとしか思えない。
なぜもっと真摯に公平に報道しないのだろう。
なぜ事の重大性と紙面の面積をあえて変えて、さも重大であることのように見せようとするのだろうか?
人間は「善・悪」を併せ持つ生き物であり、政治家であっても悪の部分が存在するはずである。そういう前提で物事を語るべきである。
マスコミは政治家に「悪」の部分はすべて排除せよといわんばかりだ。
しかも、その悪が犯罪であるのかどうかわからない段階でまるで「悪」であるかのように書き立てる。
人間は「悪」を内包するからこそ「悪」を抑制するための「法」が必要なのであり、「悪」をできる限り減らすために日々反省し、「遵法」にいそしまなければならない。
過去に法の過ちを冒すことは人間なら誰しもあることであり、「反省」および「厚生」をして現在遵法状態にある人間を、過去に遡及して現状を顧みず批判する記事も本当に多い。
マスコミがいかにいい加減かは今に始まったことではない。
マスコミは戦前のファシズムの台頭を助け、破滅へと導くよう国民を煽動したという事実がある。
戦後マスコミは自省をしただろうか?ファシズムという「悪」なるものに屈せず、沈着冷静に事実を公平に報道したかどうかという点において。
自民党が与党であったときも散々見てきたこのマスコミによる、「小スキャンダルで民意を煽動し、コロコロ大臣・総理を変えさせる」のは何の目的で行っているのか?
マスコミはその多大なる影響力をもってこの国をどうしたいのだろうか?僕には破滅に導いているとしか思えない。
なぜもっと真摯に公平に報道しないのだろう。
なぜ事の重大性と紙面の面積をあえて変えて、さも重大であることのように見せようとするのだろうか?
人間は「善・悪」を併せ持つ生き物であり、政治家であっても悪の部分が存在するはずである。そういう前提で物事を語るべきである。
マスコミは政治家に「悪」の部分はすべて排除せよといわんばかりだ。
しかも、その悪が犯罪であるのかどうかわからない段階でまるで「悪」であるかのように書き立てる。
人間は「悪」を内包するからこそ「悪」を抑制するための「法」が必要なのであり、「悪」をできる限り減らすために日々反省し、「遵法」にいそしまなければならない。
過去に法の過ちを冒すことは人間なら誰しもあることであり、「反省」および「厚生」をして現在遵法状態にある人間を、過去に遡及して現状を顧みず批判する記事も本当に多い。
マスコミがいかにいい加減かは今に始まったことではない。
マスコミは戦前のファシズムの台頭を助け、破滅へと導くよう国民を煽動したという事実がある。
戦後マスコミは自省をしただろうか?ファシズムという「悪」なるものに屈せず、沈着冷静に事実を公平に報道したかどうかという点において。

