我正在使用NAudio来满足我的音频需求,但我遇到了一个棘手的问题。我有一个可以接收RTP音频的远程设备。我想将音频文件流式传输到该设备(在u-law或类似的编码+ RTP包装之后)。但是,似乎没有一种机制来维护RTP数据包的传出时序。
例如,WaveOut播放器"管理"通过简单地响应来自底层声音/ directx层的请求来进行定时。通过这种方式,时间实际上由声音驱动程序使用" pull"方法
我正在寻找的是一个可以提供正确"拉动"在(例如)IWaveProvider
(或类似)上计时,以便我可以接收每个数据包,RTP-ify,然后通过网络发送。
所以,这是核心代码:
IPEndPoint target = new IPEndPoint(addr, port);
Socket sender = new Socket( AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp );
IWaveProvider provider = new AudioFileReader(filename);
MuLawChatCodec codec = new MuLawChatCodec(); // <-- from chat example
int alignment = provider.BlockAlign * 32; // <-- arbitrary
byte [] buffer = new byte [alignment];
try
{
int numbytes;
while( (numbytes = provider.Read(buffer, 0, alignment)) != 0 )
{
byte [] encoded = m_Codec.Encode(buffer, 0, numbytes);
m_Sender.SendTo(buffer, numbytes, SocketFlags.None, target);
}
}
catch( Exception )
{
// We just assume that any exception is an exit signal.
}
发生的事情是while
循环只是抓住&#34;音频&#34;尽可能快地将其吹出UDP端口。这不适用于RTP,因为我们需要保持适当的输出时序。
作为测试,我尝试使用NotifyingSampleProvider
的WaveOut,将每个L / R对馈送到编码器/ RTP-ifier /发送器,它似乎工作正常。然而,音频播放本地扬声器的副作用(通过WaveOut)对于我正在处理的应用来说是不可接受的(例如,我们可能希望同时将多个不同的文件流式传输到不同的设备)。我们也可能正在使用音频硬件(例如)同时进行软电话转换。基本上,我们并不想在此实现中实际使用本地音频硬件。
那么,是否有人知道(或编写)可以为发送方提供适当时机的组件?能够以适当的速率获取音频的东西,以便我可以提供编码器/发送器链吗?
答案 0 :(得分:1)
如果有人有兴趣,我就让它上班了。我不得不添加一些组件,并将时间缩短到非常精细的水平。
添加了:
m2 <- cbind(which(m1!=0, arr.ind=TRUE), value= m1[m1!=0])
m2[order(m2[,'value']),]
。我使用它是因为它为您阅读的每个帧提供时序信息。NAudio.Wave.Mp3FileReader
和System.Diagnostics.Stopwatch
这是代码的精简(单线程)版本,没有尝试/捕获等。实际的东西使用了一个播放器线程和一些其他同步机制,让你通过杀死套接字“取消”播放。
Socket.Poll
答案 1 :(得分:0)
基本上,您需要生成一个时钟来驱动样品交付。 AudioFileReader继承自WaveStream,它通过CurrentTime(通过WaveFormat.AverageBytesPerSecond计算)提供样本的当前时间。您应该可以使用它来为音频数据包加时间戳。
此外,根据您的项目需求,您可能需要查看StreamCoder的MediaSuite.NET产品。我过去曾用它来做类似的事情,它为这类事情抽象了大部分传输层复杂性。