Playing Audio files for "Text To Speech"

Hello, I have been experimenting a bit. And I was wondering how I could make my own “text to speech”.

The way it works is, there is a library of audio files representing a word. When the user inputs text, the string will get split, and check to see if the word is in the database. If it is, it will match up the word with the name of the audio clip. If not, it will skip it.

I got everything to work. Though when it comes to actually playing the sound… That is where the issue comes in.

I tried to loop through the list of words, and set a bool based on whether or not the Audio Source is finished playing. This bool is called “canSpeak”. The audio source would get the audio clip applied, and if it “could Speak” then it would play it.

The problem is, it won’t wait for the clip. It won’t change the clip in the audio source (unless it’s just too fast). And most of all. It skips to the last word. And only plays that. So if I type in “hi my name is bob”… it will just say “bob”.

This is my code.

public void ParseText()
    {
        tiString = ti.text.ToLower();
        string[] st;
        st = tiString.Split(' ');

        for (int i = 0; i < wd.words.Count -1; i++)
        {
            if (wd.words.Contains(st[i]))
            {
                aus.clip = wd.sounds[i];
                aus.Play();
                Debug.Log("Word: <color=yellow>" + st[i] + "</color> <color=green>is valid.</color>");
            }
            else
            {
                Debug.Log("Word: <color=yellow>" + st[i] + "</color> <color=red>is not valid.</color>");
            }
        }
    }

Is there something I am doing wrong? I have been playing with this for hours now and can’t figure it out :confused:

1 Like

The Problem you are running into is this: you are assuming that the Audio source would be queuing the Audio Clips for you. But it doesn’t. The line ‘aus.clip = xxx’ tells it ‘Forget anything you are playing, and get ready to play THIS’. You do this a couple of times, and finally, you end up with Bob’s Clip, and that gets played. The Audio source is doing exactly what you are telling it to do, you are assuming it is much smarter than it actually is :slight_smile:

What you Need to do is implement your own Clip Queue, and play each Clip after the one before as been played completely. Unfortunately, there is no good way in Unity right now to do that except actively polling the Audiosource and seeing if it is still playing (why Unity doesn’t have a OnAudioFinished is beyond me). Tedious stuff, not really difficult, but highly annoying. I bet everyone has written their own Audio Queue at some Point.

Hello, Thanks for your response. I have tried to find a simple audio queue example. But when I tried to implement it, it won’t actually add the files to the queue.

This is my new code: It’s using this Queue Package .

public void ParseText()
    {
        tiString = ti.text.ToLower();
        string[] st;
        st = tiString.Split(' ');

        foreach(string s in st)
        {
            if (wd.words.Contains(s))
            {
                int idx = wd.words.IndexOf(s);
                aq.AddToQueue(wd.sounds[idx]);
                Debug.Log("Word: <color=yellow>" + s + "</color> <color=green>is valid.</color>");
                aq.Delay = wd.sounds[idx].length;
                aq.PlayNextClip();
            }
            else
            {
                Debug.Log("Word: <color=yellow>" + s + "</color> <color=red>is not valid.</color>");
            }
        }
    }

The text function still works, but the audio queue is still broken.

I have also tried to make it so the delay will be set to the clip length, so it won’t overlap.

Is there anything else I could do better? This is my first time experimenting with this type of stuff.

Two thoughts:

  1. you are calling aq.PlayNextClip from within the loop, directly after adding the sound. Not knowing anything about your implementation of the Audio Queue, this still feels wrong, like pressing ‘Skip’ on the remote every time you queue up another song.

  2. you don’t show the wd.sounds array/list in the inspector. Make sure that all sounds are correctly loaded, and that you have access to wd.

Cheers,
-ch