サウンドデコーダーを作りたいのですが・・

解決


KEN  2003-08-21 03:07:18  No: 79094

Windowsにあるサウンドデコーダーのようなツールを作ろうとしているんですが
VBでマイクからwav形式(8kHz,8bitか11.025kHz,8bit)で録音するのはどう
すれば良いのでしょうか?
MMcontrolやmcisendstringやwaveInxxxなどを使っていろいろやってみたの
ですが、うまく行きませんでした。私が初心者なせいもあるとは思いますが
詳しい方おりましたら助けてください。。よろしくお願いします。


岡田 之仁  2003-08-21 14:53:19  No: 79095

私がやった方法では・・・

録音ルーチンは、ActiveXで、C言語(C++で、MFC使ってます)を用いて
作成しました。

とも言うのも、録音ルーチンは、オーディオデバイスからのコールバック
ルーチンとしての機能が必要であった為、VBの.BASに記述して・・・
という裏技も可能なのですが、速度が要求される部分だった為、VBのみ
での記述では、到底処理しきれるものではないと思った為です。

今は他によいものがあるかもしれませんが・・・
VBのみでのレコーディング機能の作成は、かなり無理があると思います
が・・・

以上。


KEN  2003-08-21 17:51:01  No: 79096

すいません。訂正個所がありました…
WindowsのサウンドデコーダーではなくWindowsのサウンドレコーダーでした。


岡田 之仁  2003-08-21 19:26:52  No: 79097

まず、デコーダという語句を、勝手にレコーダと読み替えて上記書き込みを
していました・・・

それと・・・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 );
}

以上。


KEN  2003-08-22 01:50:35  No: 79098

ありがとうございます!ですが、仕事の都合上やはりVBで制作しなければ
ならないのでVBで頑張ってみます。
一応、mciSendStringを使ってマイクからwavファイルに録音することは出来ました
が、保存するときに

'録音した物をセーブ
mciSendString "save file c:\ウェブ\test.wav", ret, 255, 0  
この命令を使っているので毎回[test.wav]のファイル名で保存されてしまいます。
毎回自分でファイル名を指定出来なくて今つまっています。


KEN  2003-08-23 00:56:35  No: 79099

解決しました。岡田 之仁さん、いろいろありがとうございました!


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加