摘要:语音通话已经是IM的基本功能了,qq,MSN甚至连刚出来的百度HI都自带语音聊天的功能,大家可能觉得很炫,其实大家都是用的windows平台上的API,懂了原理之后自己也可以做,再说了微软也提供了DirectSound的托管互操作程序集,使.net开发人员也很容易的介入到这个领域,甚至你还可以写一个能跑在window mobile上的语音电话,现在好多手机都支持wifi,这样一个简单的wifi电话就由你的手里诞生了。本帖来和大家一起看看如何来做网络电话。

思路:要想做一个网络电话,基本遵循以下步骤

1、一方实时的录音,把模拟信号转换成数字信号;

2、把声音实时压缩;

3、通过网络协议把压缩后的数据传输给接收方;

4、接收方解压缩接受到的音频数据;

5、实时的把接收到的数字信号转换成模拟信号并播放出来。

下面我们来看看每一步面临的挑战及其解决方案。

1、第一步,实时录音,DirectxSound有录音方面的API,托管的类分别是Microsoft.DirectX.DirectSound.CaptureDevicesCollection,Microsoft.DirectX.DirectSound.Capture和Microsoft.DirectX.DirectSound.CaptureBuffer,CaptureDevicesCollection用来枚举本机的可用的录音设备,Capture则表示一个录音设备,CaptureBuffer是用来存放录音数据的缓冲区,我们开始录音后,音频数据会不断的写入到环形的流式缓冲区,然后我们定期从缓冲区中把录音数据取出来返回给上层应用层就可以了。关于环形的流式缓冲区,可以看参考链接部分。

2、声音的压缩是一个很难抉择的步骤,默认的DirectSound只能播放和录制PCM格式(WAV)的音频数据,但这种声音格式特别大。常用的声音压缩格式有h.7231,gsm,amr,h.711等等,各种压缩算法都有自己的码率和适用范围。因为我们做的是互联网的语音电话,不考虑慢速网络和无线连接下的情况,也不用考虑终端设备的CPU能不能支持我们选用的压缩算法,我们做的语音电话双方都是PC机,应该什么解压缩算法都不会引起什么性能上的问题,所以只要网络快一些,选择哪个压缩算法都无所谓了,网上有h.711的压缩算法,我打算就采用这个,他的码率是64Kbps,比PCM的1.544Mbps和2.048Mbps要小的多。然后我们进行了音频数据压缩后,还可以对字节流进行GZIP或者7ZIP压缩,前者用SharpZip,后者7zip的官方有c#的使用代码,大家可以测试一下这两个算法的性能后做出适合自己的决定。关于各种压缩格式的特性可以参考我做的PPT及提供的参考链接。

3、网络电话注重实时性,而把声音从网络上传输就要走IP网络,而IP网络不是一个等时系统,所以我们就要尽量的去模拟实时的语音传输,提到实时,肯定UDP比TCP要实时,因为TCP要保证传输的可靠性,有序性等,而专门用于实时传输有一个应用层协议是RTP协议,这个协议一般就是建立在UDP基础上的,它在每个包头提供了一些序列号、时间戳等信息,但UDP本身并不会使用这些信息,这时候就有一个RTCP协议来用这些信息进行流量控制和拥塞控制,比如说RTCP检测到网络拥挤,会告诉发送方变换一种低码率的语音压缩算法来传输数据。这些大多都需要自己去实现,本文的源码没有去实现这些,关于RTP和RTCP可以参考相关资料或者我做的PPT。

4、每个压缩算法都有相应的解压缩算法,呵呵。

5、播放声音肯定也需要用到DS,也需要用到StreamBuffer,大致流程如下

1)创建一个声音设备Microsoft.DirectX.DirectSound.Device dev = new Microsoft.DirectX.DirectSound.Device();

2)设置协调级别dev.SetCooperativeLevel(this, Microsoft.DirectX.DirectSound.CooperativeLevel.Normal);

3)创建声音格式、缓冲区描述、及辅助缓冲区;

4)给辅助缓冲区设定通知;

5)用声音数据填满缓冲区;

6)播放缓冲区的声音数据,播放到一定的通知点,通知填充线程,填充新的声音数据;

7)循环第6步,直到没有新的声音数据填充到缓冲区。

具体的过程参考PPT或者具体代码。


版权声明:

附件源代码里的CaptureSound,SoundPlayer和CircularBuffer类反编译自随意桌面的代码(注释是我加的),版权归作者所有。

