Unity中使用NAudio创建AudioClip,读取数据卡顿1-2秒

Using NAudio to create AudioClip in Unity, freezes 1-2 seconds while reading data

我目前在我的 Unity 项目中使用以下代码从目录流式传输 mp3 文件。它工作得很好但是,它在读入文件和填充浮点数时冻结。 由于这个项目是在 VR 中进行的,因此冻结非常刺耳。我怎样才能解决它以便它可以在没有锁定的情况下读入?我是否尝试将它放在另一个线程上?

注释掉下面几行时没有任何问题。

aud = new AudioFileReader(musicPath);

aud.Read(AudioData, 0, (int)aud.Length);

    public void LoadSong(string musicPath){

    //Set title of song
    songTitle = Path.GetFileNameWithoutExtension(musicPath);
    if(songTitle != currentlyPlaying && songTitle != lastPlayedTitle){
        //Parse the file with NAudio
        aud = new AudioFileReader(musicPath);

        //Create an empty float to fill with song data
        AudioData = new float[aud.Length];
        //Read the file and fill the float
        aud.Read(AudioData, 0, (int)aud.Length);

        //Create a clip file the size needed to collect the sound data
        craftClip = AudioClip.Create(songTitle, (int)aud.Length, aud.WaveFormat.Channels, aud.WaveFormat.SampleRate, false);
        //Fill the file with the sound data
        craftClip.SetData(AudioData, 0);

        if(craftClip.isReadyToPlay){
            playMusic(craftClip, songTitle);
            aud.Dispose();
         }

        }

        else
        {
            playMusic(lastPlayedAudioFile, lastPlayedTitle);
        }

}

我也尝试使用下面的代码下载这个问题 https://answers.unity.com/questions/933090/wwwgetaudioclip-streaming-of-mp3-on-this-plattform.html 中提到的文件,尽管包含文件类型,但我收到 'mp3' on this platform is not supported 错误.这是我使用的代码。

public class AudioDownloadTest : MonoBehaviour {
public AudioSource playThis;
public AudioClip clipy;
string pathh = @"D:\TestFiles\IntheAirTonightShort.mp3";

IEnumerator Download(string pathh){
    WWW song = new WWW(pathh);
    yield return song;
    clipy = song.GetAudioClip(false,false,AudioType.MPEG);
    playThis.clip = clipy;
}

void Start () {
    StartCoroutine(Download(pathh));
}

}

我设法通过存储最后播放的歌曲稍微改善了这种情况,这样如果用户选择播放的上一首歌曲就不会出现延迟。

非常感谢

音频通常使用 函数加载,但由于您 运行 对它有例外,所以您决定使用 NAudio。 AudioFileReader(musicPath)aud.Read(AudioData, 0, (int)aud.Length) 执行时发生的冻结是有道理的,因为此构造函数和函数试图在主线程上加载音频文件并使用它们创建 PCM 数据。

因为 AudioFileReader 不是 Unity API,你应该可以在 Thread 中使用它。从另一个线程读取音频的浮点数据后,您可以回调主线程以使用 AudioClip.Create 函数创建 AudioClip,因为您不能从主线程使用此 API线程。

this post 获取 UnityThread 可以在主线程上轻松回调,然后查看下面的新 LoadSong 函数应该是什么样子。我使用了 ThreadPool,但如果您愿意,您可以在 C# 中使用任何其他线程 API。

void Awake()
{
    //Enable Callback on the main Thread
    UnityThread.initUnityThread();
}

public void LoadSong(string musicPath)
{
    ThreadPool.QueueUserWorkItem(delegate
    {
        //Set title of song
        songTitle = Path.GetFileNameWithoutExtension(musicPath);
        if (songTitle != currentlyPlaying && songTitle != lastPlayedTitle)
        {
            //Parse the file with NAudio
            aud = new AudioFileReader(musicPath);

            //Create an empty float to fill with song data
            AudioData = new float[aud.Length];
            //Read the file and fill the float
            aud.Read(AudioData, 0, (int)aud.Length);

            //Now, create the clip on the main Thread and also play it
            UnityThread.executeInUpdate(() =>
            {
                //Create a clip file the size needed to collect the sound data
                craftClip = AudioClip.Create(songTitle, (int)aud.Length, aud.WaveFormat.Channels, aud.WaveFormat.SampleRate, false);
                //Fill the file with the sound data
                craftClip.SetData(AudioData, 0);

                if (craftClip.isReadyToPlay)
                {
                    playMusic(craftClip, songTitle);

                    /*Disposing on main thread may also introduce freezing so do that in a Thread too*/
                    ThreadPool.QueueUserWorkItem(delegate { aud.Dispose(); });
                }
            });
        }
        else
        {
            UnityThread.executeInUpdate(() =>
            {
                playMusic(lastPlayedAudioFile, lastPlayedTitle);
            });
        }
    });
}