我正在尝试播放从ohlibspotify c#library传递的原始PCM数据(https://github.com/openhome/ohlibspotify)。
我在以下回调中获取数据:
public void MusicDeliveryCallback(SpotifySession session, AudioFormat format, IntPtr frames, int num_frames)
{
//EXAMPLE DATA
//format.channels = 2, format.samplerate = 44100, format.sample_type = Int16NativeEndian
//frames = ?
//num_frames = 2048
}
现在,我想直接使用Naudio(http://naudio.codeplex.com/)播放收到的数据。使用以下代码段,我可以从磁盘播放MP3文件。是否可以将收到的数据从Spotify直接传递给Naudio并实时播放?
using (var ms = File.OpenRead("test.pcm"))
using (var rdr = new Mp3FileReader(ms))
using (var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr))
using (var baStream = new BlockAlignReductionStream(wavStream))
using (var waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
{
waveOut.Init(baStream);
waveOut.Play();
while (waveOut.PlaybackState == PlaybackState.Playing)
{
Thread.Sleep(100);
}
}
编辑:我更新了代码。该程序不会丢掉任何错误,但我也听不到音乐。我的代码有什么错吗?
这是音乐交付回调:
public void MusicDeliveryCallback(SpotifySession session, AudioFormat format, IntPtr frames, int num_frames)
{
//format.channels = 2, format.samplerate = 44100, format.sample_type = Int16NativeEndian
//frames = ?
//num_frames = 2048
byte[] frames_copy = new byte[num_frames];
Marshal.Copy(frames, frames_copy, 0, num_frames);
bufferedWaveProvider = new BufferedWaveProvider(new WaveFormat(format.sample_rate, format.channels));
bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(40);
bufferedWaveProvider.AddSamples(frames_copy, 0, num_frames);
bufferedWaveProvider.Read(frames_copy, 0, num_frames);
if (_waveOutDeviceInitialized == false)
{
IWavePlayer waveOutDevice = new WaveOut();
waveOutDevice.Init(bufferedWaveProvider);
waveOutDevice.Play();
_waveOutDeviceInitialized = true;
}
}
这些是SessionListener中的覆盖回调:
public override int MusicDelivery(SpotifySession session, AudioFormat format, IntPtr frames, int num_frames)
{
_sessionManager.MusicDeliveryCallback(session, format, frames, num_frames);
return base.MusicDelivery(session, format, frames, num_frames);
}
public override void GetAudioBufferStats(SpotifySession session, out AudioBufferStats stats)
{
stats.samples = 2048 / 2; //???
stats.stutter = 0; //???
}
我认为您可以这样做:
- 创建一个BufferedWaveProvider。
- 将此传递给waveout.init。
- 在您的MusicDeliveryCallback中,使用Marshal.copy从本机缓冲区复制到托管字节阵列中。
- 将此托管字节阵列传递给您的BufferedWaveProvider上的addsamples。
- 在您的getaudiobufferstats回调中,使用bufferedwaveprovider.bufferedbytes/2用于"样本",然后将" stusters"作为0。
i Think Think 将起作用。它涉及一些不必要的复制,并且不能准确跟踪斯托特,但这是一个很好的起点。我认为实施iWaveProvider并自己管理缓冲可能是更好的(更高效,更可靠的)解决方案。
我写了《 ohlibspotify包装纸》,但我不再为同一家公司工作了,所以我不再参与其开发。您也许可以从这个论坛上的某人那里获得更多帮助:http://forum.openhome.org/forumdisplay.php?fid=6就音乐传递而言,OhlibSpotify的目标是使开销尽可能少。它根本不复制音乐数据,它只是通过提供的LibSpotify库本身的本机指针,因此您可以自己复制到最终目的地,并避免使用不必要的层复制。不过,它确实使简单用法有点笨拙。
祝你好运!
首先,上面显示的代码片段比需要的要复杂。您只需要五个,而不是两个using
统计。Mp3FileReader
为您解码为PCM。其次,优先使用 WaveOutEvent
,而不是 WaveOut
带有函数回调。它更可靠。
using (var rdr = new Mp3FileReader("test.pcm"))
using (var waveOut = new WaveOutEvent())
{
//...
}
要回答您的实际问题,您需要使用BufferedWaveProvider
。您可以创建其中之一,并将其传递给INIT方法中的输出设备。现在,当您收到音频时,将其解压缩到PCM(如果被压缩)并将其放入BufferedWaveProvider
中。Naudiodemo应用程序包括有关如何执行此操作的示例,因此请查看Naudio源代码以查看其完成方式。