PPT里的图片和一些文字选自一个叫做ch11-DxSound&Input2.ppt的文件,源链接已丢失,还有一些选择一个叫做“SIP之 穿越NAT.ppt”的文件,网上可以搜索到,版权均归原作者所有,源作者要是再引用别人的东西,我就不知道了。

下面看一些具体的代码

用户创建声音格式

 


[转]c#编写网络电话_数据public class DirectSoundManager

[转]c#编写网络电话_microsoft_02[转]c#编写网络电话_数据_03[转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05    public static WaveFormat CreateWaveFormat(int hz, short bits, short channels)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        WaveFormat format = new WaveFormat();

[转]c#编写网络电话_数据_05        //声音的格式,通常使用WAVE_FORMAT_PCM来设定,

[转]c#编写网络电话_数据_05        //因为PCM是比较常用的声音格式。

[转]c#编写网络电话_数据_05        format.FormatTag = WaveFormatTag.Pcm;

[转]c#编写网络电话_数据_05        //采样率(单位:赫兹)典型值:11025、22050、44100Hz

[转]c#编写网络电话_数据_05        format.SamplesPerSecond = hz;

[转]c#编写网络电话_数据_05        //每个采样点数;8-bit或16-bit;

[转]c#编写网络电话_数据_05        format.BitsPerSample = bits;

[转]c#编写网络电话_数据_05        //声道的设置,当其值为1时是单声道,为2时是双声道;

[转]c#编写网络电话_数据_05        format.Channels = channels;

[转]c#编写网络电话_数据_05        //每个采样点字节数

[转]c#编写网络电话_数据_05        format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / 8));

[转]c#编写网络电话_数据_05        //平均传输率,每秒的数据流量

[转]c#编写网络电话_数据_05        format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond;

[转]c#编写网络电话_数据_05        return format;

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    属性#region 属性

[转]c#编写网络电话_数据_05    // Properties

[转]c#编写网络电话_数据_05    public static WaveFormat DefaultFormat

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        get

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            return WaveFormat_8000_8_1;

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public static WaveFormat WaveFormat_11025_8_1

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        get

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            return CreateWaveFormat(0x2b11, 8, 1);

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public static WaveFormat WaveFormat_22050_16_2

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        get

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            return CreateWaveFormat(0x5622, 0x10, 2);

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public static WaveFormat WaveFormat_44100_16_2

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        get

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            return CreateWaveFormat(0xac44, 0x10, 2);

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public static WaveFormat WaveFormat_8000_8_1

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        get

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            return CreateWaveFormat(0x1f40, 8, 1);

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    } 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_microsoft_89}



用于播放流式声音

   

 


[转]c#编写网络电话_数据public class SoundPlayer : IDisposable

[转]c#编写网络电话_microsoft_02[转]c#编写网络电话_数据_03[转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    私有成员#region 私有成员

[转]c#编写网络电话_数据_05    private const int MaxLatencyMs = 300;

[转]c#编写网络电话_数据_05    private const int NumberRecordNotifications = 4;

[转]c#编写网络电话_数据_05    private readonly CircularBuffer circularBuffer;

[转]c#编写网络电话_数据_05    private readonly int m_BufferBytes;

[转]c#编写网络电话_数据_05    private readonly bool m_OwnsDevice;

[转]c#编写网络电话_数据_05    private readonly int notifySize;

[转]c#编写网络电话_数据_05    private readonly BufferPositionNotify[] positionNotify;

[转]c#编写网络电话_数据_05    private bool isRunning;

[转]c#编写网络电话_数据_05    private SecondaryBuffer m_Buffer;

[转]c#编写网络电话_数据_05    private Device m_Device;

[转]c#编写网络电话_数据_05    private int nextWriteOffset;

[转]c#编写网络电话_数据_05    private AutoResetEvent notificationEvent;

[转]c#编写网络电话_数据_05    private Notify notify;

[转]c#编写网络电话_数据_05    private Thread notifyThread; 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    构造函数#region 构造函数

[转]c#编写网络电话_数据_05    public SoundPlayer(Control owner, WaveFormat format)

[转]c#编写网络电话_数据_05        : this(owner, null, format)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public SoundPlayer(Control owner, Device device, WaveFormat format)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        positionNotify = new BufferPositionNotify[5];

[转]c#编写网络电话_数据_05        notificationEvent = null;

[转]c#编写网络电话_数据_05        notify = null;

[转]c#编写网络电话_数据_05        notifyThread = null;

