Использование NAudio для создания AudioClip в Unity, останавливается на 1-2 секунды при чтении данных - PullRequest
0 голосов
/ 23 ноября 2018

В настоящее время я использую приведенный ниже код в своем проекте 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));
}

}

Мне удалось немного улучшить ситуацию, сохранив последнюю сыгранную песню, чтобы, если пользователь выбрал предыдущую песню, которая там воспроизводиласьнет задержки.

Большое спасибо

1 Ответ

0 голосов
/ 24 ноября 2018

Аудио обычно загружается с помощью функции WWW.GetAudioClip, но, поскольку вы столкнулись с исключениями, вы решили использовать NAudio.Замораживание, которое происходит при выполнении AudioFileReader(musicPath) и aud.Read(AudioData, 0, (int)aud.Length), имеет смысл, поскольку этот конструктор и функция пытаются загрузить аудиофайл в основной поток и создают с ними данные PCM.

Поскольку AudioFileReader не является API Unity, вы должны иметь возможность использовать его из Thread.После того, как вы выполняете чтение плавающих данных аудио из другого потока, вы можете сделать обратный вызов основного потока, чтобы создать AudioClip с функцией AudioClip.Create, поскольку вы не можете использовать этот API из основного потока.

Grab UnityThread, который включает простой обратный вызов в главном потоке из этой записи , затем посмотрите, как должна выглядеть ваша новая функция LoadSong.Я использовал ThreadPool, но вы можете использовать любой другой Thread API в C #, если хотите.

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);
            });
        }
    });
}
...