新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 C/C++编程思想 』 → 基于API的录音机程序 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 4919 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 基于API的录音机程序 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 基于API的录音机程序

    一、数字音频基础知识

    Fourier级数:
    任何周期的波形可以分解成多个正弦波,这些正弦波的频率都是整数倍。级数中其他正线波的频率是基础频率的整数倍。基础频率称为一级谐波。

    PCM:
    pulse code modulation,脉冲编码调制,即对波形按照固定周期频率采样。为了保证采样后数据质量,采样频率必须是样本声音最高频率的两倍,这就是Nyquist频率。
    样本大小:采样后用于存储振幅级的位数,实际就是脉冲编码的阶梯数,位数越大表明精度越高,这一点学过数字逻辑电路的应该清楚。

    声音强度:
    波形振幅的平方。两个声音强度上的差常以分贝(db)为单位来度量,

    计算公式如下:
    20*log(A1/A2)分贝。A1,A2为两个声音的振幅。如果采样大小为8位,则采样的动态范围为20*log(256)分贝=48db。如果样本大小为16位,则采样动态范围为20*log(65536)大约是96分贝,接近了人听觉极限和痛苦极限,是再线音乐的理想范围。windows同时支持8位和16位的采样大小。

    二、相关API函数,结构,消息
    对于录音设备来说,windows 提供了一组wave***的函数,比较重要的有以下几个:

    打开录音设备函数
    MMRESULT waveInOpen(
    LPHWAVEIN phwi,      //输入设备句柄
    UINT uDeviceID,      //输入设备ID
    LPWAVEFORMATEX pwfx,    //录音格式指针
    DWORD dwCallback,     //处理MM_WIM_***消息的回调函数或窗口句柄,线程ID
    DWORD dwCallbackInstance,  
    DWORD fdwOpen       //处理消息方式的符号位
    );
    为录音设备准备缓存函数
    MMRESULT waveInPrepareHeader( HWAVEIN hwi, LPWAVEHDR pwh, UINT bwh );  
    给输入设备增加一个缓存
    MMRESULT waveInAddBuffer( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh );  
    开始录音
    MMRESULT waveInStart( HWAVEIN hwi );  
    清除缓存
    MMRESULT waveInUnprepareHeader( HWAVEIN hwi,LPWAVEHDR pwh, UINT cbwh);  
    停止录音
    MMRESULT waveInReset( HWAVEIN hwi );  
    关闭录音设备
    MMRESULT waveInClose( HWAVEIN hwi );  
    Wave_audio数据格式
    typedef struct {
      WORD wFormatTag; //数据格式,一般为WAVE_FORMAT_PCM即脉冲编码
      WORD nChannels; //声道
      DWORD nSamplesPerSec; //采样频率
      DWORD nAvgBytesPerSec; //每秒数据量
      WORD nBlockAlign;
      WORD wBitsPerSample;//样本大小
      WORD cbSize;
    } WAVEFORMATEX;  
    waveform-audio 缓存格式 
    typedef struct {
      LPSTR lpData; //内存指针
      DWORD dwBufferLength;//长度
      DWORD dwBytesRecorded; //已录音的字节长度
      DWORD dwUser;
      DWORD dwFlags;
      DWORD dwLoops; //循环次数
      struct wavehdr_tag * lpNext;
      DWORD reserved;
    } WAVEHDR;  
    相关消息 
    MM_WIM_OPEN:打开设备时消息,在此期间我们可以进行一些初始化工作
    MM_WIM_DATA:当缓存已满或者停止录音时的消息,处理这个消息可以对缓存进行重新分配,实现不限长度录音
    MM_WIM_CLOSE:关闭录音设备时的消息。
    相对于录音来说,回放就简单的多了,用到的函数主要有以下几个:
    打开回放设备 
    MMRESULT waveOutOpen(
    LPHWAVEOUT phwo,      
    UINT uDeviceID,       
    LPWAVEFORMATEX pwfx,    
    DWORD dwCallback,      
    DWORD dwCallbackInstance,  
    DWORD fdwOpen        
    );  
    为回放设备准备内存块 
    MMRESULT waveOutPrepareHeader(
    HWAVEOUT hwo,  
    LPWAVEHDR pwh,
    UINT cbwh    
    );
    写数据(放音) 
    MMRESULT waveOutWrite(
    HWAVEOUT hwo,  
    LPWAVEHDR pwh,
    UINT cbwh    
    );
    相应的也有三个消息,用法跟录音的类似:

    三、程序设计

    一个录音程序的简单流程: 打开录音设备waveInOpen===>准备wave数据头waveInPrepareHeader===>
    准备数据块waveInAddBuffer===>开始录音waveInStart===>停止录音(waveInReset) ===>
    关闭录音设备(waveInClose)
    当开始录音后当buffer已满时,将收到MM_WIM_DATA消息,处理该消息可以保存已录好数据。

    回放程序比这个要简单的多: 打开回放设备waveOutOpen===>准备wave数据头waveOutPrepareHeader===>写wave数据waveOutWrite===>
    停止放音(waveOutRest) ===>关闭回放设备(waveOutClose)
    如何处理MM消息: MSDN告诉我们主要有 CALLBACK_FUNCTION、CALL_BACKTHREAD、CALLBACK_WINDOW 三种方式,常用的是
    Thread,window方式。
    线程模式
    waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,m_ThreadID,NULL,CALLBACK_THREAD),我们可以继承MFC的CwinThread类,只要相应的处理线程消息即可。
    MFC线程消息的宏为:

      ON_THREAD_MESSAGE,
    可以这样添加消息映射:   ON_THREAD_MESSAGE(MM_WIM_CLOSE, OnMM_WIM_CLOSE)  
    窗口模式
    类似于线程模式,参见源程序即可。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/8/6 8:52:00
     
     taoyx 帅哥哟,离线,有人找我吗?
      
      
      等级:大一(高数修炼中)
      文章:12
      积分:104
      门派:XML.ORG.CN
      注册:2007/8/9

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给taoyx发送一个短消息 把taoyx加入好友 查看taoyx的个人资料 搜索taoyx在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看taoyx的博客2
    发贴心情 
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/8/9 10:57:00
     
     taoyx 帅哥哟,离线,有人找我吗?
      
      
      等级:大一(高数修炼中)
      文章:12
      积分:104
      门派:XML.ORG.CN
      注册:2007/8/9

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给taoyx发送一个短消息 把taoyx加入好友 查看taoyx的个人资料 搜索taoyx在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看taoyx的博客3
    发贴心情 
    再顶
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/8/9 10:57:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/28 15:44:45

    本主题贴数3,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.500ms