[转]c#编写网络电话_数据_05        notifySize = 0;

[转]c#编写网络电话_数据_05        m_Device = device;

[转]c#编写网络电话_数据_05        if (m_Device == null)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            m_Device = new Device();

[转]c#编写网络电话_数据_05            m_Device.SetCooperativeLevel(owner, CooperativeLevel.Normal);

[转]c#编写网络电话_数据_05            m_OwnsDevice = true;

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        // 设定通知的大小, 大小为播放一秒钟声音所需要的字节。这里为什么除以8,我不清楚

[转]c#编写网络电话_数据_05        notifySize = (1024 > (format.AverageBytesPerSecond / 8)) ? (1024) : ((format.AverageBytesPerSecond / 8));

[转]c#编写网络电话_数据_05        notifySize = (notifySize - (notifySize % format.BlockAlign));

[转]c#编写网络电话_数据_05        m_BufferBytes = (notifySize * 4); //整体缓冲区的大小

[转]c#编写网络电话_数据_05        BufferDescription desc = new BufferDescription(format);

[转]c#编写网络电话_数据_05        //缓冲区具有控制音量的能力;

[转]c#编写网络电话_数据_05        desc.ControlVolume = true;

[转]c#编写网络电话_数据_05        //缓冲区具有控制位置的能力。

[转]c#编写网络电话_数据_05        desc.ControlPositionNotify = true;

[转]c#编写网络电话_数据_05        //设置缓冲区能取到当前的播放位置

[转]c#编写网络电话_数据_05        desc.CanGetCurrentPosition = true;

[转]c#编写网络电话_数据_05        //缓冲区不具有控制3D音效的能力;

[转]c#编写网络电话_数据_05        desc.Control3D = false;

[转]c#编写网络电话_数据_05        //Specifies whether the buffer supports effects processing.

[转]c#编写网络电话_数据_05        desc.ControlEffects = false;

[转]c#编写网络电话_数据_05        //缓冲区具有控制频率的能力;

[转]c#编写网络电话_数据_05        desc.ControlFrequency = true;

[转]c#编写网络电话_数据_05        //缓冲区具有控制左右声道的能力;

[转]c#编写网络电话_数据_05        desc.ControlPan = true;

[转]c#编写网络电话_数据_05        //设置是否使用全局缓存

[转]c#编写网络电话_数据_05        desc.GlobalFocus = true;

[转]c#编写网络电话_数据_05        //设置缓冲区大小为整个缓冲区的大小

[转]c#编写网络电话_数据_05        desc.BufferBytes = m_BufferBytes;

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05        //创建辅助缓冲区

[转]c#编写网络电话_数据_05        m_Buffer = new SecondaryBuffer(desc, m_Device);

[转]c#编写网络电话_数据_05        //创建环形缓冲区

[转]c#编写网络电话_数据_05        circularBuffer = new CircularBuffer((m_BufferBytes * 10));

[转]c#编写网络电话_数据_05        InitNotifications();

[转]c#编写网络电话_数据_05        m_Buffer.Play(0, BufferPlayFlags.Looping);

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public SoundPlayer(Control owner, int sr, short bps, short ch)

[转]c#编写网络电话_数据_05        : this(owner, null, DirectSoundManager.CreateWaveFormat(sr, bps, ch))

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public SoundPlayer(Control owner, Device device, int sr, short bps, short ch)

[转]c#编写网络电话_数据_05        : this(owner, device, DirectSoundManager.CreateWaveFormat(sr, bps, ch))

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_24    } 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    公开属性#region 公开属性

[转]c#编写网络电话_数据_05    public int BitsPerSample

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        get [转]c#编写网络电话_构造函数_04{ return m_Buffer.Format.BitsPerSample; }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public int Channels

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        get [转]c#编写网络电话_构造函数_04{ return m_Buffer.Format.Channels; }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public Device Device

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        get [转]c#编写网络电话_构造函数_04{ return m_Device; }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public int SamplingRate

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        get [转]c#编写网络电话_构造函数_04{ return m_Buffer.Format.SamplesPerSecond; }

[转]c#编写网络电话_microsoft_24    } 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    IDisposable Members#region IDisposable Members

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public void Dispose()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        Stop();

[转]c#编写网络电话_数据_05        if (m_Buffer != null)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            m_Buffer.Dispose();

[转]c#编写网络电话_数据_05            m_Buffer = null;

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        if (m_OwnsDevice && (m_Device != null))

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            m_Device.Dispose();

