在C#中播放ohLibSpotify PCM数据流,n音讯 [英] Playing ohLibSpotify pcm data stream in C# with NAudio

查看:769
本文介绍了在C#中播放ohLibSpotify PCM数据流,n音讯的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想打从ohLibSpotify C#库( https://github.com/openhome提供原始PCM数据/ ohLibSpotify )。

我得到以下回调的数据:

 公共无效MusicDeliveryCallback(SpotifySession会议,AudioFormat的格式,IntPtr的框架,诠释num_frames)
{
    //实例数据
    //format.channels = 2,format.samplerate = 44100,format.sample_type = Int16NativeEndian
    //帧=?
    // num_frames = 2048
}
 

现在我想直接与n音讯播放接收到的数据( HTTP://naudio.$c$cplex .COM / )。用下面的code段,我可以从硬盘播放一个MP3文件。是否有可能从Spotify的接收到的数据直接传递到n音讯,并实时播放呢?

 使用(VAR毫秒= File.OpenRead(test.pcm))
使用(VAR RDR =新Mp3FileReader(MS))
使用(VAR wavStream = WaveFor​​matConversionStream.CreatePcmStream(RDR))
使用(VAR baStream =新BlockAlignReductionStream(wavStream))
使用(VAR waveout的=新waveout的(WaveCallbackInfo.FunctionCallback()))
{
    waveOut.Init(baStream);
    waveOut.Play();
    而(waveOut.PlaybackState == PlaybackState.Playing)
    {
        Thread.sleep代码(100);
    }
}
 


编辑: 我更新了我的code。该计划不会引发任何错误,但我也不能听音乐。什么是错误的,我code?

这是音乐传递回调:

 公共无效MusicDeliveryCallback(SpotifySession会议,AudioFormat的格式,IntPtr的框架,诠释num_frames)
{
    //format.channels = 2,format.samplerate = 44100,format.sample_type = Int16NativeEndian
    //帧=?
    // num_frames = 2048

    byte []的frames_copy =新的字节[num_frames]
    Marshal.Copy(帧,frames_copy,0,num_frames);

    bufferedWaveProvider =新BufferedWaveProvider(新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);

    如果(_waveOutDeviceInitialized ==假)
    {
        IWavePlayer waveOutDevice =新waveout的();
        waveOutDevice.Init(bufferedWaveProvider);
        waveOutDevice.Play();
        _waveOutDeviceInitialized = TRUE;
    }
}
 

而这些都是在SessionListener被覆盖的回调:

 公众覆盖INT MusicDelivery(SpotifySession会议,AudioFormat的格式,IntPtr的框架,诠释num_frames)
{
    _sessionManager.MusicDeliveryCallback(会话,格式,帧,num_frames);
    返回base.MusicDelivery(会话,格式,帧,num_frames);
}

公众覆盖无效GetAudioBufferStats(SpotifySession会议,出AudioBufferStats统计)
{
    stats.samples = 2048/2; // ???
    stats.stutter = 0; // ???
}
 

解决方案

我想你可以这样做:

  1. 创建一个BufferedWaveProvider。
  2. 通过这个来waveOut.Init。
  3. 在MusicDeliveryCallback,使用Marshal.Copy从本地缓存复制到托管字节数组中。
  4. 通过这个管理字节数组AddSamples您BufferedWaveProvider。
  5. 在GetAudioBufferStats回调,使用bufferedWaveProvider.BufferedBytes / 2的样本,并留下迟缓为0。

我的认为的,将工作。它涉及到一些不必要的复制和不准确的跟踪断断续续的,但它是一个很好的起点。我想这可能是一个更好的(更高效,更可靠的)解决方案来实现IWaveProvider和管理的缓冲吧。

我写了ohLibSpotify包装库,但我并不在同一个公司工作了,所以我不参与它的发展了。您也许能够从别人得到更多的帮助,在这个论坛上: HTTP://forum.openhome .ORG / forumdisplay.php?FID = 6 至于音乐传输的推移,ohLibSpotify的目标有尽可能小的开销越好。它不会在所有的,它只是通过在同一本地的libspotify库本身提供的指针复制的音乐数据的,这样您就可以自己把它复制到它的最终目的地,避免不必要的层复制。它并使它有点笨重的简单的使用,虽然。

祝你好运!

I'm trying to play raw pcm data delivered from ohLibSpotify c# library (https://github.com/openhome/ohLibSpotify).

I get the data in the following callback:

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
}

Now i want to directly play the received data with NAudio (http://naudio.codeplex.com/). With the following code snippet i can play a mp3 file from disk. Is it possible to directly pass the data received from spotify to NAudio and play it in realtime?

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);
    }
}


EDIT: I updated my code. The program doesn't throw any errors, but i also can't hear music. Is anything wrong in my code?

This is the music delivery callback:

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;
    }
}

And these are the overwritten callbacks in the 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;          //???
}

解决方案

I think you can do this:

  1. Create a BufferedWaveProvider.
  2. Pass this to waveOut.Init.
  3. In your MusicDeliveryCallback, use Marshal.Copy to copy from the native buffer into a managed byte array.
  4. Pass this managed byte array to AddSamples on your BufferedWaveProvider.
  5. In your GetAudioBufferStats callback, use bufferedWaveProvider.BufferedBytes / 2 for "samples" and leave "stutters" as 0.

I think that will work. It involves some unnecessary copying and doesn't accurately keep track of stutters, but it's a good starting point. I think it might be a better (more efficient and reliable) solution to implement IWaveProvider and manage the buffering yourself.

I wrote the ohLibSpotify wrapper-library, but I don't work for the same company anymore, so I'm not involved in its development anymore. You might be able to get more help from someone on this forum: http://forum.openhome.org/forumdisplay.php?fid=6 So far as music delivery goes, ohLibSpotify aims to have as little overhead as possible. It doesn't copy the music data at all, it just passes you the same native pointer that the libspotify library itself provided, so that you can copy it yourself to its final destination and avoid an unnecessary layer of copying. It does make it a bit clunky for simple usage, though.

Good luck!

这篇关于在C#中播放ohLibSpotify PCM数据流,n音讯的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