Has anyone for any sample code to take a .wav file from the persistentDataPath, and play it?
I actually have a few I need to play back to back, so I’d need to know when each had finished playing so I could play the next one.
The wav files were generated by Unity, I just want to replay them now.
From what I understand I need to create and AudioClip and load the wavFile into it, then play through an AudioSource.
But I’m not sure how to do the load.
If someone has some simple working sample code that would be great.
but its struggling to do anythingwith the IEnumerator returned by the function.
Sorry, this is way outside my understanding.
And which bits need to go in the seperate function - just th download, or the play as well?
StartCoroutine() lets you run other method as yet another Update() loop, while IEnumerator returned by that method lets you control, when it has to do something.
When you “yield return www.SendWebRequest();” it suspends this coroutine until this UnityWebRequest is finished, that can be any number of frames, just the next line after “yield return” will be run in during first Update AFTER UnityWebRequest is complete.
The alternatives for coroutine are:
just start UnityWebRequest by calling SendWebRequest() and during the next frame check it’s isDone property; play audio when isDone becomes true; do this for each audio clip.
the SendWebRequest() returns an AsyncOperation, to which you can attach a completion handler, that will be called once loading finishes
OK, I have tried again
No errors, and it gets as far as printing the “DONE”
But no sound. I realise I probably need a flag to say if I want to be lookking to play something, but for now I’d settle for something coming out of the speakers.
What am I missing?
And also, I dont appear to be telling the audio source what clip to play. Do I need to do that, and if so how?
First of all, you are loading all of your sounds at once, not one by one. And you are only checking the last one for being done, you simply lose all other UnityWebRequest objects as you assign them all to the same variable.
You should also probably call Play() on audio source once, now you are calling it every frame after you’ve finished loading and I also don’t see where you take a loaded audio clip.
OK, thanks, I guess I can sort the logic out so it sets flags and does one at a time.
And only plays once.
Unfortunately it doesnt help that the code to generate said files only runs in android, so its difficult to debug.
What do you mean by ‘take a loaded audio clip’?
Do you mean assigned to the audio source?
And if so how?
I need to hard code TRUE to even get it into the bit where it prints DONE (I’ve no idea why), but it is getting in there.
If I have the proper if statement I just get ISDONE
Now it prints DONE
Nothing playing though.
I cant even begin to look at the logic until I can get a single clip to load and play.
Help …
Please …
Thanks
Can you play an audio clip normally through that audio source? As in you assign an audio clip directly to the source, and set it to play on awake, are you getting a sound?
It might be that your audio source and audio listeners are too far apart and the audio source is in 3D or something like that.
Also make sure the audio clip you’re downloading can be played if it’s just dumped in Unity.
I have made a little progress.
I started a whole new app to do some testing, as I am not able to test my main one in the editor due to the files being created in Android.
I’ve succesfully got it to output sound. It was repeating the one sound over and over.
I then set on adding logic to move on, and it obviously got stuck in a loop.
It crashed my PC, and on loading back up I’ve lost all of the gameobjects.
Forunately it kept my code.
I just need to work out the best way of moving through my list of files, playing them, and moving on to the next once it has finished.
This is what I ended up with when I crashed the PC:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System;
using UnityEngine.Networking;
public class TestSound : MonoBehaviour {
public GameObject textBox;
public AudioSource g03AudioSource;
bool playingSoundFile = false;
int clipCount = 1;
int clipIndex = 0;
UnityWebRequest www;
// Use this for initialization
void Start () {
textBox.GetComponent<Text>().text = Application.persistentDataPath;
ReplayAllSounds ();
}
// Update is called once per frame
void Update () {
checkIfSoundFileLoaded ();
}
// Replay All SOunds
public void ReplayAllSounds(){
//for (int x = 0; x < InteractionPanel.instance.saveClips.Count (); x++) {
playingSoundFile = false;
do {
//debugText.GetComponent<Text> ().text = debugText.GetComponent<Text> ().text + InteractionPanel.instance.saveClips[x];
textBox.GetComponent<Text> ().text = Application.persistentDataPath + "/test" + clipIndex + ".wav";
//string wavFile = Application.persistentDataPath + InteractionPanel.instance.saveClips[x];
//AudioClip audioClip = WavUtility.ToAudioClip (wavFile);
//AudioSource.PlayClipAtPoint = audioClip;
//AudioSource.PlayClipAtPoint ();
www = UnityWebRequestMultimedia.GetAudioClip (Application.persistentDataPath + "/test" + clipIndex + ".wav", AudioType.WAV);
www.SendWebRequest ();
playingSoundFile = false;
} while (clipIndex <= clipCount);
}
void checkIfSoundFileLoaded(){
if (www.isDone) {
//go3AudioSource.clip = www.GetA
textBox.GetComponent<Text> ().text = "ISDONE";
if (!g03AudioSource.isPlaying) {
textBox.GetComponent<Text> ().text = "DONE";
playingSoundFile = true;
AudioClip audioClip = DownloadHandlerAudioClip.GetContent (www);
g03AudioSource.clip = audioClip;
g03AudioSource.Play ();
}
else{
// CLip Finished
clipIndex++;
}
}
}
}
OK, so in the above code it must have gone into an infinite loop in my while loop.
But I’m struggling to work out the best way of looping through.
Because I am going out to a background process, if I use a loop it just runs away through the for loop through all my values before the first sound has finished playing.
If I use a do/while it just spins until it crashes.
Could someone help me out with the best syntax to be able to loop through my list of files, but then checking whether the current one completes in the background before moving on.
Right, apologies for the repeated posting.
Debugging this in the editor I think it seems to do what I want, although its not easy as it loads and plays the sounds in real time.
But it only ever plays 1 sound.
I have files for test0.wav, test1.wav, test2.wav
Does the web request need resetting - does it always think it is complete after the first one, even though it has moved on to a new request?
Or more generally, is there a better way to do this (most likely)?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System;
using UnityEngine.Networking;
public class TestSound : MonoBehaviour {
public GameObject textBox;
public AudioSource g03AudioSource;
bool playingSoundFile = false;
bool loadingAudioClip = false;
int clipCount = 2;
int clipIndex = 0;
UnityWebRequest www;
// Use this for initialization
void Start () {
textBox.GetComponent<Text>().text = Application.persistentDataPath;
}
// Update is called once per frame
void Update () {
ReplayAllSounds ();
checkIfSoundFileLoaded ();
}
// Replay All SOunds
public void ReplayAllSounds(){
if (clipIndex <= clipCount && playingSoundFile == false && loadingAudioClip == false){
textBox.GetComponent<Text> ().text = Application.persistentDataPath + "/test" + clipIndex + ".wav";
loadingAudioClip = true;
playingSoundFile = false;
www = UnityWebRequestMultimedia.GetAudioClip (Application.persistentDataPath + "/test" + clipIndex + ".wav", AudioType.WAV);
www.SendWebRequest ();
}
}
void checkIfSoundFileLoaded(){
if (www.isDone ) { // If loaded
textBox.GetComponent<Text> ().text = "ISLOADED " + clipIndex;
if (!g03AudioSource.isPlaying) { // If not playing
// First time not playing - startplaying
if (playingSoundFile == false ) {
playingSoundFile = true;
textBox.GetComponent<Text> ().text = "ISPLAYING "+ clipIndex;
playingSoundFile = true; //set flag to say playing
AudioClip audioClip = DownloadHandlerAudioClip.GetContent (www);
g03AudioSource.clip = audioClip;
g03AudioSource.Play (); // and play
}
else
{
// we have already played and finished
playingSoundFile = false;
loadingAudioClip = false;
clipIndex++; // move on to next one
}
}
}
}
}
From what I can tell g03AudioSource.isPlaying seems unreliable as a test to see whether the current clip is completed.
It seems to always return true
In fact, looking at the API docs it seems to imply this is only set when the Pause method is called.
Are there any known issues with its reliability to tell if the clip is complete?
Stepping back from this slightly, all I need to do is play a load of clips in the order they were created.
After this, I’d like to offer the option to save into a single wav file anyway.
So perhaps I’m better off cutting out the middle man and instead of playing the clips just combinging them into a single file.
To repeat my original question that was asked many hours ago, does anyone have any sample code for that?
To the original post, I’d like to find a WAV parser to load WAV files, because Unity’s is broken in webGL. Note: some files work, and some files work on one server but not from another, even though they are identical. Why? I don’t work for Unity so I can’t say, except I need something that always works. Please.