[转]c#编写网络电话_数据_05            m_Device = null;

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        GC.SuppressFinalize(this);

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05    ~SoundPlayer()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        Dispose();

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    私有方法#region 私有方法

[转]c#编写网络电话_数据_05    private void InitNotifications()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        notifyThread = new Thread(NotifyThreadHandler);

[转]c#编写网络电话_数据_05        isRunning = true;

[转]c#编写网络电话_数据_05        notifyThread.IsBackground = true;

[转]c#编写网络电话_数据_05        notifyThread.Start();

[转]c#编写网络电话_数据_05        notificationEvent = new AutoResetEvent(false);

[转]c#编写网络电话_数据_05        notify = new Notify(m_Buffer);

[转]c#编写网络电话_数据_05        //把整个缓冲区分成4个缓冲区片段,每播放4分之一就会给写线程发送一个信号

[转]c#编写网络电话_数据_05        for (int i = 0; i < 4; i = (i + 1))

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            positionNotify[i].Offset = (((notifySize * i) + notifySize) - 1);

[转]c#编写网络电话_数据_05            positionNotify[i].EventNotifyHandle = notificationEvent.SafeWaitHandle.DangerousGetHandle();

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        notify.SetNotificationPositions(positionNotify, 4);

[转]c#编写网络电话_数据_05        nextWriteOffset = 0;

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    private void NotifyThreadHandler()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        while (isRunning)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            try

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07            [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05                notificationEvent.WaitOne(-1, true);

[转]c#编写网络电话_数据_05                Play();

[转]c#编写网络电话_microsoft_24            }

[转]c#编写网络电话_数据_05            catch (Exception)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07            [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_24            }

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    private void Play()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        try

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            try

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07            [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05                int currentPlayPosition;

[转]c#编写网络电话_数据_05                int currentWritePosition;

[转]c#编写网络电话_数据_05                m_Buffer.GetCurrentPosition(out currentPlayPosition, out currentWritePosition);

[转]c#编写网络电话_数据_05                //得到刚刚播放完的缓冲区片段,这个片段需要用新的数据去填充

[转]c#编写网络电话_数据_05                int lockSize = (currentWritePosition - nextWriteOffset);

[转]c#编写网络电话_数据_05                //todo:这里不知道什么时候会发生

[转]c#编写网络电话_数据_05                if (lockSize < 0)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07                [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05                    lockSize = (lockSize + m_BufferBytes);

[转]c#编写网络电话_microsoft_24                }

[转]c#编写网络电话_数据_05                //对齐需要填充的缓冲区片段

[转]c#编写网络电话_数据_05                lockSize = (lockSize - (lockSize % notifySize));

[转]c#编写网络电话_数据_05                if (0 != lockSize)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07                [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05                    if (lockSize == m_BufferBytes)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07                    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_24                    }

[转]c#编写网络电话_数据_05                    byte[] data = new byte[lockSize];

[转]c#编写网络电话_数据_05                    if (circularBuffer.Read(data) > 0)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07                    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05                        m_Buffer.Write(nextWriteOffset, data, LockFlag.None);

[转]c#编写网络电话_数据_05                        nextWriteOffset = (nextWriteOffset + lockSize);

[转]c#编写网络电话_数据_05                        //如果完整写完一次缓冲区,那么把写数据指针放到缓冲区的最开始,

[转]c#编写网络电话_数据_05                        //因为前面设置了m_Buffer.Play(0, BufferPlayFlags.Looping);

[转]c#编写网络电话_数据_05                        //所以系统在播放缓冲区后会自动重新开始播放缓冲区起始处的声音数据

[转]c#编写网络电话_数据_05                        nextWriteOffset = (nextWriteOffset % m_BufferBytes);

[转]c#编写网络电话_microsoft_24                    }

[转]c#编写网络电话_microsoft_24                }

[转]c#编写网络电话_microsoft_24            }

[转]c#编写网络电话_数据_05            catch (Exception)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07            [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_24            }

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        finally

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    } 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    公开方法#region 公开方法

[转]c#编写网络电话_数据_05    public void Stop()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        isRunning = false;

[转]c#编写网络电话_数据_05        if (m_Buffer != null)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            m_Buffer.Stop();

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public void Write(byte[] data)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        try

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            Console.WriteLine("播放声音:{0}", data.Length);

[转]c#编写网络电话_数据_05            circularBuffer.Write(data);

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        catch (Exception)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    } 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_microsoft_89}


 

用户录制声音

 


