Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用NAudio在C#中播放ohLibSpotify pcm数据流_C#_.net 4.0_Naudio_Libspotify - Fatal编程技术网

用NAudio在C#中播放ohLibSpotify pcm数据流

用NAudio在C#中播放ohLibSpotify pcm数据流,c#,.net-4.0,naudio,libspotify,C#,.net 4.0,Naudio,Libspotify,我正在尝试播放ohLibSpotify c#library()提供的原始pcm数据 我在以下回调中获取数据: public void MusicDeliveryCallback(SpotifySession session, AudioFormat format, IntPtr frames, int num_frames) { //EXAMPLE DATA //format.channels = 2, format.samplerate = 44100, format.samp

我正在尝试播放ohLibSpotify c#library()提供的原始pcm数据

我在以下回调中获取数据:

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
}
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;
    }
}
现在我想用NAudio()直接播放接收到的数据。通过下面的代码片段,我可以从磁盘上播放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)
{
    //EXAMPLE DATA
    //format.channels = 2, format.samplerate = 44100, format.sample_type = Int16NativeEndian
    //frames = ?
    //num_frames = 2048
}
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;          //???
}

首先,上面显示的代码片段比需要的复杂得多。使用stations,您只需要五个,而不是两个<代码>Mp3FileReader为您解码到PCM。第二,在函数回调中使用
WaveOutEvent
优先于
WaveOut
。它更可靠

using (var rdr = new Mp3FileReader("test.pcm"))
using (var waveOut = new WaveOutEvent())
{
   //...
}

要回答实际问题,您需要使用
BufferedWaveProvider
。您可以创建其中一个并在Init方法中将其传递给输出设备。现在,当您接收音频时,将其解压缩到PCM(如果已压缩),并将其放入
BufferedWaveProvider
。NAudioDemo应用程序包含了如何执行此操作的示例,因此请查看NAudio源代码以了解如何执行此操作。

我认为您可以执行以下操作:

  • 创建一个BufferedWaveProvider
  • 将此消息传递给waveOut.Init
  • 在MusicDeliveryCallback中,使用Marshal.Copy从本机缓冲区复制到托管字节数组中
  • 将此托管字节数组传递给BufferedWaveProvider上的AddSamples
  • 在GetAudioBufferStats回调中,将bufferedWaveProvider.BufferedBytes/2用于“samples”,并将“stutters”保留为0
  • 我想那会管用的。它涉及一些不必要的复制,不能准确地跟踪口吃,但这是一个很好的起点。我认为实现IWaveProvider并自己管理缓冲可能是一个更好(更高效、更可靠)的解决方案

    我编写了ohLibSpotify包装库,但我不再为同一家公司工作,因此我不再参与它的开发。在这个论坛上,你可能会从某人那里得到更多的帮助:就音乐交付而言,ohLibSpotify的目标是尽可能减少开销。它根本不复制音乐数据,它只是传递libspotify库本身提供的同一个本机指针,以便您可以自己将其复制到最终目的地,避免不必要的复制层。不过,对于简单的使用来说,它确实有点笨重


    祝你好运

    谢谢你的回答。但我并没有真正理解第五步。我应该将这些值设置为“样本”和“口吃”吗
    public override void GetAudioBufferStats(SpotifySession,out AudioBufferStats){stats.samples=2048/4;//?stats.stutter=0;//?base.GetAudioBufferStats(session,out stats)}
    Yes,这是正确的,除了不应该调用基类实现,因为它只会覆盖您刚才设置的值。我需要检查libspotify文档,但这里的想法是您告诉Spotify它需要多快的速度向您发送音频,以便它可以调整其流媒体速率以匹配。示例是重要的一个,如果我没记错的话,它会告诉libspotify缓冲区有多满。但是我已经有一段时间没有这么做了,文档也不是很好,所以我可能记错了。事实上,我看了一下,把样本和框架弄糊涂了。我想你只想除以2。(每个框架包含两个样本,每个样本有2个字节。)我在链接的openhome论坛上回答了这个问题,但为了读者的利益,我犯了一个错误,我说第一条评论是正确的。您不想对stats.samples使用固定值,需要在调用GetAudioBufferStats时通过查询BufferedWaveProvider.BufferedBytes计算它。