c# - 使用NAudio在Unity中创建AudioClip,在读取数据时卡住1-2秒

标签 c# unity3d audio naudio

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

在注释掉以下几行时,没有任何障碍。

aud =新的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”流不支持的错误。这是我使用的代码。
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));
}

}

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

非常感谢

最佳答案

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

因为AudioFileReader不是Unity API,所以您应该可以在Thread中使用它。从另一个线程读取音频的 float 数据后,您就可以对主线程进行回调,以使用AudioClip.Create函数创建AudioClip,因为您无法从主线程使用此API。

捕获UnityThread,可以从this帖子中轻松地在主线程上进行回调,然后在下面查看新的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);
            });
        }
    });
}

关于c# - 使用NAudio在Unity中创建AudioClip,在读取数据时卡住1-2秒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53446540/

相关文章:

c# - .NET 6 如何处理程序集引用冲突?

c# - ASP MVC : Sending an E-mail

c++ - 如何在音轨中找到无声部分

c# - 已存在与此命令关联的打开的 DataReader,必须先将其关闭 在 Nopcommerce 中

c# - .NET Core编译错误:找不到类型或 namespace 名称 'LibGpiodDriver'

javascript - 显然我不能在预制件中保留游戏对象。我该如何解决这个问题?

audio - 使用 Unity3d 制作 VST

c# - Unity3d 中的 Material 、着色器和对象轮廓

android - ImageButton 音板安卓应用

audio - 在iOS 5中获取有关mp3文件的信息