[转]c#编写网络电话_数据public class CaptureSound

[转]c#编写网络电话_microsoft_02[转]c#编写网络电话_数据_03[转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    私有成员#region 私有成员

[转]c#编写网络电话_数据_05    private const int NumberRecordNotifications = 4;

[转]c#编写网络电话_数据_05    private readonly BufferPositionNotify[] positionNotify;

[转]c#编写网络电话_数据_05    private Capture selectedDevice;

[转]c#编写网络电话_数据_05    private CaptureBuffer buffer;

[转]c#编写网络电话_数据_05    private int captureBufferSize;

[转]c#编写网络电话_数据_05    private string fileName;

[转]c#编写网络电话_数据_05    private bool isRecording;

[转]c#编写网络电话_数据_05    private int nextCaptureOffset;

[转]c#编写网络电话_数据_05    private AutoResetEvent notificationEvent;

[转]c#编写网络电话_数据_05    private Notify notify;

[转]c#编写网络电话_数据_05    private int notifySize;

[转]c#编写网络电话_数据_05    private Thread notifyThread;

[转]c#编写网络电话_数据_05    private long sampleCount;

[转]c#编写网络电话_数据_05    private WaveFormat selectedFormat;

[转]c#编写网络电话_数据_05    private FileStream waveFile;

[转]c#编写网络电话_数据_05    private BinaryWriter writer; 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    构造函数#region 构造函数

[转]c#编写网络电话_数据_05    public CaptureSound()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        isRecording = false;

[转]c#编写网络电话_数据_05        positionNotify = new BufferPositionNotify[5];

[转]c#编写网络电话_数据_05        notificationEvent = null;

[转]c#编写网络电话_数据_05        buffer = null;

[转]c#编写网络电话_数据_05        fileName = string.Empty;

[转]c#编写网络电话_数据_05        notify = null;

[转]c#编写网络电话_数据_05        notifyThread = null;

[转]c#编写网络电话_数据_05        waveFile = null;

[转]c#编写网络电话_数据_05        writer = null;

[转]c#编写网络电话_数据_05        captureBufferSize = 0;

[转]c#编写网络电话_数据_05        nextCaptureOffset = 0;

[转]c#编写网络电话_数据_05        sampleCount = 0L;

[转]c#编写网络电话_数据_05        notifySize = 0;

[转]c#编写网络电话_数据_05        InitializeDeviceSelector();

[转]c#编写网络电话_数据_05        InitializeWaveFormatSelector();

[转]c#编写网络电话_数据_05        Initialize();

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public CaptureSound(Capture device)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        isRecording = false;

[转]c#编写网络电话_数据_05        positionNotify = new BufferPositionNotify[5];

[转]c#编写网络电话_数据_05        notificationEvent = null;

[转]c#编写网络电话_数据_05        buffer = null;

[转]c#编写网络电话_数据_05        fileName = string.Empty;

[转]c#编写网络电话_数据_05        notify = null;

[转]c#编写网络电话_数据_05        notifyThread = null;

[转]c#编写网络电话_数据_05        waveFile = null;

[转]c#编写网络电话_数据_05        writer = null;

[转]c#编写网络电话_数据_05        captureBufferSize = 0;

[转]c#编写网络电话_数据_05        nextCaptureOffset = 0;

[转]c#编写网络电话_数据_05        sampleCount = 0L;

[转]c#编写网络电话_数据_05        notifySize = 0;

[转]c#编写网络电话_数据_05        selectedDevice = device;

[转]c#编写网络电话_数据_05        InitializeWaveFormatSelector();

[转]c#编写网络电话_数据_05        Initialize();

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public CaptureSound(WaveFormat waveFormat)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        isRecording = false;

[转]c#编写网络电话_数据_05        positionNotify = new BufferPositionNotify[5];

[转]c#编写网络电话_数据_05        notificationEvent = null;

[转]c#编写网络电话_数据_05        buffer = null;

[转]c#编写网络电话_数据_05        fileName = string.Empty;

[转]c#编写网络电话_数据_05        notify = null;

[转]c#编写网络电话_数据_05        notifyThread = null;

[转]c#编写网络电话_数据_05        waveFile = null;

[转]c#编写网络电话_数据_05        writer = null;

[转]c#编写网络电话_数据_05        captureBufferSize = 0;

[转]c#编写网络电话_数据_05        nextCaptureOffset = 0;

[转]c#编写网络电话_数据_05        sampleCount = 0L;

