csharp 从Unity3D中的CoherentUI浏览器获取PCM音频数据,并通过Unity音频过滤器播放。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp 从Unity3D中的CoherentUI浏览器获取PCM音频数据,并通过Unity音频过滤器播放。相关的知识,希望对你有一定的参考价值。

using UnityEngine;
using System.Collections;
using Coherent.UI;
using System.IO;
using System;
using System.Runtime.InteropServices;

[RequireComponent(typeof(CoherentUIView))]
[RequireComponent(typeof(AudioSource))]
unsafe public class CoherentAudioPlayerFilter : MonoBehaviour
{
    public int BufferSize = 8192;
    [Range(0, 2f)] public float gain = 1f;

    View m_View;
    UnityViewListener m_ViewListener;
    new AudioSource audio;    

    int m_StreamId;
    int m_BitDepth;
    int m_Frequency;
    int m_Channels;

    bool isPlaying;

    void Start ()
    {
        audio = GetComponent<AudioSource>();
        GetComponent<CoherentUIView>().OnViewCreated += InitBrowser;
    }

    void InitBrowser(View view)
    {
        m_View = view;
        m_ViewListener = GetComponent<CoherentUIView>().Listener;

        m_ViewListener.AudioStreamCreated += this.OnAudioStreamCreated;
        m_ViewListener.AudioStreamPlay += this.OnAudioStreamPlay;
        m_ViewListener.AudioStreamPause += this.OnAudioStreamPause;
        m_ViewListener.AudioStreamClose += this.OnAudioStreamClose;
    }

    void OnAudioFilterRead(float[] data, int channels)
    {
        if (!isPlaying) return;

        int numBytes = data.Length * 2;
        IntPtr m_AudioBuffer = Marshal.AllocHGlobal(numBytes);

        // When you need more data to play for stream #streamID
        int timeout = 0; // A zero timeout means block until data is received
        int received = m_View.GetAudioData(m_StreamId, m_AudioBuffer, numBytes, timeout);
        if (received <= 0)
        {
            // Negative values indicate an error; Zero is a valid return value if no data is present
            return;
        }

        // Get a byte pointer from the unmanaged memory block. 
        byte* audioBufferBytePtr = (byte*)m_AudioBuffer.ToPointer();
        UnmanagedMemoryStream readStream = new UnmanagedMemoryStream(audioBufferBytePtr, received, numBytes, FileAccess.Read);
        // Create a byte array to hold data from unmanaged memory. 
        byte[] managedData = new byte[received];

        // Read from unmanaged memory to the byte array.
        readStream.Read(managedData, 0, received);
        readStream.Close();
        // You now have your data in *managedData* and you can set it to the audio clip.

        //WriteToConsole("manageddata", ArrayToString(managedData));

        float[] audioFloats = PCMBytesToFloats(managedData);

        for (int i = 0; i < audioFloats.Length; i++)
        {
            data[i] = audioFloats[i] * gain;
        }
    }

    public void OnAudioStreamCreated(int streamId, int channels, int bitDepth, int frequency)
    {
        Debug.Log("sid = " + streamId + " channels = " + channels + " bitdepth = " + bitDepth + " frequency = " + frequency);
        m_StreamId = streamId;
        m_Channels = channels;
        m_BitDepth = bitDepth;
        m_Frequency = frequency;

        AudioClip audioClip = AudioClip.Create("browser-audio-" + streamId, BufferSize, m_Channels, 44000, false);
        audio.clip = audioClip;
    }

    public void OnAudioStreamPlay(int streamId)
    {
        Debug.Log("on audio stream play");
        isPlaying = true;
        audio.Play();
    }

    public void OnAudioStreamPause(int streamId)
    {
        Debug.Log("on audio stream pause");
        isPlaying = false;
        audio.Pause();
    }

    public void OnAudioStreamClose(int streamId)
    {
        Debug.Log("on audio stream close");
        isPlaying = false;
        audio.Stop();
    }

    static float[] PCMBytesToFloats(byte[] bytes)
    {
        float[] floats = new float[bytes.Length / 2];
        for (int i = 0; i < bytes.Length; i += 2)
        {
            short s = BitConverter.ToInt16(bytes, i); // convert 2 bytes to short
            floats[i / 2] = ((float)s) / (float)32768; // convert short to float
        }
        return floats;
    }
  }
}

以上是关于csharp 从Unity3D中的CoherentUI浏览器获取PCM音频数据,并通过Unity音频过滤器播放。的主要内容,如果未能解决你的问题,请参考以下文章

csharp Unity3D预处理器指令

csharp 适用于Unity3D的超级银河战士风格相机。

csharp Unity3d在IOS和Android上播放视频

Unity3D研究院之通过C#使用Advanced CSharp Messenger(五十)

csharp ConcurrentQueue使用锁在旧的.NET项目中使用(如在Unity3D中)

Unity3D 加密 Assembly-CSharp.dll (Android平台) 防止反编译