• 11249阅读
  • 7回复

请教QT在不同平台下的音频采集方案(已实现在windows环境下) [复制链接]

上一主题 下一主题
离线gaoyuke
 
只看楼主 正序阅读 楼主  发表于: 2009-01-21
— 本帖被 XChinux 执行加亮操作(2009-01-22) —
关键词: 音频采集
想做一个支持多平台的QT音频采集。不知道在windows、linux和symbian下有什么解决方案?
不知道有没有什么库可以用?

搜了下portAudio是c写的一个跨平台音频库
directshow貌似也可以,c++的
貌似可以调用mmsystem.dll来使用waveInOpen等函数


09-1-29
windows下音频采集
  windows下的音频采集我最后还是没用portAudio来做。觉得在windows下还是用windows的办法吧,最后选择了wavein、waveout函数簇。下面简单介绍下我的实现方法(和mfc差

不多):
(一)用到的函数及类库
一、wavein函数簇
1.waveinopen
2.waveinprepareheader
3.waveinaddbuffer
4.waveinstart

二、waveout函数簇
1.waveoutopen
2.waveoutprepareheader
3.waveOutWrite


(二)实现代码
一、录音
void audioDevice::record()
{
  if(bRecording == true){waveInReset(hWaveIn);}//如果正在录制,重置输入设备


  if (!pBuffer1 || !pBuffer2)
    {
        if (pBuffer1) free(pBuffer1);
        if (pBuffer2) free(pBuffer2);
        return;
    }

  waveform.wFormatTag=WAVE_FORMAT_PCM;
  waveform.nChannels=1;
  waveform.nSamplesPerSec=44100;
  waveform.nAvgBytesPerSec=44100;
  waveform.nBlockAlign=1;
  waveform.wBitsPerSample=8;
  waveform.cbSize=0;

  if (waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,(DWORD)WaveInCallback,0,CALLBACK_FUNCTION)) {
                free(pBuffer1);
                free(pBuffer2);
                qWarning( "can not open audio capture device.Return");
        }

  for(int i=0;i<=3;i++){
        pWaveHdr1->lpData=(LPSTR)pBuffer1;
        pWaveHdr1->dwBufferLength=INP_BUFFER_SIZE;
        pWaveHdr1->dwBytesRecorded=0;
        pWaveHdr1->dwUser=0;
        pWaveHdr1->dwFlags=0;
        pWaveHdr1->dwLoops=0;
        pWaveHdr1->lpNext=NULL;
        pWaveHdr1->reserved=0;

        waveInPrepareHeader(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));



        //////////////////////////////////////////////////////////////////////////

        // Add the buffers

        waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
    }

        // Begin sampling
        waveInStart (hWaveIn) ;


        qWarning( "dwBytesRecorded.Return %d",pWaveHdr1->dwBytesRecorded);


}

二、播放
void audioDevice::play()
{
    if(bPlaying == true){waveOutReset(hWaveOut);}//如果正在播放,重置输出设备
/*
    pNewBuffer = (PBYTE)realloc (pSaveBuffer, dwDataLength + pWaveHdr1->dwBytesRecorded) ;
qWarning( "pNewBuffer.Return %d",pNewBuffer);
        if (pNewBuffer == NULL)
        {
                waveInClose (hWaveIn) ;

                return ;
        }

        pSaveBuffer = pNewBuffer ;
        qWarning( "pSaveBuffer.Return %d",pSaveBuffer);
        //////////////////////////////////////////////////////////////////////////

        CopyMemory (pSaveBuffer + dwDataLength, ((PWAVEHDR) pWaveHdr1)->lpData,
                ((PWAVEHDR) pWaveHdr1)->dwBytesRecorded) ;

        dwDataLength += pWaveHdr1->dwBytesRecorded ;
qWarning( "dwDataLength.Return %d",dwDataLength);
*/
  //open waveform audio for output
        waveform.wFormatTag        =    WAVE_FORMAT_PCM;
        waveform.nChannels        =    1;
        waveform.nSamplesPerSec    =44100;
        waveform.nAvgBytesPerSec=44100;
        waveform.nBlockAlign    =1;
        waveform.wBitsPerSample    =8;
        waveform.cbSize            =0;


        int ret = waveOutOpen(&hWaveOut,WAVE_MAPPER,&waveform,0,0,CALLBACK_NULL);
        if (ret) {

                qWarning( "can not open audio play device.Return %d",ret);
        }
        qWarning( "pSaveBuffer.Return %d",pSaveBuffer);


        pWaveHdr1->lpData = (LPSTR)pSaveBuffer ;
        qWarning( "dwDataLength.Return %d",dwDataLength);
        pWaveHdr1->dwBufferLength  = dwDataLength ;
        pWaveHdr1->dwBytesRecorded = 0 ;
        pWaveHdr1->dwUser          = 0 ;
        pWaveHdr1->dwFlags        = WHDR_BEGINLOOP | WHDR_ENDLOOP ;
        pWaveHdr1->dwLoops        = 0 ;
        pWaveHdr1->lpNext          = NULL ;
        pWaveHdr1->reserved        = 0 ;

        // Prepare and write
        waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
        waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;

        bPlaying = true;


}

三、回调函数
  使用waveinopen和waveoutopen自带的回调函数机制,对录音和播放时发出的消息进行处理。本来打算用mfc的消息映射,不过Qt和MFC的头文件及库交叉使用的方法我不会,最

后为了避重就轻,选择了用回调函数来处理。
1.回调函数的作用
当MM_WOM_DONE、WIM_OPEN、WIM_CLOSE或WIM_DATA消息发出时执行相应操作
2.当WIM_DATA(录音buffer满)发送,调用addNewBuffer存储buffer,然后添加新的buffer到waveheader中继续录音
3.其他信号操作可按你的要求添加

waveinopen函数的回调函数如下

static void CALLBACK
WaveInCallback (HWAVEIN waveindev, UINT uMsg, DWORD dwInstance, DWORD dwParam1,
                  DWORD dwParam2)
{

  switch (uMsg)
    {
      case MM_WOM_DONE:
          qWarning( "MM_WOM_DONE.");
        break;

      case WIM_OPEN:
          qWarning( "Record start.");
          bRecording = true;
        break;
      case WIM_CLOSE:
            qWarning( "Record end.");
        break;
      case WIM_DATA:
            qWarning( "Buffer full.");
            addNewBuffer();

        break;
    }
}
[ 此贴被gaoyuke在2009-01-30 22:06重新编辑 ]
离线gaoyuke
只看该作者 7楼 发表于: 2009-01-30
需要包含的头文件mmsystem.h,windows.h,库winmm.lib
离线diyuanbo

只看该作者 6楼 发表于: 2009-01-22
portaudio为应用提供不依赖于操作系统和音频设备驱动的接口,directsound是
windows下的一种驱动
离线diyuanbo

只看该作者 5楼 发表于: 2009-01-21
可以google一下”portaudio“
离线signallock

只看该作者 4楼 发表于: 2009-01-21
关注
离线gaoyuke
只看该作者 3楼 发表于: 2009-01-21
audio_fd=open("/dev/dsp",O_RDWR)可以在linux下实现,windows和symbian下不知道怎样做??
离线wd007

只看该作者 2楼 发表于: 2009-01-21
不清楚,帮问吧
欢迎访问我的博客,一起学习提高
http://blog.csdn.net/qter_wd007
只看该作者 1楼 发表于: 2009-01-21
Qt uses the Phonon multimedia framework to provide functionality for playback of the most common multimedia formats.

简而言之,回放用的
快速回复
限100 字节
 
上一个 下一个