[转]c#编写网络电话_数据_05        notifySize = 0;

[转]c#编写网络电话_数据_05        selectedFormat = waveFormat;

[转]c#编写网络电话_数据_05        InitializeDeviceSelector();

[转]c#编写网络电话_数据_05        Initialize();

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public CaptureSound(Capture device, WaveFormat waveFormat)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        isRecording = false;

[转]c#编写网络电话_数据_05        positionNotify = new BufferPositionNotify[5];

[转]c#编写网络电话_数据_05        notificationEvent = null;

[转]c#编写网络电话_数据_05        buffer = null;

[转]c#编写网络电话_数据_05        fileName = string.Empty;

[转]c#编写网络电话_数据_05        notify = null;

[转]c#编写网络电话_数据_05        notifyThread = null;

[转]c#编写网络电话_数据_05        waveFile = null;

[转]c#编写网络电话_数据_05        writer = null;

[转]c#编写网络电话_数据_05        captureBufferSize = 0;

[转]c#编写网络电话_数据_05        nextCaptureOffset = 0;

[转]c#编写网络电话_数据_05        sampleCount = 0L;

[转]c#编写网络电话_数据_05        notifySize = 0;

[转]c#编写网络电话_数据_05        selectedDevice = device;

[转]c#编写网络电话_数据_05        selectedFormat = waveFormat;

[转]c#编写网络电话_数据_05        Initialize();

[转]c#编写网络电话_microsoft_24    } 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    公开属性#region 公开属性

[转]c#编写网络电话_数据_05    public int BufferBytes

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        get [转]c#编写网络电话_构造函数_04{ return captureBufferSize; }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public string FileName

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        get [转]c#编写网络电话_构造函数_04{ return fileName; }

[转]c#编写网络电话_数据_05        set

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            fileName = value;

[转]c#编写网络电话_数据_05            CreateRIFF();

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public long SampleCount

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        get [转]c#编写网络电话_构造函数_04{ return sampleCount; }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public WaveFormat SelectedFormat

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        get [转]c#编写网络电话_构造函数_04{ return selectedFormat; }

[转]c#编写网络电话_microsoft_24    } 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    公开事件#region 公开事件

[转]c#编写网络电话_数据_05    public event DirectSoundBufferDataEventHandler BufferData; 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    私有方法#region 私有方法

[转]c#编写网络电话_数据_05    private void CreateCaptureBuffer()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        CaptureBufferDescription desc = new CaptureBufferDescription();

[转]c#编写网络电话_数据_05        if (null != notify)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            notify.Dispose();

[转]c#编写网络电话_数据_05            notify = null;

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        if (null != buffer)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            buffer.Dispose();

[转]c#编写网络电话_数据_05            buffer = null;

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        if (0 != selectedFormat.Channels)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            notifySize = (1024 > (selectedFormat.AverageBytesPerSecond / 8))

[转]c#编写网络电话_数据_05                             ? (1024)

[转]c#编写网络电话_数据_05                             :

[转]c#编写网络电话_数据_05                                 ((selectedFormat.AverageBytesPerSecond / 8));

[转]c#编写网络电话_数据_05            notifySize = (notifySize - (notifySize % selectedFormat.BlockAlign));

[转]c#编写网络电话_数据_05            captureBufferSize = (notifySize * 4);

[转]c#编写网络电话_数据_05            desc.BufferBytes = captureBufferSize;

[转]c#编写网络电话_数据_05            selectedFormat.FormatTag = WaveFormatTag.Pcm;

[转]c#编写网络电话_数据_05            desc.Format = selectedFormat;

[转]c#编写网络电话_数据_05            buffer = new CaptureBuffer(desc, selectedDevice);

[转]c#编写网络电话_数据_05            nextCaptureOffset = 0;

[转]c#编写网络电话_数据_05            InitNotifications();

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    private void CreateRIFF()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        waveFile = new FileStream(FileName, FileMode.Create);

[转]c#编写网络电话_数据_05        writer = new BinaryWriter(waveFile);

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        char[] chArray = new char[] [转]c#编写网络电话_构造函数_04{ 'R', 'I', 'F', 'F' };

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        char[] chArray2 = new char[] [转]c#编写网络电话_构造函数_04{ 'W', 'A', 'V', 'E' };

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        char[] chArray3 = new char[] [转]c#编写网络电话_构造函数_04{ 'f', 'm', 't', ' ' };

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        char[] chArray4 = new char[] [转]c#编写网络电话_构造函数_04{ 'd', 'a', 't', 'a' };

