naudio WaveOut未播放iSampleProvider提供的所有数据
本文关键字:数据 WaveOut 播放 iSampleProvider naudio | 更新日期: 2023-09-27 18:22:05
我正在使用nAudio开发一个点击生成器。作为测试,我创建了一个ISampleProvideror类来读取/播放音频文件。iSampleProvider读取PCM(32位ieee)wav文件,然后使用WaveOut播放器播放。WaveOut只播放通过IsampleProvideror Read()方法传递的音频的大约1/4。这会导致播放不稳定。ISampleProvider read()方法在正确的时间间隔请求正确的数据量,但WaveOut只播放提供给接口的前25%的样本。知道如何解决这个问题吗?或者我是否使用了错误的类来构建点击轨迹(BufferedWaveProvider也可能工作,但它只缓冲5秒的音频)?
public void TestSampleProvider()
{
ISampleProvider mySamples = new MySamples();
var _waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()) {DeviceNumber = 0};
_waveOut.Init(mySamples);
_waveOut.Play();
Console.ReadLine();
}
public class MySamples : ISampleProvider
{
private float[] samplesFloats;
private int position;
private WaveFileReader clicksound;
public int Read(float[] buffer, int offset, int count)
{
var copyCount = count;
if (position + copyCount > samplesFloats.Count())
{
copyCount = samplesFloats.Count() - position;
}
Console.WriteLine("samplesFloats {0} position {1} copyCount {2} offset {3} time {4}", samplesFloats.Count(), position, copyCount, offset, DateTime.Now.Millisecond);
Buffer.BlockCopy(samplesFloats, position, buffer, offset, copyCount);
position += copyCount;
return copyCount;
}
public MySamples()
{
clicksound = new WaveFileReader(@"C:'temp'sample.wav");
WaveFormat = clicksound.WaveFormat;
samplesFloats = new float[clicksound.SampleCount];
for (int i = 0; i < clicksound.SampleCount; i++)
{
samplesFloats[i] = clicksound.ReadNextSampleFrame()[0];//it;s a mono file
}
}
public WaveFormat WaveFormat { get; private set; }
}
我认为使用ISampleProvider的WaveOut可能有问题,所以我使用IWaveProvider接口来做同样的事情。事实上,这里有一个用于向waveout发送无尾点击的基本类。如果你让它运行很长时间,这可能会遇到内存问题,但对于流行歌曲来说,这应该没问题。同样,这只适用于32位文件(注意字节缓冲区上的*4)
public class MyClick : IWaveProvider
{
private int position;
private WaveFileReader clicksound;
private byte[] samplebuff;
MemoryStream _byteStream = new System.IO.MemoryStream();
public MyClick(float bpm=120)
{
clicksound = new WaveFileReader(@"click_sample.wav");
var bpmsampleslen = (60 / bpm) * clicksound.WaveFormat.SampleRate;
samplebuff = new byte[(int) bpmsampleslen*4];
clicksound.Read(samplebuff, 0,(int) clicksound.Length);
_byteStream.Write(samplebuff, 0, samplebuff.Length);
_byteStream.Position = 0;
WaveFormat = clicksound.WaveFormat;
}
public int Read(byte[] buffer, int offset, int count)
{
//we reached the end of the stream add another one to the end and keep playing
if (count + _byteStream.Position > _byteStream.Length)
{
var holdpos = _byteStream.Position;
_byteStream.Write(samplebuff, 0, samplebuff.Length);
_byteStream.Position = holdpos;
}
return _byteStream.Read(buffer, offset, count);
}
public WaveFormat WaveFormat { get; private set; }
}