与 Naudio RadioStreaming 的 Unity

Posted

技术标签:

【中文标题】与 Naudio RadioStreaming 的 Unity【英文标题】:Unity with Naudio RadioStreaming 【发布时间】:2015-08-09 16:38:15 【问题描述】:

我在 Unity 游戏中使用基于 NAudio Demo modified for streaming a Shoutcast 的脚本。

我尝试使用 MonoBehvaiour 类中的更新来删除原始的 while 循环,但在我使用此脚本进行流式传输时,我只听到了一些噪音但没有音乐。

在执行与格式相关时,我通常会遇到错误

MmException: AcmNotPossible 调用 acmStreamConvert NAudio.MmException.Try(MmResult 结果,System.String 函数) NAudio.Wave.Compression.AcmStreamHeader.Convert (Int32 bytesToConvert, System.Int32& sourceBytesConverted) NAudio.Wave.Compression.AcmStream.Convert (Int32 bytesToConvert, System.Int32& sourceBytesConverted) NAudio.Wave.AcmMp3FrameDecompressor.DecompressFrame (NAudio.Wave.Mp3Frame frame, System.Byte[] dest, Int32 destOffset)

我在网上尝试过使用不同的收音机,但我总是收到这个错误。我不知道发生了什么...有什么帮助吗?

 public class NAudiostreamer : MonoBehaviour 

    private IWavePlayer mWaveOutDevice;


    private WaveStream  mMainOutputStream;
    private WaveChannel32 mVolumeStream;
    private VolumeWaveProvider16 volumeProvider;



    private string m_Url = "http://37.59.32.115:8122/";


    enum StreamingPlaybackState
    
        Stopped,
        Playing,
        Buffering,
        Paused
    

    private volatile StreamingPlaybackState playbackState = StreamingPlaybackState.Stopped;


    private bool fullyDownloaded = false;
    public bool m_Play = false;
    float timer;

    void Update()
    
        if (m_Play)
        
            playbackState = StreamingPlaybackState.Buffering;
            StreamMP3(m_Url);
            m_Play = false;
        

        switch (playbackState)
        
            case StreamingPlaybackState.Buffering:
            case StreamingPlaybackState.Playing:
                StreamMP3(m_Url);
                break;

            default:        
                break;
        

    

    HttpWebRequest webRequest;
    BufferedWaveProvider bufferedWaveProvider = null;
    byte[] buffer = new byte[16384 * 4];


    private void StreamMP3(string lUrl)
    
        this.fullyDownloaded = false;
        webRequest = (HttpWebRequest)WebRequest.Create(lUrl);

        int metaInt = 0; // blocksize of mp3 data

        webRequest.Headers.Clear();
        webRequest.Headers.Add("GET", "/ HTTP/1.0");

        webRequest.Headers.Add("Icy-MetaData", "1");
        webRequest.UserAgent = "WinampMPEG/5.09";

        HttpWebResponse resp = null;
        try
        
            resp = (HttpWebResponse)webRequest.GetResponse();
        
        catch(WebException e)
        
            if (e.Status != WebExceptionStatus.RequestCanceled)
            
                Debug.LogError(e.Message);
            
            return;
        
         // needs to be big enough to hold a decompressed frame

        try
        
            // read blocksize to find metadata block
            metaInt = Convert.ToInt32(resp.GetResponseHeader("icy-metaint"));

        
        catch
        
        

        IMp3FrameDecompressor decompressor = null;

        try
        
            using (var responseStream = resp.GetResponseStream())
            

                ReadFullyStream readFullyStream = new ReadFullyStream(responseStream);
                //do
                
                    if (bufferedWaveProvider != null && bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes < bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4)
                    
                        Debug.LogError("Buffer getting full, taking a break");
                        Thread.Sleep(500);
                    
                    else
                    
                        Mp3Frame frame = null;
                        try
                        

                            frame = Mp3Frame.LoadFromStream(readFullyStream, true);



                        
                        catch (EndOfStreamException)
                        
                            this.fullyDownloaded = true;
                            Debug.LogError("reached the end of the MP3 file / stream");
                            // reached the end of the MP3 file / stream
//                          break;
                        
                        catch (WebException)
                        
                            // probably we have aborted download from the GUI thread
//                          break;
                        
                        if (decompressor == null && frame != null)
                        
                            // don't think these details matter too much - just help ACM select the right codec
                            // however, the buffered provider doesn't know what sample rate it is working at
                            // until we have a frame
                            WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate);
                            decompressor = new AcmMp3FrameDecompressor(waveFormat);
                            if(bufferedWaveProvider == null)
                            
                                this.bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat);
                                this.bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(20); // allow us to get well ahead of ourselves
                            

                        

                        int decompressed =  decompressor.DecompressFrame(frame, buffer, 0);

                        if(bufferedWaveProvider != null)
                        
                            bufferedWaveProvider.AddSamples(buffer, 0, decompressed);

                        
                    
                 

                if (this.mWaveOutDevice == null && this.bufferedWaveProvider != null)
                
                    Debug.Log("Creating WaveOut Device");
                    this.mWaveOutDevice = new  WaveOut();
                    this.volumeProvider = new VolumeWaveProvider16(bufferedWaveProvider);
                    this.volumeProvider.Volume = 100.0f;
                    mWaveOutDevice.Init(volumeProvider);

                
                else if (bufferedWaveProvider != null)
                
                    double bufferedSeconds = bufferedWaveProvider.BufferedDuration.TotalSeconds;
                    if(bufferedSeconds > 0.2f && playbackState == StreamingPlaybackState.Buffering)
                    
                        Debug.Log("PLaying music...");
                        mWaveOutDevice.Play();
                        playbackState = StreamingPlaybackState.Playing;
                    

                
            
        
        finally
        
            if (decompressor != null)
            
                decompressor.Dispose();
            
        
    

【问题讨论】:

【参考方案1】:

ACM 错误意味着机器上没有 ACM MP3 解码器,或者可能接收到损坏的帧(或某些专辑封面被误解为帧)。是后者,您可以捕获错误并忽略它。如果是前者,则需要安装解码器,或使用不同的 MP3 帧解压缩器。 (可能是NLayer one)。

【讨论】:

以上是关于与 Naudio RadioStreaming 的 Unity的主要内容,如果未能解决你的问题,请参考以下文章

NAudio 与 MultiplexingSampleProvider 和 WasapiOut

NAudio - WaveOut 与 WaveOffsetStream 一起使用时不会引发 PlaybackStopped 事件

wav 文件连接异常与 naudio 库

如何使用 NAudio 将两个 wav 音频文件与 30 秒的白色声音连接起来

VST.NET 与 NAUDIO(vstaudiobuffer 与 pcmstream 缓冲区)

有没有办法将 NAudio.Lame 与 Xamarin (Android/iOS) 应用程序一起使用?