Mail to Keith Dan
keith的天空
海阔凭鱼跃,天高任鸟飞
posts - 29,comments - 176,trackbacks - 2

应一个朋友委托,做一个录音程序.
我原本以为要用direct来做,先是在google上搜索了一把,收获不大。后来在codeproject上发现一篇文章A full-duplex audio player in C# using the waveIn/waveOut APIs ,原来可以很简单。在System32下原来有一个多媒体处理的API,winmm.dll,发现之非常兴奋,哈哈。
原来微软已经提供了一系列的wavein 和waveout方法,参考了里面一些东西做法。做了一些修改。由于我以前对音频并不怎么了解,特地查了一下音频的有关知识,不了解的朋友也可以了解一下,呵呵,知识共享拉。
其中音频采样率(位/bit),采样率包括32000Hz,44100Hz,48000Hz3种,采样大小分为16位和8位,声道通常就是2(立体声)和1(单声道)了。其中有一个重要的数据叫采样速率,计算公式为采样速率=采样率×采样大小×声道。我们通常比较熟悉的128K的MP3就是44100×16×2=1411.2Kb/s,这样的音频很大,通常10秒种就有1M多。而如果使用模拟信号的话并非采样率越高越好,只会盲目的增加我们文件的大小,只有数字信号的时候才会提高我们的效果。
对于音频这一块,希望其他朋友能提供给一些更多的知识与技术。特别是音频对比和频谱图等等。
那么我们往下看。

//wav头
                long chunksize = fs.Length + 36;
                WriteChars(bw, 
"RIFF");//格式
                bw.Write((int)chunksize);//文件长度(要加上头的36字节)
                WriteChars(bw, "WAVE");//标示
                WriteChars(bw, "fmt ");//fmt
                bw.Write((int)16);//fmt长度
                bw.Write(m_Format.wFormatTag);//压缩模式
                bw.Write(m_Format.nChannels);//声道
                bw.Write(m_Format.nSamplesPerSec);//采样率包含:32000Hz,44100Hz,48000Hz.
                bw.Write(m_Format.nAvgBytesPerSec);//每秒播放字节
                bw.Write(m_Format.nBlockAlign);//位速
                bw.Write(m_Format.wBitsPerSample);//采样大小
                WriteChars(bw,"data");//data标志
                bw.Write(fs.Length);//音频长度

这就是我们需要给wave文件写上的头。
大家查一下winmm.dll就会发现,里面提供了很多有用的API,非常的棒。
// WaveIn calls
        [DllImport(mmdll)]
        
public static extern int waveInGetNumDevs();
        [DllImport(mmdll)]
        
public static extern int waveInAddBuffer(IntPtr hwi, ref WaveHdr pwh, int cbwh);
        [DllImport(mmdll)]
        
public static extern int waveInClose(IntPtr hwi);
        [DllImport(mmdll)]
        
public static extern int waveInOpen(out IntPtr phwi, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags);
        [DllImport(mmdll)]
        
public static extern int waveInPrepareHeader(IntPtr hWaveIn, ref WaveHdr lpWaveInHdr, int uSize);
        [DllImport(mmdll)]
        
public static extern int waveInUnprepareHeader(IntPtr hWaveIn, ref WaveHdr lpWaveInHdr, int uSize);
        [DllImport(mmdll)]
        
public static extern int waveInReset(IntPtr hwi);
        [DllImport(mmdll)]
        
public static extern int waveInStart(IntPtr hwi);
        [DllImport(mmdll)]
        
public static extern int waveInStop(IntPtr hwi);
其中DataArrived方法是委托的方法,它将我们接收到的数据拷贝到m_RecBuffer中,再写入到文件里。在这里我并没有使用MenmoyStream,看到windows录音限制1分钟,我估计它(我并没有认真看过)是讲数据写入内存,再统一存储的,为了没有限制,所以直接用了FileStream,写到文件里了。
private void DataArrived(IntPtr data, int size)
        
{
            
try
            
{
                
if (m_RecBuffer == null || m_RecBuffer.Length < size)
                
{
                    m_RecBuffer 
= new byte[size];
                }

                System.Runtime.InteropServices.Marshal.Copy(data, m_RecBuffer, 
0, size);

                bw_tmp.Write(m_RecBuffer);
                _recordSize
+=m_RecBuffer.Length;
            }

            
catch(Exception e)
            
{
                
return;
            }

        }

里面我加入了一些功能,包括开始,停止,暂停,继续等等。

在此,我想问一下其他朋友,音频的频谱图是基于怎样的算法呢?如何画的?这个我很想了解,有这方面知识的朋友望能告知,给点参考。在此谢过。

Source
--------------------------------------------
参考:
A full-duplex audio player in C# using the waveIn/waveOut APIs
PCM编码及其技术
posted on 2006-12-19 14:42 KeithDan 阅读(4011) 评论(26)  编辑 收藏 所属分类: C#

FeedBack:
2006-12-19 16:10 | neoragex2002      
音频的频谱图:快速傅立叶变换,网上介绍很多
  回复  引用  查看    
