I’m struggling to get multiple wav files to be loaded from persistant data are and played one after another.
I did have another thread on this which got out of control, so thought I’d try again afresh with a simple example.
The filenames for the clips are in a List. But for the purpose of this test I’m just using an index x to find files test1, test2, test3.wav in persistant data path. They need to be there, as I create them earlier.
I’m initially checking if I need to load a file using WWW in ReplayAllSOunds. If I do, I’ll start loading it.
Then I’ll check if it is loaded.
If it is and thats the first time I check I’ll start playing it and set a flag
What I cant work out is how to know it has finished playing it, and how to get my ReplayAllSounds method should move on to the next file. I’ve tried yield. I’ve tried isPlaying(). I’ve tried using the time as per the current example. Nothing seems to work. It plays the first clip and thats it.
If someone could get this simple example working I’d be very grateful. I’m made the example code as simple as I possibly can, it just needs someone who knows how to tell when its playing and when its not.
Thank You in advanace. I’m sure its fairly simple, but I’m new to all this and struggling badly with this.
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;
bool needToLoadAudioclip = true;
bool needToCheckForAudioclip = false;
int clipCount = 2;
int clipIndex = 0;
float progress;
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 && needToLoadAudioclip == true){
textBox.GetComponent<Text> ().text = Application.persistentDataPath + "/test" + clipIndex + ".wav";
loadingAudioClip = true;
needToCheckForAudioclip = true;
playingSoundFile = false;
www = UnityWebRequestMultimedia.GetAudioClip (Application.persistentDataPath + "/test" + clipIndex + ".wav", AudioType.WAV);
www.SendWebRequest ();
}
}
void checkIfSoundFileLoaded(){
if (needToCheckForAudioclip == true) {
if (www.isDone) { // If loaded
loadingAudioClip = false;
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
{
progress = Mathf.Clamp01(g03AudioSource.time / g03AudioSource.clip.length);
if (progress == 1f)
{
g03AudioSource.Stop ();
www.Abort ();
www.Dispose ();
playingSoundFile = false;
loadingAudioClip = false;
needToCheckForAudioclip = false;
needToLoadAudioclip = true;
clipIndex++; // move on to next one
}
}
}
}
}
}
I think I would personally organize things a bit differently.
However, before getting into that, if you write a small test script and play 1 clip from an audio source (doesn’t even have to go through WWW), can you simply check in Update for “isPlaying” do you get false when it’s over?
I dont think isPlaying is reliable.
In my previous testing I’m pretty sure it isn’t.
The difficulty I have is its very difficult to tell in debug mode, because by the time it steps through the code it has finished.
I think it appears to work the first time. But not subsequent times.
What I actually see if debugging is it plays the first sound.
It then seems to go through properly and should play the 2nd one but doesn’t.
I I think click stop in the unity player, I actually get the start or the sound.
I’ve taken out the bit I added where I was trying to get the length of the file, now I’m back as I was relying on isPlaying - I think that is simpler.
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;
bool needToLoadAudioclip = true;
bool needToCheckForAudioclip = false;
int clipCount = 2;
int clipIndex = 0;
float progress;
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 && needToLoadAudioclip == true){
textBox.GetComponent<Text> ().text = Application.persistentDataPath + "/test" + clipIndex + ".wav";
loadingAudioClip = true;
needToCheckForAudioclip = true;
playingSoundFile = false;
www = UnityWebRequestMultimedia.GetAudioClip (Application.persistentDataPath + "/test" + clipIndex + ".wav", AudioType.WAV);
www.SendWebRequest ();
}
}
void checkIfSoundFileLoaded(){
if (needToCheckForAudioclip == true) {
if (www.isDone) { // If loaded
loadingAudioClip = false;
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 {
{
g03AudioSource.Stop ();
www.Abort ();
www.Dispose ();
playingSoundFile = false;
loadingAudioClip = false;
needToCheckForAudioclip = false;
needToLoadAudioclip = true;
clipIndex++; // move on to next one
}
}
}
}
}
}
Thanks. I’m using it as I dont know how else to reliably do it unfortunately.
I was hoping somebody knows or has done this.
If you read my other thread (its a long one) I’ve tried yield, I’ve tried coroutines, I just couldn’t get it working.
Then every time someone suggested another way I just went down another dead end.
Hence starting afresh to see if anyone has done this before.
I also found the following, but couldn’t get that to work either!
Part of the issue of course is my limited c# and Unity skills. I’m been putting my app together using other’s code where I’ve got stuck.
This time I have got stuck and nobody seems to have done anything similar, even though in theory it doesn’t sound like a particularly complicated way to do it.
One other option is to forget about the playing of the clips, and instead combine them into a single large clip that I can just play. I may start another thread on that, as at least it would get around the isPlaying issue.
Ya, if they always play together, making one clip sounds reasonable.
If you want to share a few small music clips in a zip file, some online storage you have and paste a link here… I’d be happy to try to get it working when I have a free few mins , just to see if I can - for fun
I’d be absolutely delighted if you can get that working! It will just be these files in this order, doesn’t need to be any more flexible than being able to write them out to one big file.
The difficulty seems to be they need to be loaded with WWW rather than just attached to the project.
I’ve PM’d you with a link to some sample files.
Not sure if it helps, but this was the next dead end I was going to try driving down:
Surely I was slightly lazy at removing a few print statements and one yield (0.1f) that isn’t needed.
For like 20 mins I couldn’t even play the file, until I added “file://” sigh. lol that slowed me down.
I also didn’t retry “Play” instead of OneShot… as I changed that when nothing was working, early on.
Wow. You’re a genius. Thank you very much. That works perfectly.
However, I’ve now discovered one more HUGE problem:(
Some of these clips are microphone recordings.
I’m grabbing them with the code here, which I converted to c#
(post #9)
I’m hard coding tmerec to 20, as I dont know in advance how long the recording will be.
Which means my short recording is actually 20 seconds long. I hadn’t even realised up until now
So it waits upto 20 seconds before playing the next one.
So it looks like I need to revisit this recording code. Looks lile there are functions to trim Silence, though I dont think they ever get called, and I’m really not sure what they even do. Maybe I need to call them when I hit my stop recording button. Unfortunately, it wasn’t totally clear to me what it was doing, it just ‘worked’
Once again its been a long day so I’ll have to revist tomorrow.
Many thanks for your help on this, the bit you have done works prefectly. On to the next problem!
EDIT: it looks to be further discussed here.
Ya, I would suggest that you either try to end the recording as soon as possible. If not, and whatever seems complicated or not working, find a useful audio editing program. you can probably cut it there
Luckily the ones you sent me didn’t have that lol … at least not that I noticed.
For info, I managed to get your code fully integrated into my app, and also fixed the clip length using bits of the code I linked to above.
Many thanks again for your help.