private
void
RecordCapturedData(Socket Client,EndPoint epServer )
{
byte
[] capturedata =
null
;
int
readpos = 0, capturepos = 0, locksize = 0;
capturebuffer.GetCurrentPosition(
out
capturepos,
out
readpos);
locksize = readpos - iBufferOffset;
//这个大小就是我们可以安全读取的大小
if
(locksize == 0)
{
return
;
}
if
(locksize < 0)
{
//因为我们是循环的使用缓冲区,所以有一种情况下为负:当文以载读指针回到第一个通知点,而Ibuffeoffset还在最后一个通知处
locksize += iBufferSize;
}
capturedata = (
byte
[])capturebuffer.Read(iBufferOffset,
typeof
(
byte
), LockFlag.FromWriteCursor, locksize);
//capturedata = g729.Encode(capturedata);//语音编码
try
{
int
intSet = capturedata.Length;
//播放
GetVoiceData(intSet,capturedata);
if
(IsRecord)
{
// 写入Wav文件
mWriter.Write(capturedata, 0, capturedata.Length);
// 更新已经录制的数据长度.
mSampleCount += capturedata.Length;
}
//Client.SendTo(capturedata, epServer);//传送语音
}
catch
{
// throw new Exception();
}
iBufferOffset += capturedata.Length;
iBufferOffset %= iBufferSize;
//取模是因为缓冲区是循环的。
}
/// <summary>
/// 从字节数组中获取音频数据,并进行播放
/// </summary>
/// <param name="intRecv">字节数组长度</param>
/// <param name="bytRecv">包含音频数据的字节数组</param>
public
void
GetVoiceData(
int
intRecv,
byte
[] bytRecv)
{
//intPosWrite指示最新的数据写好后的末尾。intPosPlay指示本次播放开始的位置。
if
(intPosWrite + intRecv <= memstream.Capacity)
{
//如果当前写指针所在的位移+将要写入到缓冲区的长度小于缓冲区总大小
if
((intPosWrite - intPosPlay >= 0 && intPosWrite - intPosPlay < intNotifySize) || (intPosWrite - intPosPlay < 0 && intPosWrite - intPosPlay + memstream.Capacity < intNotifySize))
{
memstream.Write(bytRecv, 0, intRecv);
intPosWrite += intRecv;
}
else
if
(intPosWrite - intPosPlay >= 0)
{
//先存储一定量的数据,当达到一定数据量时就播放声音。
buffDiscript.BufferBytes = intPosWrite - intPosPlay;
//缓冲区大小为播放指针到写指针之间的距离。
SecondaryBuffer sec =
new
SecondaryBuffer(buffDiscript, PlayDev);
//建立一个合适的缓冲区用于播放这段数据。
memstream.Position = intPosPlay;
//先将memstream的指针定位到这一次播放开始的位置
sec.Write(0, memstream, intPosWrite - intPosPlay, LockFlag.FromWriteCursor);
sec.Play(0, BufferPlayFlags.Default);
memstream.Position = intPosWrite;
//写完后重新将memstream的指针定位到将要写下去的位置。
intPosPlay = intPosWrite;
}
else
if
(intPosWrite - intPosPlay < 0)
{
buffDiscript.BufferBytes = intPosWrite - intPosPlay + memstream.Capacity;
//缓冲区大小为播放指针到写指针之间的距离。
SecondaryBuffer sec =
new
SecondaryBuffer(buffDiscript, PlayDev);
//建立一个合适的缓冲区用于播放这段数据。
memstream.Position = intPosPlay;
sec.Write(0, memstream, memstream.Capacity - intPosPlay, LockFlag.FromWriteCursor);
memstream.Position = 0;
sec.Write(memstream.Capacity - intPosPlay, memstream, intPosWrite, LockFlag.FromWriteCursor);
sec.Play(0, BufferPlayFlags.Default);
memstream.Position = intPosWrite;
intPosPlay = intPosWrite;
}
}
else
{
//当数据将要大于memstream可容纳的大小时
int
irest = memstream.Capacity - intPosWrite;
//memstream中剩下的可容纳的字节数。
memstream.Write(bytRecv, 0, irest);
//先写完这个内存流。
memstream.Position = 0;
//然后让新的数据从memstream的0位置开始记录
memstream.Write(bytRecv, irest, intRecv - irest);
//覆盖旧的数据
intPosWrite = intRecv - irest;
//更新写指针位置。写指针指示下一个开始写入的位置而不是上一次结束的位置,因此不用减一
}
}