2006-12-19 17:06 | 肥仔鱼      
谢谢,测试一把

  回复  引用  查看    
#3楼 [楼主]
2006-12-21 09:33 | KeithDan      
@neoragex2002
好的,我去仔细看下
  回复  引用  查看    
2007-01-26 17:57 | net [未注册用户]
该怎么 查看 winmm.dll 呢?用 Reflector.exe ?
  回复  引用    
2007-01-26 17:58 | net [未注册用户]
我在程序中引用 winmm.dll 怎么不行呢?请您指点
  回复  引用    
#6楼 [楼主]
2007-02-04 17:22 | KeithDan      
@net
调用winmm.dll 不行?我不知道你什么原因,看看才知道
  回复  引用  查看    
2007-04-18 21:34 | 蛙蛙池塘      
你好,我把你的代码用在我一个小软件里了,可以吗?
  回复  引用  查看    
#8楼 [楼主]
2007-04-27 16:14 | KeithDan      
@蛙蛙池塘
可以啊,呵呵
  回复  引用  查看    
2007-05-03 16:14 | kaven [未注册用户]
我现在也在做一个录音程序,楼主能否将源代码共享一下,谢谢!
我的邮箱是quncy168@163.com
  回复  引用    
2007-05-28 14:37 | qfluo [未注册用户]
楼主,我现在也是在做录音程序,同样是使用wave in函数,楼主能否发一份源码给我学习一下啊1!谢谢
qfluowing@126.com
qq:215337979
  回复  引用    
2007-05-28 16:09 | yytoday [未注册用户]
楼主,我现在也正准备做录音程序,能不能把你的源码让我学习一下,发邮件给我:yytoday@163.com
谢谢
  回复  引用    
#12楼 [楼主]
2007-05-28 23:17 | KeithDan      
@qfluo
@yytoday
@kaven
我这里已经附带有demo的源代码啊,大家都已经下载来学习研究
  回复  引用  查看    
2007-05-30 14:38 | Jeffers Yuan      
有没有什么办法直接录制成mp3格式?
  回复  引用  查看    
2007-06-10 02:08 | emu32.com [未注册用户]
要画频谱图要用到 原始声音数据 也就是PCM DATA
如何获取? 其实就是 WAV的数据部分.去除了Wav文件头44个字节之后的数据

无论何种格式最终都需要转化为 WAV才能播放.
画波形图 直接把WAV的数据部分读出来,再加上坐标变换就可以画出来了.

要画频谱图的话 要经过快速傅里叶转换,之后获得一个个点。
只后就可以通过坐标变换 画出来了.

可以参考一套基于DSPack开源的Delphi控件 DCDSPFilter
官方地址 : http://dsp-worx.de

我的主页地址:http://www.emu32.com/
  回复  引用    
2007-08-24 12:35 | ¾ [未注册用户]
源代码里附带的程序不能用。。。
  回复  引用    
2007-09-19 22:11 | treesky [未注册用户]
来学习下 一直没有找到这个方面的资料!谢谢
  回复  引用    
2008-01-09 19:40 | snow009 [未注册用户]
呵呵,我也找到用mmdll例子了,正好和你的一起参考,谢谢哦,我一开始用winform,direct作的录音,但郁闷的是在别人的机器上不好使,出错,direct版本的问题,现在录音问题基本解决了,请问有什么方法可以控制麦克风,输入设备?比如静音,恢复?,我找了很多比如用mix的api但都是c++的,有winform的吗?c#的?谢谢了
  回复  引用    
2008-01-14 10:21 | bugboy [未注册用户]
为什么录音后文件用Media Player 播放不了呢??
  回复  引用    
2008-01-14 11:10 | bugboy [未注册用户]
请问在 WM5 平台下用C#怎么实现录音??
希望能给份源码:wqzh_1985@126.com
非常谢谢!!
  回复  引用    
2008-02-22 19:38 | jianyi0115      
学习 ~
  回复  引用  查看    
#21楼 [楼主]
2008-02-24 22:38 | KeithDan      
@snow009
静音和恢复都可以通过API来控制,具体是哪个函数要查一下
你看到的C++的都可以作为参考,把该API函数作为非托管静态函数申明调用即可
  回复  引用  查看    
2008-04-23 17:53 | snow009 [未注册用户]
十分感谢楼主!!我的问题解决了:)谢谢了
  回复  引用    
2008-05-04 00:18 | www.cn28.com [未注册用户]
请问有无办法录制声卡播出来的声音?
  回复  引用    
2008-05-29 13:25 | nash [未注册用户]
感谢兄弟贡献出了源代码,谢谢!
  回复  引用    
2008-06-13 18:14 | 陌生的友人 [未注册用户]
非常感谢~

  回复  引用    
2008-09-27 21:53 | zjk [未注册用户]
请问在WinForm下可以实现直接录制mp3格式的文件吗,

我现在用C#在VS2005平台下开以WinForm程序,要做一个录音的工具,可以把源码分享一下吗?

我的邮箱:zjk537@126.com
  回复  引用    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-12-20 23:21 编辑过


相关链接: