我目前在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/