Windowsにあるサウンドデコーダーのようなツールを作ろうとしているんですが
VBでマイクからwav形式(8kHz,8bitか11.025kHz,8bit)で録音するのはどう
すれば良いのでしょうか?
MMcontrolやmcisendstringやwaveInxxxなどを使っていろいろやってみたの
ですが、うまく行きませんでした。私が初心者なせいもあるとは思いますが
詳しい方おりましたら助けてください。。よろしくお願いします。
私がやった方法では・・・
録音ルーチンは、ActiveXで、C言語(C++で、MFC使ってます)を用いて
作成しました。
とも言うのも、録音ルーチンは、オーディオデバイスからのコールバック
ルーチンとしての機能が必要であった為、VBの.BASに記述して・・・
という裏技も可能なのですが、速度が要求される部分だった為、VBのみ
での記述では、到底処理しきれるものではないと思った為です。
今は他によいものがあるかもしれませんが・・・
VBのみでのレコーディング機能の作成は、かなり無理があると思います
が・・・
以上。
すいません。訂正個所がありました…
WindowsのサウンドデコーダーではなくWindowsのサウンドレコーダーでした。
まず、デコーダという語句を、勝手にレコーダと読み替えて上記書き込みを
していました・・・
それと・・・VBで出来ないのか?と言う部分では、可能性を否定するつも
りは全くありません。が、機能的に有利なものを使うのが得策だとは考えて
おります。
C言語でも、当時は大変でした・・・
とある商品の開発を行った折の完全に動作していたActiveXのC++ソース
コードの一部を掲載します。コメントは、依頼元の都合上、大半を削除させ
て頂いております。また、このままでは当然、コンパイルし動作させること
はできません。が、オーディオ系のAPIの呼び方の順序や関わりが解るとは
思います。
※ 申し訳ありませんが、録音部分のコールバック関数周辺のみですが、
長文となっております。これから解るように、ここをVBで記述する
のは至難の業と言うか、VBでは、解決できないAPIがありますので・・・
BOOL CUtilCtrl::SampWaveIn(long hWnd)
{
// TODO: ここにディスパッチ ハンドラ コードを追加してください。
WAVEINCAPS wic;
UINT nDevId;
MMRESULT rc;
long lvol , rvol , lSelect , lMute;
long ret;
lSelect = 1;
ret = VolumeFunction( DEST_RECORD , SET_DEVICE_ONOFF , &lvol , &rvol , &lSelect , MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE );
// YAMAHA OPLx3等のカードの場合、CD Audioが、デフォルトで選択された状態でマイク
// を選択しても、反映されない場合がある。故に、一旦CD Audio, MIC以外の必ず存在
// するデバイス(LINE等)を選択し、マイクを選択することで問題を回避。
lSelect = 0;
ret = VolumeFunction( DEST_RECORD , GET_DEVICE_ONOFF , &lvol , &rvol , &lSelect , MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE );
if ( ret == 0 && lSelect != 1 ){
lSelect = 1;
ret = VolumeFunction2( DEST_RECORD , SET_DEVICE_ONOFF , &lvol , &rvol , &lSelect , MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE );
}
lMute = 1;
VolumeFunction( DEST_PLAY , SET_VOLUME_MUTE_NORMAL , &lvol , &rvol , &lMute , MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE );
hWndOrg = ( HWND )hWnd;
UINT nMaxDevice = waveInGetNumDevs();
hwi = NULL;
m_lPeakVolume = 0;
for ( nDevId = 0 ; nDevId < nMaxDevice ; nDevId++ ){
rc = waveInGetDevCaps( nDevId , &wic , sizeof( wic ) );
if ( rc == MMSYSERR_NOERROR ){
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = WAVE_FORMAT_1M08;
wfx.nSamplesPerSec = 11025;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec;
wfx.wBitsPerSample = 8;
wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
wfx.cbSize = 0;
do {
rc = waveInOpen( &hwi , WAVE_MAPPER , &wfx , ( DWORD )( VOID * )waveInProc , ( DWORD )hWnd , CALLBACK_FUNCTION );
if ( rc != MMSYSERR_NOERROR ){
::Sleep( 100 );
}
}while( rc != MMSYSERR_NOERROR );
break;
}
}
if ( hwi == NULL )
return( FALSE );
else {
if ( pPlaybackBuffer == NULL ){
m_lPlaybackBufferSize = wfx.nSamplesPerSec * wfx.wBitsPerSample / 8 * 10; // 10秒間の録音サイズ
pPlaybackBuffer = ( void * )HeapAlloc( GetProcessHeap() , HEAP_ZERO_MEMORY , m_lPlaybackBufferSize );
if ( pPlaybackBuffer == NULL ){
rc = waveInClose( hwi );
hwi = NULL;
return( FALSE );
} else
nPlaybackBufferPos = 0;
} else
nPlaybackBufferPos = 0;
}
for ( int i = 0 ; i < MIC_BUFF_COUNT ; i++ ){
DWORD AllocSize = wfx.nSamplesPerSec * wfx.wBitsPerSample / 8 / MIC_SAMP_COUNT;
whi[ i ] = ( WAVEHDR * )GlobalAlloc( GPTR , sizeof( WAVEHDR ) );
if ( whi[ i ] ){
whi[ i ]->lpData = ( LPSTR )GlobalAlloc( GPTR , AllocSize );
whi[ i ]->dwBufferLength = AllocSize;
whi[ i ]->dwBytesRecorded = 0;
whi[ i ]->dwUser = 0;
whi[ i ]->dwFlags = 0;
whi[ i ]->dwLoops = 0;
whi[ i ]->lpNext = 0;
whi[ i ]->reserved = 0;
}
}
m_lCountIn = 0;
for ( i = 0 ; i < MIC_BUFF_COUNT ; i++ ){
rc = waveInPrepareHeader( hwi , whi[ i ] , sizeof( WAVEHDR ) );
if ( rc == MMSYSERR_NOERROR ){
WaitForCallBack( ( long * )&whi[ i ]->dwFlags , WHDR_PREPARED );
rc = waveInAddBuffer( hwi , whi[ i ] , sizeof( WAVEHDR ) );
if ( rc != MMSYSERR_NOERROR ){
break;
} else
m_lCountIn++;
} else
break;
}
if ( rc != MMSYSERR_NOERROR ){
m_lCountIn = 0;
StopRecord( ( HWND )hWnd );
return( FALSE );
}
for ( i = 0 ; i < MIC_BUFF_COUNT ; i++ )
WaitForCallBack( ( long * )&whi[ i ]->dwFlags , WHDR_PREPARED );
m_fStopIn = FALSE;
rc = waveInStart( hwi );
if ( rc != MMSYSERR_NOERROR ){
StopRecord( ( HWND )hWnd );
return( FALSE );
}
return TRUE;
}
void CALLBACK CUtilCtrl::waveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
MMRESULT rc;
pThisCtl->m_lCountIn--;
if ( pThisCtl->m_fStopIn )
return;
switch( uMsg ){
case WIM_OPEN:
case WIM_CLOSE:
break;
case WIM_DATA:
LPWAVEHDR lpwh = ( LPWAVEHDR )dwParam1;
if ( pThisCtl->m_fStartRecord ){
if ( pThisCtl->nPlaybackBufferPos + lpwh->dwBytesRecorded <= pThisCtl->m_lPlaybackBufferSize ){
memcpy( ( ( char * )pThisCtl->pPlaybackBuffer + pThisCtl->nPlaybackBufferPos ) , lpwh->lpData , lpwh->dwBytesRecorded );
pThisCtl->nPlaybackBufferPos += lpwh->dwBytesRecorded;
pThisCtl->nPlaybackBufferLen += lpwh->dwBytesRecorded;
} else
pThisCtl->m_fStartRecord = FALSE;
}
rc = waveInAddBuffer( pThisCtl->hwi , lpwh , sizeof( WAVEHDR ) );
if (rc != MMSYSERR_NOERROR){
pThisCtl->StopRecord( pThisCtl->hWndOrg );
} else
pThisCtl->m_lCountIn++;
long lMax = 0;
short level = 0;
int i;
BYTE *pByte;
WORD *pWord;
switch( pThisCtl->wfx.wBitsPerSample ){
case 8:
pByte = ( BYTE * )lpwh->lpData;
for ( i = 0 ; i < ( int )( lpwh->dwBytesRecorded ) ; i++ ){
level = ( ( short )*( pByte + i ) ) - 0x007f;
if ( lMax < ( long )abs( level ) )
lMax = ( long )abs( level );
}
pThisCtl->m_lPeakVolume = ( ( lMax << 8 ) * 100L ) / 0x7fffL; // PeakVolume!!
break;
case 16:
pWord = ( WORD * )lpwh->lpData;
for ( i = 0 ; i < ( int )( lpwh->dwBytesRecorded / 2 ) ; i++ ){
level = ( ( short )*( pWord + i ) ) - 0x7fff;
if ( lMax < ( long )abs( level ) )
lMax = ( long )abs( level );
}
pThisCtl->m_lPeakVolume = ( lMax * 100L ) / 0x7fffL; // PeakVolume!!
break;
}
break;
}
}
int CUtilCtrl::VolumeFunction(int destNo ,int funcNo, long * lvol, long * rvol, long * lmute, long tdwComponentType)
{
UINT uDest , uConnect , uConnections;
MIXERCAPS mxcaps;
MIXERLINE mxl;
MIXERLINECONTROLS mxlc;
PMIXERCONTROL paMixerControls;
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED *pmxcdu;
MIXERCONTROLDETAILS_BOOLEAN *pmxcdb;
MIXERCONTROLDETAILS_LISTTEXT *pmxcdl;
long r = 0;
int flag;
BOOL fDone = FALSE;
DWORD dwType0;
DWORD dwType1 , dwType2;
paMixerControls = NULL;
pmxcdu = NULL;
pmxcdb = NULL;
pmxcdl = NULL;
//ミキサーがインストールされているか
if ( mixerGetNumDevs() == 0 ){
return( 1 );
}
//1つ目のミキサデバイスをオープンする
rc = mixerOpen( &hmx , nDevID , 0 , ( DWORD )NULL , MIXER_OBJECTF_MIXER );
if ( rc != MMSYSERR_NOERROR ){
return( 2 );
}
//メインのライン出力スピーカを探す
mxcaps.cDestinations = 0;
mixerGetDevCaps( nDevID , &mxcaps , sizeof( MIXERCAPS ) );
for ( uDest = 0 ; uDest < mxcaps.cDestinations ; uDest++ ){
r = 3;
mxl.cbStruct = sizeof( mxl );
mxl.dwDestination = uDest;
//ライン情報の取得
rc = mixerGetLineInfo( ( HMIXEROBJ )hmx , &mxl , MIXER_GETLINEINFOF_DESTINATION );
if ( rc != MMSYSERR_NOERROR ){
continue;
}
switch( funcNo ){
case SET_VOLUME_MAIN:
case GET_VOLUME_MAIN:
flag = 0;
dwType0 = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
dwType1 = MIXERCONTROL_CONTROLTYPE_VOLUME;
dwType2 = -1;
break;
case SET_VOLUME_MUTE_MAIN:
case GET_VOLUME_MUTE_MAIN:
flag = 0;
dwType0 = tdwComponentType;
dwType1 = MIXERCONTROL_CONTROLTYPE_MUTE;
dwType2 = MIXERCONTROL_CONTROLF_UNIFORM;
break;
case SET_VOLUME_NORMAL:
case GET_VOLUME_NORMAL:
flag = 1;
dwType0 = tdwComponentType;
dwType1 = MIXERCONTROL_CONTROLTYPE_VOLUME;
dwType2 = -1;
break;
case SET_VOLUME_MUTE_NORMAL:
case GET_VOLUME_MUTE_NORMAL:
flag = 1;
dwType0 = tdwComponentType;
dwType1 = MIXERCONTROL_CONTROLTYPE_MUTE;
dwType2 = MIXERCONTROL_CONTROLF_UNIFORM;
break;
case SET_DEVICE_ONOFF:
case GET_DEVICE_ONOFF:
flag = 2;
dwType0 = tdwComponentType;
dwType1 = -1;
dwType2 = MIXERCONTROL_CONTROLF_UNIFORM;
break;
}
switch( flag ){
case 0:
// メインボリューム側処理
if ( uDest == ( UINT )destNo
&& mxl.dwComponentType == dwType0 ){
r = 0;
rc = mixerGetLineInfo( ( HMIXEROBJ )hmx , &mxl , MIXER_GETLINEINFOF_LINEID );
if ( rc != MMSYSERR_NOERROR ){
r = 4;
break;
}
if ( mxl.cControls == 0 ){
r = 5;
break;
}
//PMIXERCONTROL構造体の配列のためのメモリを割り当てる
paMixerControls = ( PMIXERCONTROL )GlobalAlloc( GPTR , sizeof( MIXERCONTROL ) * mxl.cControls );
if ( !paMixerControls ){
r = 10;
break;
}
//MIXERLINECONTROLS構造体を設定
mxlc.cbStruct = sizeof( mxlc );
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlID = 0;
mxlc.dwControlType = 0;
mxlc.cControls = mxl.cControls;
mxlc.cbmxctrl = sizeof( MIXERCONTROL );
mxlc.pamxctrl = paMixerControls;
rc = mixerGetLineControls( ( HMIXEROBJ )hmx , &mxlc , MIXER_GETLINECONTROLSF_ALL );
if ( rc != MMSYSERR_NOERROR ){
r = 11;
} else {
UINT u;
for ( u = 0 ; u < mxlc.cControls ; u++ ){
if ( dwType2 == -1 ){
if ( paMixerControls[ u ].dwControlType == dwType1 ){
r = -1;
//コントロールがアクティブか確認
if ( paMixerControls[ u ].fdwControl & MIXERCONTROL_CONTROLF_DISABLED ){
r = 13;
break;
}
//pmxcduのメモリ確保
pmxcdu = ( MIXERCONTROLDETAILS_UNSIGNED * )GlobalAlloc( GPTR , mxl.cChannels * sizeof( MIXERCONTROLDETAILS_UNSIGNED ) );
if ( pmxcdu == NULL ){
r = 14;
break;
}
//MIXERCONTROLDETAILS構造体の設定
mxcd.cbStruct = sizeof( MIXERCONTROLDETAILS );
mxcd.dwControlID = paMixerControls[ u ].dwControlID;
mxcd.cChannels = mxl.cChannels;
mxcd.cMultipleItems = paMixerControls[ u ].cMultipleItems;
mxcd.cbDetails = sizeof( MIXERCONTROLDETAILS_UNSIGNED );
mxcd.paDetails = pmxcdu;
rc = mixerGetControlDetails( ( HMIXEROBJ )hmx , &mxcd , 0L );
if ( rc != MMSYSERR_NOERROR ){
r = 30;
} else {
switch( funcNo ){
case SET_VOLUME_MAIN:
case SET_VOLUME_NORMAL:
//メインボリュームの設定
pmxcdu[ 0 ].dwValue = ( DWORD )*lvol;
pmxcdu[ 1 ].dwValue = ( DWORD )*rvol;
rc = mixerSetControlDetails( ( HMIXEROBJ )hmx , &mxcd , 0L );
if ( rc != MMSYSERR_NOERROR ){
r = 31;
} else
fDone = TRUE;
break;
case GET_VOLUME_MAIN:
//メインボリュームの数値
*lvol = pmxcdu[ 0 ].dwValue;
*rvol = pmxcdu[ 1 ].dwValue;
fDone = TRUE;
break;
}
// HeapFree( GetProcessHeap() , 0 , pmxcdu );
GlobalFree( ( HGLOBAL )pmxcdu );
}
break;
}
} else {
if ( ( paMixerControls[ u ].dwControlType == dwType1 )
&& ( paMixerControls[ u ].fdwControl & dwType2 ) ){
r = -1;
//コントロールがアクティブか確認
if ( paMixerControls[ u ].fdwControl & MIXERCONTROL_CONTROLF_DISABLED ){
r = 13;
break;
}
//pmxcduのメモリ確保
switch( funcNo ){
case SET_VOLUME_MUTE_MAIN:
pmxcdb = ( MIXERCONTROLDETAILS_BOOLEAN * )GlobalAlloc( GPTR , mxl.cChannels * sizeof( MIXERCONTROLDETAILS_BOOLEAN ) );
break;
case GET_VOLUME_MUTE_MAIN:
pmxcdb = ( MIXERCONTROLDETAILS_BOOLEAN * )GlobalAlloc( GPTR , mxl.cChannels * sizeof( MIXERCONTROLDETAILS_BOOLEAN ) );
break;
}
if ( pmxcdb == NULL ){
r = 14;
break;
}
//MIXERCONTROLDETAILS構造体の設定
mxcd.cbStruct = sizeof( MIXERCONTROLDETAILS );
mxcd.dwControlID = paMixerControls[ u ].dwControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = paMixerControls[ u ].cMultipleItems;
mxcd.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN );
mxcd.paDetails = pmxcdb;
rc = mixerGetControlDetails( ( HMIXEROBJ )hmx , &mxcd , 0L );
if ( rc != MMSYSERR_NOERROR ){
r = 30;
} else {
switch( funcNo ){
case SET_VOLUME_MUTE_MAIN:
//メインボリュームの設定
pmxcdb->fValue = *lmute;
rc = mixerSetControlDetails( ( HMIXEROBJ )hmx , &mxcd , 0L );
if ( rc != MMSYSERR_NOERROR ){
r = 31;
} else
fDone = TRUE;
break;
case GET_VOLUME_MUTE_MAIN:
//メインボリュームの数値
*lmute = pmxcdb->fValue;
fDone = TRUE;
break;
}
}
GlobalFree( ( HGLOBAL )pmxcdb );
break;
}
}
}
}
GlobalFree( ( HGLOBAL )paMixerControls );
if ( fDone )
break;
}
break;
case 1:
// 通常ボリューム側処理
uConnections = ( UINT )mxl.cConnections;
for ( uConnect = 0 ; uConnect < uConnections ; uConnect++ ){
mxl.cbStruct = sizeof( mxl );
mxl.dwDestination = uDest;
mxl.dwSource = uConnect;
rc = mixerGetLineInfo( ( HMIXEROBJ )hmx , &mxl , MIXER_GETLINEINFOF_SOURCE );
if ( rc != MMSYSERR_NOERROR ){
r = 40;
break;
}
if ( uDest == ( UINT )destNo
&& mxl.dwComponentType == ( DWORD )tdwComponentType ){
r = 0;
rc = mixerGetLineInfo( ( HMIXEROBJ )hmx , &mxl , MIXER_GETLINEINFOF_LINEID );
if ( rc != MMSYSERR_NOERROR ){
r = 4;
break;
}
if ( mxl.cControls == 0 ){
r = 5;
break;
}
//PMIXERCONTROL構造体の配列のためのメモリを割り当てる
paMixerControls = ( PMIXERCONTROL )GlobalAlloc( GPTR
, sizeof( MIXERCONTROL )
* mxl.cControls );
if ( !paMixerControls ){
r = 10;
break;
}
//MIXERLINECONTROLS構造体を設定
mxlc.cbStruct = sizeof( mxlc );
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlID = 0;
mxlc.dwControlType = 0;
mxlc.cControls = mxl.cControls;
mxlc.cbmxctrl = sizeof( MIXERCONTROL );
mxlc.pamxctrl = paMixerControls;
rc = mixerGetLineControls( ( HMIXEROBJ )hmx , &mxlc , MIXER_GETLINECONTROLSF_ALL );
if ( rc != MMSYSERR_NOERROR ){
r = 11;
} else {
UINT u;
for ( u = 0 ; u < mxlc.cControls ; u++ ){
if ( dwType2 == -1 ){
if ( paMixerControls[ u ].dwControlType == dwType1 ){
r = -1;
//正しいコントロールかどうか確認
if ( !( paMixerControls[ u ].dwControlType & dwType1 ) ){
r = 12;
break;
}
//コントロールがアクティブか確認
if ( paMixerControls[ u ].fdwControl & MIXERCONTROL_CONTROLF_DISABLED ){
r = 13;
break;
}
//pmxcduのメモリ確保
pmxcdu = ( MIXERCONTROLDETAILS_UNSIGNED * )GlobalAlloc( GPTR , mxl.cChannels * sizeof( MIXERCONTROLDETAILS_UNSIGNED ) );
//MIXERCONTROLDETAILS構造体の設定
mxcd.cbStruct = sizeof( MIXERCONTROLDETAILS );
mxcd.dwControlID = paMixerControls[ u ].dwControlID;
mxcd.cChannels = mxl.cChannels;
mxcd.cMultipleItems = paMixerControls[ u ].cMultipleItems;
mxcd.cbDetails = sizeof( MIXERCONTROLDETAILS_UNSIGNED );
mxcd.paDetails = pmxcdu;
rc = mixerGetControlDetails( ( HMIXEROBJ )hmx , &mxcd , 0L );
if ( rc != MMSYSERR_NOERROR ){
r = 30;
} else {
switch( funcNo ){
case SET_VOLUME_NORMAL:
//メインボリュームの設定
pmxcdu[ 0 ].dwValue = ( DWORD )*lvol;
pmxcdu[ 1 ].dwValue = ( DWORD )*rvol;
rc = mixerSetControlDetails( ( HMIXEROBJ )hmx , &mxcd , 0L );
if ( rc != MMSYSERR_NOERROR ){
r = 31;
} else
fDone = TRUE;
break;
case GET_VOLUME_NORMAL:
//メインボリュームの数値
*lvol = pmxcdu[ 0 ].dwValue;
*rvol = pmxcdu[ 1 ].dwValue;
fDone = TRUE;
break;
}
}
GlobalFree( ( HGLOBAL )pmxcdu );
break;
}
} else {
if ( ( paMixerControls[ u ].dwControlType == dwType1 )
&& ( paMixerControls[ u ].fdwControl & dwType2 ) ){
r = -1;
//正しいコントロールかどうか確認
if ( !( paMixerControls[ u ].dwControlType & dwType1 ) ){
r = 12;
break;
}
//コントロールがアクティブか確認
if ( paMixerControls[ u ].fdwControl & MIXERCONTROL_CONTROLF_DISABLED ){
r = 13;
break;
}
//pmxcduのメモリ確保
pmxcdb = ( MIXERCONTROLDETAILS_BOOLEAN * )GlobalAlloc( GPTR , mxl.cChannels * sizeof( MIXERCONTROLDETAILS_BOOLEAN ) );
if ( pmxcdb == NULL ){
r = 14;
break;
}
//MIXERCONTROLDETAILS構造体の設定
mxcd.cbStruct = sizeof( MIXERCONTROLDETAILS );
mxcd.dwControlID = paMixerControls[ u ].dwControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = paMixerControls[ u ].cMultipleItems;
mxcd.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN );
mxcd.paDetails = pmxcdb;
rc = mixerGetControlDetails( ( HMIXEROBJ )hmx , &mxcd , 0L );
if ( rc != MMSYSERR_NOERROR ){
r = 30;
} else {
switch( funcNo ){
case SET_VOLUME_MUTE_NORMAL:
//メインボリュームの設定
pmxcdb->fValue = ( DWORD )*lmute;
rc = mixerSetControlDetails( ( HMIXEROBJ )hmx , &mxcd , MIXER_SETCONTROLDETAILSF_VALUE );
if ( rc != MMSYSERR_NOERROR ){
r = 31;
} else
fDone = TRUE;
break;
case GET_VOLUME_MUTE_NORMAL:
//メインボリュームの数値
*lmute = pmxcdb->fValue;
fDone = TRUE;
break;
}
}
GlobalFree( ( HGLOBAL )pmxcdb );
break;
}
}
}
}
GlobalFree( ( HGLOBAL )paMixerControls );
if ( fDone )
break;
}
}
break;
case 2:
r = 4;
if ( uDest != ( UINT )destNo )
break;
UINT u , uMaxConnections;
int Index = -1 , j;
uMaxConnections = mxl.cConnections;
rc = mixerGetLineInfo( ( HMIXEROBJ )hmx , &mxl , MIXER_GETLINEINFOF_LINEID );
if ( rc != MMSYSERR_NOERROR ){
r = 4;
break;
}
if ( mxl.cControls == 0 ){
r = 5;
break;
}
paMixerControls = ( PMIXERCONTROL )GlobalAlloc( GPTR , sizeof( MIXERCONTROL ) * mxl.cControls );
if ( !paMixerControls ){
r = 10;
break;
}
//MIXERLINECONTROLS構造体を設定
mxlc.cbStruct = sizeof( mxlc );
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlID = 0;
mxlc.dwControlType = 0;
mxlc.cControls = mxl.cControls;
mxlc.cbmxctrl = sizeof( MIXERCONTROL );
mxlc.pamxctrl = paMixerControls;
rc = mixerGetLineControls( ( HMIXEROBJ )hmx , &mxlc , MIXER_GETLINECONTROLSF_ALL );
if ( rc == MMSYSERR_NOERROR ){
for ( u = 0 ; u < mxlc.cControls ; u++ ){
if ( ( ( paMixerControls[ u ].dwControlType == MIXERCONTROL_CONTROLTYPE_MUX )
|| ( paMixerControls[ u ].dwControlType == MIXERCONTROL_CONTROLTYPE_MIXER ) )
&& ( paMixerControls[ u ].fdwControl & dwType2 ) ){
pmxcdl = ( MIXERCONTROLDETAILS_LISTTEXT * )GlobalAlloc( GPTR , paMixerControls[ u ].cMultipleItems * sizeof( MIXERCONTROLDETAILS_LISTTEXT ) );
//MIXERCONTROLDETAILS構造体の設定
mxcd.cbStruct = sizeof( MIXERCONTROLDETAILS );
mxcd.dwControlID = 0;
mxcd.cChannels = 1;
mxcd.cMultipleItems = paMixerControls[ u ].cMultipleItems;
mxcd.cbDetails = sizeof( MIXERCONTROLDETAILS_LISTTEXT );
mxcd.paDetails = pmxcdl;
rc = mixerGetControlDetails( ( HMIXEROBJ )hmx , &mxcd , MIXER_GETCONTROLDETAILSF_LISTTEXT );
if ( rc == MMSYSERR_NOERROR ){
for ( j = 0 ; j < ( int )paMixerControls[ u ].cMultipleItems ; j++ ){
if ( pmxcdl[ j ].dwParam2 == ( DWORD )dwType0 ){
Index = ( int )j;
break;
}
}
}
GlobalFree( ( HGLOBAL )pmxcdl );
}
if ( Index != -1 )
break;
}
}
GlobalFree( ( HGLOBAL )paMixerControls );
if ( Index != -1 ){
//pmxcduのメモリ確保
pmxcdb = ( MIXERCONTROLDETAILS_BOOLEAN * )GlobalAlloc( GPTR , uMaxConnections * sizeof( MIXERCONTROLDETAILS_BOOLEAN ) );
if ( pmxcdb ){
//MIXERCONTROLDETAILS構造体の設定
mxcd.cbStruct = sizeof( MIXERCONTROLDETAILS );
mxcd.dwControlID = 0;
mxcd.cChannels = 1;
mxcd.cMultipleItems = uMaxConnections;
mxcd.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN );
mxcd.paDetails = pmxcdb;
rc = mixerGetControlDetails( ( HMIXEROBJ )hmx , &mxcd , MIXER_GETCONTROLDETAILSF_VALUE );
if ( rc == MMSYSERR_NOERROR ){
switch( funcNo ){
case SET_DEVICE_ONOFF:
//メインボリュームの設定
pmxcdb[ Index ].fValue = ( DWORD )*lmute;
rc = mixerSetControlDetails( ( HMIXEROBJ )hmx , &mxcd , MIXER_SETCONTROLDETAILSF_VALUE );
if ( rc != MMSYSERR_NOERROR ){
r = 31;
} else
fDone = TRUE;
break;
case GET_DEVICE_ONOFF:
//メインボリュームの数値
*lmute = pmxcdb[ Index ].fValue;
fDone = TRUE;
break;
}
}
GlobalFree( ( HGLOBAL )pmxcdb );
}
}
break;
}
if ( fDone ){
r = 0;
break;
}
}
rc = mixerClose( hmx );
return( r );
}
以上。
ありがとうございます!ですが、仕事の都合上やはりVBで制作しなければ
ならないのでVBで頑張ってみます。
一応、mciSendStringを使ってマイクからwavファイルに録音することは出来ました
が、保存するときに
'録音した物をセーブ
mciSendString "save file c:\ウェブ\test.wav", ret, 255, 0
この命令を使っているので毎回[test.wav]のファイル名で保存されてしまいます。
毎回自分でファイル名を指定出来なくて今つまっています。
解決しました。岡田 之仁さん、いろいろありがとうございました!
ツイート | ![]() |