[转]c#编写网络电话_数据_05        short num = 1;

[转]c#编写网络电话_数据_05        int num2 = 0x10;

[转]c#编写网络电话_数据_05        int num3 = 0;

[转]c#编写网络电话_数据_05        short num4 = 0;

[转]c#编写网络电话_数据_05        if ((8 == selectedFormat.BitsPerSample) && (1 == selectedFormat.Channels))

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            num4 = 1;

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        else if (((8 == selectedFormat.BitsPerSample) && (2 == selectedFormat.Channels)) ||

[转]c#编写网络电话_数据_05                 ((0x10 == selectedFormat.BitsPerSample) && (1 == selectedFormat.Channels)))

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            num4 = 2;

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        else if ((0x10 == selectedFormat.BitsPerSample) && (2 == selectedFormat.Channels))

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            num4 = 4;

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        writer.Write(chArray);

[转]c#编写网络电话_数据_05        writer.Write(num3);

[转]c#编写网络电话_数据_05        writer.Write(chArray2);

[转]c#编写网络电话_数据_05        writer.Write(chArray3);

[转]c#编写网络电话_数据_05        writer.Write(num2);

[转]c#编写网络电话_数据_05        writer.Write(num);

[转]c#编写网络电话_数据_05        writer.Write(selectedFormat.Channels);

[转]c#编写网络电话_数据_05        writer.Write(selectedFormat.SamplesPerSecond);

[转]c#编写网络电话_数据_05        writer.Write(selectedFormat.AverageBytesPerSecond);

[转]c#编写网络电话_数据_05        writer.Write(num4);

[转]c#编写网络电话_数据_05        writer.Write(selectedFormat.BitsPerSample);

[转]c#编写网络电话_数据_05        writer.Write(chArray4);

[转]c#编写网络电话_数据_05        writer.Write(0);

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    private void Initialize()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        CreateCaptureBuffer();

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    private void InitializeDeviceSelector()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05        CaptureDevicesCollection devices = new CaptureDevicesCollection();  // 枚举音频捕捉设备 

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05        if (devices.Count > 0)

[转]c#编写网络电话_数据_05            selectedDevice = new Capture(devices[0].DriverGuid);

[转]c#编写网络电话_数据_05        else

[转]c#编写网络电话_数据_05            throw new ArgumentException("无法初始化声音设备");

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    private void InitializeWaveFormatSelector()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        if (selectedDevice == null)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            throw new ArgumentException("尚未設定音訊裝置,無法選擇輸出格式。");

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        selectedFormat = DirectSoundManager.DefaultFormat;

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    private void InitNotifications()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        if (null == buffer)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            throw new NullReferenceException();

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        if (null == notifyThread)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            isRecording = true;

[转]c#编写网络电话_数据_05            notifyThread = new Thread(WaitThread);

[转]c#编写网络电话_数据_05            notifyThread.IsBackground = true;

[转]c#编写网络电话_数据_05            notifyThread.Start();

[转]c#编写网络电话_数据_05            notificationEvent = new AutoResetEvent(false);

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        for (int i = 0; i < 4; i++)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            positionNotify[i].Offset = (((notifySize * i) + notifySize) - 1);

[转]c#编写网络电话_数据_05            positionNotify[i].EventNotifyHandle = notificationEvent.SafeWaitHandle.DangerousGetHandle();

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        notify = new Notify(buffer);

[转]c#编写网络电话_数据_05        notify.SetNotificationPositions(positionNotify, 4);

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    private void OnBufferData(object sender, DirectSoundBufferDataEventArgs e)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        if (BufferData != null)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            BufferData(sender, e);

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05    private void RecordCapturedData()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        byte[] data = null;

[转]c#编写网络电话_数据_05        try

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            try

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07            [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05                int currentPlayPosition;

[转]c#编写网络电话_数据_05                int currentWritePosition;

[转]c#编写网络电话_数据_05                buffer.GetCurrentPosition(out currentWritePosition, out currentPlayPosition);

[转]c#编写网络电话_数据_05                int lockSize = (currentPlayPosition - nextCaptureOffset);

[转]c#编写网络电话_数据_05                if (lockSize < 0)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07                [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05                    lockSize = (lockSize + captureBufferSize);

[转]c#编写网络电话_microsoft_24                }

[转]c#编写网络电话_数据_05                lockSize = (lockSize - (lockSize % notifySize));

[转]c#编写网络电话_数据_05                if (0 != lockSize)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07                [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07                    data = (byte[])buffer.Read(nextCaptureOffset, typeof(byte), LockFlag.None, new int[] [转]c#编写网络电话_构造函数_04{ lockSize });

[转]c#编写网络电话_数据_05                    OnBufferData(this, new DirectSoundBufferDataEventArgs(data));

[转]c#编写网络电话_数据_05                    if (writer != null)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07                    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05                        writer.Write(data, 0, data.Length);

[转]c#编写网络电话_microsoft_24                    }

[转]c#编写网络电话_数据_05                    sampleCount = (sampleCount + data.Length);

[转]c#编写网络电话_数据_05                    nextCaptureOffset = (nextCaptureOffset + data.Length);

[转]c#编写网络电话_数据_05                    nextCaptureOffset = (nextCaptureOffset % captureBufferSize);

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_microsoft_24                }

[转]c#编写网络电话_microsoft_24            }

[转]c#编写网络电话_数据_05            catch (Exception)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07            [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_24            }

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        finally

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            data = null;

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    private void WaitThread()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        while (isRecording)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            try

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07            [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05                notificationEvent.WaitOne(-1, true);

[转]c#编写网络电话_数据_05                RecordCapturedData();

[转]c#编写网络电话_microsoft_24            }

[转]c#编写网络电话_数据_05            catch (Exception)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07            [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_microsoft_24            }

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05    private void StartOrStopRecord(bool StartRecording)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        if (StartRecording)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            isRecording = true;

[转]c#编写网络电话_数据_05            CreateCaptureBuffer();

[转]c#编写网络电话_数据_05            buffer.Start(true);

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_数据_05        else

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07        [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05            isRecording = false;

[转]c#编写网络电话_数据_05            buffer.Stop();

[转]c#编写网络电话_数据_05            RecordCapturedData();

[转]c#编写网络电话_数据_05            if (writer != null)

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07            [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05                writer.Seek(4, SeekOrigin.Begin);

[转]c#编写网络电话_数据_05                writer.Write(((int)(sampleCount + 0x24L)));

[转]c#编写网络电话_数据_05                writer.Seek(40, SeekOrigin.Begin);

[转]c#编写网络电话_数据_05                writer.Write(sampleCount);

[转]c#编写网络电话_数据_05                writer.Close();

[转]c#编写网络电话_数据_05                writer = null;

[转]c#编写网络电话_数据_05                waveFile = null;

[转]c#编写网络电话_microsoft_24            }

[转]c#编写网络电话_microsoft_24        }

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_压缩算法_07[转]c#编写网络电话_microsoft_06    公开方法#region 公开方法

[转]c#编写网络电话_数据_05    public void Pause()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        buffer.Stop();

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public void Resume()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        buffer.Start(true);

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public void Start()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        StartOrStopRecord(true);

[转]c#编写网络电话_microsoft_24    }

[转]c#编写网络电话_数据_05

[转]c#编写网络电话_数据_05    public void Stop()

[转]c#编写网络电话_microsoft_06[转]c#编写网络电话_压缩算法_07    [转]c#编写网络电话_构造函数_04{

[转]c#编写网络电话_数据_05        StartOrStopRecord(false);

[转]c#编写网络电话_数据_05        notifyThread = null;

[转]c#编写网络电话_数据_05        nextCaptureOffset = 0;

[转]c#编写网络电话_数据_05        sampleCount = 0L;

[转]c#编写网络电话_microsoft_24    } 

[转]c#编写网络电话_microsoft_24    #endregion

[转]c#编写网络电话_microsoft_89}


 

程序下载地址如下(自己反射看源码,因为程序只是用于演示,所以考虑很不周全,不足以效仿)

​javascript:void(0)
​PPT下载地址如下

​http://files.cnblogs.com/onlytiancai/p2p语音.zip​

参考链接如下:

ch11-DxSound&Input2.ppt:建立DirectSound 声音的播放与控制 使用3D音效

SIP之 穿越NAT.ppt

DirectX技术实现视频会议中的音频通信

http://www.ctiforum.com/forum/2008/03/forum08_0357.htm

C#中使用DirectSound录音

http:///uplook/archive/2005/12/14/657145.aspx

在C#下利用DirectSound实现声音播放


隨意桌面,數位溝通

http:///2007/05/blog-post_9694.html

用DirectX Audio和DirectShow播放声音和音乐

http://www.cppblog.com/lovedday/archive/2007/09/24/32815.html