Link to home
Start Free TrialLog in
Avatar of InfoTechEE
InfoTechEE

asked on

TTS

In my Andoid app, I am trying to save Text-To-Speech to a file for playback at a later time. I am saving to a file using synthesizeToFile function of the TTS Engine. When I am using that function, I am providing a string variable called destFileName as one of the parameters, which holds the full path of the file.

My question is, once I synthesizeToFile, is there any way to use that file later to retrieve the  destFileName string?


Code below:

// Saves Text-To-Speech in a .wav file for future playback
//******************************************
string destFileName = "/sdcard/"  + ".wav";

HashMap<String, String> myHashRender = new HashMap();
              myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, previewName);
             
              try{
              if(myTTS.synthesizeToFile(saveText, myHashRender, destFileName) == TextToSpeech.SUCCESS)
              {
                    audioFileArrayList = GetFileInfo(previewName, destFileName);
                    Toast.makeText(getBaseContext(), "Saved Successfully!", Toast.LENGTH_SHORT).show();
              }
              else
                    Toast.makeText(getBaseContext(), "Oops! Something happened. Your text was not saved.", Toast.LENGTH_SHORT).show();
              } catch(Exception e) {
                    Toast.makeText(getBaseContext(), "synthesizeToFile Failed", Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
              }
Avatar of tampnic
tampnic
Flag of United Kingdom of Great Britain and Northern Ireland image

I'm not sure I understand your question - if you are using the file later then surely you must have known the path to it when you retrieved it.

A few other notes on the code ....
You should use getExternalFilesDir() to get a suitable path to write files to, after you have verified the SD card is available with Environment.getExternalStorageState().

You are not naming the file properly in your current code, just specifying a path and extension, so every time the function is called it overwrites the same file "/sdcard/.wav"

Cheers,
   Chris
Avatar of InfoTechEE
InfoTechEE

ASKER

I am able to write a for loop to cycle through all the files ending in .wav on the sd card and that's how I'm able to list them in my ListView. The problem is that it's not very user friendly and looks ugly to have a list of file names. I'd rather display the first 3 or 4 words of the saved text to speech (.wav) file. I store those first couple words in the string --  previewName.

Then -- myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, previewName);

I would like to display the previewName in a ListView and if the user clicks on that ListView Item it will play that .wav file.

Changed code below (added substring to .wav file name).


// Saves Text-To-Speech in a .wav file for future playback
//******************************************
string substr = saveText.substring(0,15);
string destFileName = "/sdcard/"  +  substr + ".wav";

HashMap<String, String> myHashRender = new HashMap();
              myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, previewName);
             
              try{
              if(myTTS.synthesizeToFile(saveText, myHashRender, destFileName) == TextToSpeech.SUCCESS)
              {
                    audioFileArrayList = GetFileInfo(previewName, destFileName);
                    Toast.makeText(getBaseContext(), "Saved Successfully!", Toast.LENGTH_SHORT).show();
              }
              else
                    Toast.makeText(getBaseContext(), "Oops! Something happened. Your text was not saved.", Toast.LENGTH_SHORT).show();
              } catch(Exception e) {
                    Toast.makeText(getBaseContext(), "synthesizeToFile Failed", Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
              }
Here's an example of what I'm looking for.

User types: "This is a test TTS message being saved to a file."

saveText = "This is a test TTS message being saved to a file."
previewName = "This is a test TTS..."
destFileName = "/sdcard/this.wav"

I know I will have to calculate the index of the first "space" character in order to save the first word of the sentence + .wav.

Anyways, then on the ListView I would like to display to the user, the many previewNames associated with the .wav files.

ListView:

This is a test TTS...
Just another test...
Here is one more...

If the user clicks on "This is a test TTS" it needs to play this.wav file.
You could store the WAV files in a database with metadata fields to describe the data. An Android cursor is limited to about 1Mb per row if I remember correctly so that's no good if your data is bigger then 1Mb. In that case store the filepath along with the descripition in the database instead.

Cheers,
   Chris
I'm a beginner and this is for a class project. Databases sound really complex and complicated. Is that true?

I just need to save short sentences for playback. Never exceeding 1mb.

I was thinking some kind of text file on the sd card that holds a list of description and file paths to whatever files on that card. That is if extracting the PreviewName from the wav file -- like in the original question -- is not possible.
ASKER CERTIFIED SOLUTION
Avatar of tampnic
tampnic
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
OK so extracting anything from the WAV file is not an option is what I'm understanding.

Will look into the database option as I do have MS SQL experience, but I only have 2 weeks left to finalize this project and I don't know how likely it is that I'll finish it in time. I only have about one and a half months experience programming the Android and about a year experience with JAVA all together. Having said that, I have doubts in my abilitites to implement this.

So are you saying a text file IS an option???

As far as "serializable" goes, I have read something about it when I was trying to pass an objects array from one activity to another. Instead I ended up implementing parselabel. What I'm doing now is inserting the PreviewName and DestinationFileName into a class object and storing that object into an Array. Then passing that array from my Main Activity which saves the WAV files to antoher Activity which displays the available files. The problem is once the App closes is that the Array is gone. Thats why I'm exploring these other options.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
If I had more time I would definitely use a database. Can u please point me in the right direction to use serializable to save array of objects to disk? And then retrieve that array later?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Wow, thanks so much for that example. I will try that code ASAP when I come home today.

When I was making my decision to use serializable vs. parselabel, I had to implement many weird methods to MyData class, but with Serializable, I'm noticing it's pretty simple. Looks easy. Will let you know how it goes.

Thanks again.