Unity中使用NAudio创建AudioClip,读取数据时卡顿1-2秒
Posted
技术标签:
【中文标题】Unity中使用NAudio创建AudioClip,读取数据时卡顿1-2秒【英文标题】:Using NAudio to create AudioClip in Unity, freezes 1-2 seconds while reading data 【发布时间】:2018-11-23 12:14:20 【问题描述】:我目前在我的 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”流式传输错误。这是我使用的代码。
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));
我已经设法通过存储最后播放的歌曲来稍微改善这种情况,这样如果用户选择上一首播放的歌曲就不会延迟。
非常感谢
【问题讨论】:
能否将aud.Read(AudioData, 0, (int)aud.Length)
及以下的代码注释掉,看看问题是否真的存在?
本可以发誓我已经这样做了,但也许没有:/ 它仍然会发生,但时间较短,抱歉让我再看看。
currentSong.isDone
正在正确使用机器人。您的 LoadSong 函数应该是一个协程函数,您应该放入 isDone 循环并使用 StartCoroutine 调用该函数。有关更多示例,请参阅duplicate。
删除 WWW 相关代码仍然会导致问题,因为音频文件的路径直接传递给 AudioFileReader,所以功能不需要它。我会将我的问题更改为不使用 WWW 的功能代码。
创建新的 AudioFileReader 时会出现问题,然后在读取文件时会延长。它会因音频文件的大小而异,但这些问题肯定会发生。
【参考方案1】:
Audio 通常使用 WWW.GetAudioClip
函数加载,但由于您遇到了异常,因此您决定使用 NAudio。 AudioFileReader(musicPath)
和 aud.Read(AudioData, 0, (int)aud.Length)
执行时发生的冻结是有道理的,因为此构造函数和函数试图在主线程上加载音频文件并使用它们创建 PCM 数据。
因为AudioFileReader
不是 Unity API,您应该可以在 Thread 中使用它。从另一个线程读取音频的浮动数据后,您可以回调主线程以使用 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);
);
);
【讨论】:
非常感谢!它现在只是一个可以接受的微小的昙花一现。以上是关于Unity中使用NAudio创建AudioClip,读取数据时卡顿1-2秒的主要内容,如果未能解决你的问题,请参考以下文章
unity AudioSource 怎么转换 AudioClip? 求大神来解救新手