TTS Engine

Hi all,

Is there another TTS Engine for Asterisk instead of Festival? I am facing bad voice quality problem in Festival.

I will be thankfull if anyone can tell me supported TTS engines.

Cepstral (cepstral.com) is mentioned in the Asterisk book - page 177. I have not tried it.

Cepstral is significantly better quality than festival. $30 to download (includes one voice, $30 for each additional voice).

Does Cepstral include the TTS engine? Or how do you install the Cepstral voices with Festival?

Cepstral includes a TTS engine. It also includes virtually NO documentation, but it’s pretty easy to use.

I use it from a System() command. I think someone may have built an application that allows you to use Cepstral directly, but I find it easy enough to just do it via commands.

HI,

Is Cepstral supporting Arabic and Asian Language? and is there any demo available?

Appears you may be able to test Cepstral with an AGI:

voip-info.org/wiki/view/Aste … l+www+demo

I will give it a try and let you know how it goes.

Alright, the demo above did not work as that individual’s website appears to be down. I did manage to get it working this way though (almost, see what is not working at the bottom), as it turns out phpagi.sourceforge.net has a swift function built-in to the library:

[quote="/etc/asterisk/extensions.ael"]context cepstral_test { s => { Answer(); Set(tts_text='This is a test using this voice'); Set(tts_lang='en'); AGI(cepstral_demo.php); Hangup(); };[/quote]

[quote="/var/lib/asterisk/agi-bin/cepstral_demo.php"][code]<?php
//Script to invoke Cepstral
require(‘phpagi.php’);
error_reporting(E_ALL);
$agi = new AGI();

$txt_array = $agi->get_variable(‘tts_text’);
if ($txt_array != 0) {
$text = $txt_array[‘data’];
$lang_array = $agi->get_variable(‘tts_lang’);

    if ($lang_array != 0) {
            $lang = $lang_array['data'];
            if ($lang == 'en') {
                    $swift_array = $agi->swift($text, '', 8000, 'Diane');
            } elseif ($lang == 'es') {
                    $swift_array = $agi->swift($text, '', 8000, 'Miguel');
            } else {
                    $swift_array = $agi->swift($text, '', 8000, 'Diane');
            }
    } else {
            $swift_array = $agi->swift($text, '', 8000, 'Diane');
    }

}

$agi->stream_file(‘goodbye’);
?>[/code][/quote]

Now, it invokes and plays back the correct voice on the first call. But if I change the ‘tts_lang’ variable in my extensions.ael and unload/load pbx_ael.so, the system still plays whichever voice was played regardless of what the setting is (I did test, and my logic in the script is correct that it picks up the right language).

It would appear that the function below may be picking up the first wav file to play back each time? Not sure, any ideas?

[quote=“PHPAGI.sourceforge.net”][code] function swift($text, $escape_digits=’’, $frequency=8000, $voice=NULL)
{
if(!is_null($voice))
$voice = “-n $voice”;
elseif(isset($this->config[‘cepstral’][‘voice’]))
$voice = “-n {$this->config[‘cepstral’][‘voice’]}”;

  $text = trim($text);
  if($text == '') return true;

  $hash = md5($text);
  $fname = $this->config['phpagi']['tempdir'] . DIRECTORY_SEPARATOR;
  $fname .= 'swift_' . $hash;

  // create wave file
  if(!file_exists("$fname.wav"))
  {
    // write text file
    if(!file_exists("$fname.txt"))
    {
      $fp = fopen("$fname.txt", 'w');
      fputs($fp, $text);
      fclose($fp);
    }

    shell_exec("{$this->config['cepstral']['swift']} -p audio/channels=1,audio/sampling-rate=$frequency $voice -o $fname.wav -f $fname.txt");
  }

  // stream it
  $ret = $this->stream_file($fname, $escape_digits);

// clean up old files
$delete = time() - 2592000; // 1 month
foreach(glob($this->config[‘phpagi’][‘tempdir’] . DIRECTORY_SEPARATOR . ‘swift_*’) as $file)
if(filemtime($file) < $delete)
unlink($file);

  return $ret;
}[/code][/quote]

If I delete all of the temp files in /var/spool/asterisk/sounds/tmp then it picks up the right voice without any other changes.

This solves the problem, looks like there might be a bug in PHPAGI for the swift function:

[quote="/var/lib/asterisk/agi-bin/cepstral_demo.php"][code]<?php
//Script to invoke Cepstral
require(‘phpagi.php’);
error_reporting(E_ALL);
$agi = new AGI();

$txt_array = $agi->get_variable(‘tts_text’);
if ($txt_array != 0) {
$text = $txt_array[‘data’];
$lang_array = $agi->get_variable(‘tts_lang’);

    if ($lang_array != 0) {
            $lang = $lang_array['data'];
            if ($lang == 'en') {
                    [b]$swift_fn = $agi->swift($text, '', 8000, 'Diane');[/b]
            } elseif ($lang == 'es') {
                    [b]$swift_fn = $agi->swift($text, '', 8000, 'Miguel');[/b]
            } else {
                    [b]$swift_fn = $agi->swift($text, '', 8000, 'Diane');[/b]
            }
    } else {
            [b]$swift_fn = $agi->swift($text, '', 8000, 'Diane');[/b]
    }

}

System(‘rm ‘.$swift_fn.’.*’);
?>[/code]

[quote=“PHPAGI”] // return $ret; return $fname; }[/quote][/quote]

By simply returing the filename instead of the original value which was the output of $agi->stream_file.

Hi MuppetMaster,

I am not using agiphp, i am using the perl. But i am going to apply your method in perl. If anything i will let you know.

Thank you for your kind of help