source: lliurex-jocomunico/trunk/fuentes/lliurex-jocomunico.install/var/lib/application/libraries/Myaudio.php @ 5728

Last change on this file since 5728 was 5728, checked in by joamuran, 3 years ago

Added zero-installed and updated jocomunico

  • Property svn:executable set to *
File size: 35.1 KB
Line 
1<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 
2
3class Myaudio {
4           
5    function __construct() {}
6   
7    /*
8     * RETURNS true if connected or false otherwise
9     */
10    public function isOnline() 
11    {
12        // pings example.com and google.com
13        $is_conn = null;
14        $connected1 = @fsockopen("www.example.com", 80); //website, port  (try 80 or 443)
15        $connected2 = @fsockopen("www.google.com", 80); //website, port  (try 80 or 443)
16        // if either is successful
17        if ($connected1 || $connected2){
18            $is_conn = true; //action when connected
19            fclose($connected1);
20            fclose($connected2);
21        }else{
22            $is_conn = false; //action in connection failure
23        }
24       
25        //[LLX]:checking if it's running under Ubuntu/LliureX, so, it's not "online at all" (Can't access online voices)
26        if (preg_match('/jocomunico/i', base_url())) $is_conn=false;
27        //[END LLX]
28       
29        return $is_conn;
30    }
31   
32    /*
33     * RETURNS 'local' if the App is running locally or 'server' if it's running from the server
34     */
35    public function AppLocalOrServer()
36    {
37        if (preg_match('/localhost/i', base_url())) return "local";
38        else if (preg_match('/jocomunico/i', base_url())) return "local"; // [LLX]: Uf it's on jocomunico, it's local too
39        else return "server";
40    }
41   
42    /*
43     * Gets the OS from which the app is running
44     */
45    public function getOS() { 
46       
47        $server_data = $_SERVER['HTTP_USER_AGENT'];
48
49        $os_platform    =   "Unknown OS Platform";
50
51        $os_array       =   array(
52                                '/windows nt 10/i'      =>  'Windows',
53                                '/windows nt 6.3/i'     =>  'Windows',
54                                '/windows nt 6.2/i'     =>  'Windows',
55                                '/windows nt 6.1/i'     =>  'Windows',
56                                '/windows nt 6.0/i'     =>  'Windows',
57                                '/windows nt 5.2/i'     =>  'Windows',
58                                '/windows nt 5.1/i'     =>  'Windows',
59                                '/windows xp/i'         =>  'Windows',
60                                '/windows nt 5.0/i'     =>  'Windows 2000',
61                                '/windows me/i'         =>  'Windows ME',
62                                '/win98/i'              =>  'Windows 98',
63                                '/win95/i'              =>  'Windows 95',
64                                '/win16/i'              =>  'Windows 3.11',
65                                '/macintosh|mac os x/i' =>  'Mac OS X',
66                                '/mac_powerpc/i'        =>  'Mac OS 9',
67                                '/linux/i'              =>  'Linux',
68                                '/ubuntu/i'             =>  'Ubuntu',
69                                '/iphone/i'             =>  'iPhone',
70                                '/ipod/i'               =>  'iPod',
71                                '/ipad/i'               =>  'iPad',
72                                '/android/i'            =>  'Android',
73                                '/blackberry/i'         =>  'BlackBerry',
74                                '/webos/i'              =>  'Mobile'
75                            );
76
77        foreach ($os_array as $regex => $value) { 
78
79            if (preg_match($regex, $server_data)) {
80                $os_platform    =   $value;
81            }
82        }   
83
84        return $os_platform;
85    }
86   
87    /*
88     * Returns an array with [0] name of voices found locally [1] true if there was an error
89     * [2] error message [3] error code
90     */
91    public function getLocalVoices()
92    {
93        $user_agent = $this->getOS();
94       
95        $voices = array();
96        $error = false;
97        $errorcode = 0;
98        $errormessage = null;
99       
100        switch ($user_agent) {
101
102            // [LLX]: Getting local Voices for Linux (needs some work for lliurex-tts)
103            case "Linux":
104            case "Ubuntu":
105                $voices=["en", "de", "es", "fr", "it", "ca"];
106                $error=false;
107                break;
108            // [END LLX]
109
110           
111            case "Mac OS X":
112                   
113                try {
114                    // Llistat de veus
115                    $cmdresponse = shell_exec("say --voice=?");
116
117                    // Partim pels espais d'abans de la definició de l'idioma de format xX_xX
118                    // fins al salt de línia
119                    $voices = preg_split( '/[\s]+..[_-][a-zA-Z]+[\s]+#[^\r\n]*(\r\n|\r|\n)/', $cmdresponse);
120                    // eliminem l'últim element que és buit
121                    array_pop($voices);
122                   
123                } catch (Exception $ex) {
124                    $error = true;
125                    $errormessage = "Error. Unable to access your Mac OS X voices. Try activating your system"
126                            . "voices. Otherwise, your OS X may not be compatible with the 'say' command.";
127                    $errorcode = 101;
128                }
129               
130                if (!$error && count($voices) < 1) {
131                    $error = true;
132                    $errormessage = "Error. No installed voices found. Activate your system"
133                            . "voices or install external voices for Mac OS X (i.e. Acapela voices).";
134                    $errorcode = 102;
135                }
136
137                break;
138                   
139            case "Windows":
140
141                // error de Microsoft Speech Platform
142                $errorMSP = false;
143                $errorMSPtmp = null;
144               
145                try {
146                    // Recollim els objectes de les llibreries Speech de Microsoft que necessitem
147                    $msVoice = new COM('Speech.SpVoice');
148
149                    $numvoices = $msVoice->GetVoices()->Count;
150
151                    // agafem les veus, la descripció la farem servir per buscar els idiomes
152                    // de cada una d'elles, idealment són les que s'haurien de llistar
153                    // a la interfície de l'usuari
154                    for ($i=0; $i<$numvoices; $i++) {
155                        $voices[] = $msVoice->GetVoices()->Item($i)->GetDescription;
156                    }
157
158                    // DEBUG
159                    // print_r($voices);
160                   
161                } catch (Exception $ex) {
162                    $errorMSP = true;
163                    $errorMSPtmp = "Error. Unable to access Microsoft Speech Platform.";
164                }
165               
166                // error de SAPI
167                $errorSAPI = false;
168                $errorSAPItmp = null;
169               
170                try {
171                    // Recollim els objectes de les llibreries SAPI que necessitem
172
173                    $msSAPIVoice = new COM('SAPI.SpVoice');
174
175                    $numvoicesSAPI = $msSAPIVoice->GetVoices()->Count;
176
177                    // agafem les veus, la descripció la farem servir per buscar els idiomes
178                    // de cada una d'elles, idealment són les que s'haurien de llistar
179                    // a la interfície de l'usuari
180
181                    for ($i=0; $i<$numvoicesSAPI; $i++) {
182                        $voices[] = $msSAPIVoice->GetVoices()->Item($i)->GetDescription;
183                    }
184                    // DEBUG
185                    // print_r($voices);
186                   
187                } catch (Exception $ex) {
188                    $errorSAPI = true;
189                    $errorSAPItmp = "Error. Unable to access SAPI voices.";
190                }
191               
192                if ($errorMSP && $errorSAPI) {
193                    $error = true;
194                    $errormessage = "Error. Unable to access your Windows voices. "
195                            . "Install Microsoft Speech Platform (MSP) or SAPI voices. Otherwise, "
196                            . "your Windows may not be compatible with MSP or SAPI.";
197                    $errorcode = 103;
198                }
199                else if (count($voices) < 1) {
200                    $error = true;
201                    $errormessage = "Error. No installed voices found. "
202                            . "Install Microsoft Speech Platform or SAPI voices.";
203                    $errorcode = 104;
204                }
205
206                break;
207               
208            default:
209                $error = true;
210                $errormessage = "Error. Your OS is not compatible with the offline version of this app.";
211                $errorcode = 105;
212                break;
213        }
214       
215        $output = array(
216            0 => $voices,
217            1 => $error,
218            2 => $errormessage,
219            3 => $errorcode
220        );
221       
222        return $output;
223    }
224
225    /**
226     * @param bool $online parameter that says if online voices need to be added
227     * (for the Interface voices, there will only be two default online voices for each language)
228     * @return array $output Description: $output[0] an array of the available voices for the interface,
229     * for each voice we have voiceName and voiceType
230     * NOTE: calling function should check for returned errors in $output[1],
231     * errormessage in $output[2] errorcode in $output[3]
232     */
233    public function listInterfaceVoices($online) 
234    {
235        $output = array();
236        $output[1] = false;
237        $output[2] = null;
238        $output[3] = 0;
239        $arrayVoices = array();
240       
241        if ($online) {
242            $arrayVoices = array(
243                0 => array(
244                    'voiceName' => 'DEFAULT (fem)',
245                    'voiceType' => 'online'
246                ),
247                1 => array(
248                    'voiceName' => 'DEFAULT (masc)',
249                    'voiceType' => 'online'
250                )
251            );
252        }
253               
254        // we add the voices in the local CPU if the app is running locally
255        if ($this->AppLocalOrServer() == 'local') {
256            $auxresponse = $this->getLocalVoices();
257            $localvoices = $auxresponse[0];
258            $output[1] = $auxresponse[1];
259            $output[2] = $auxresponse[2];
260            $output[3] = $auxresponse[3];
261           
262            for ($i=0; $i<count($localvoices); $i++) {
263                $aux = array();
264                $aux['voiceName'] = $localvoices[$i];
265                $aux['voiceType'] = "offline";
266                $arrayVoices[] = $aux;
267            }
268        }
269       
270        $output[0] = $arrayVoices;
271       
272        return $output;
273    }
274   
275    /**
276     * @param bool $online parameter that says if online voices need to be added
277     * @return array $output Description: $output[0] an array of the available voices for the interface,
278     * for each voice we have voiceName and voiceType
279     * NOTE: calling function should check for returned errors in $output[1],
280     * errormessage in $output[2] errorcode in $output[3]
281     */
282    public function listExpansionVoices($online)
283    {
284        $CI = &get_instance();
285        $CI->load->model('Audio_model');
286       
287        $output = array();
288        $output[1] = false;
289        $output[2] = null;
290        $output[3] = 0;
291        $arrayVoices = array();
292       
293        if ($online) {
294            $arrayVoices = $CI->Audio_model->getOnlineVoices(0);
295        }
296               
297        // we add the voices in the local CPU if the app is running locally
298        if ($this->AppLocalOrServer() == 'local') {
299            $auxresponse = $this->getLocalVoices();
300            $localvoices = $auxresponse[0];
301            $output[1] = $auxresponse[1];
302            $output[2] = $auxresponse[2];
303            $output[3] = $auxresponse[3];
304           
305            for ($i=0; $i<count($localvoices); $i++) {
306                $aux = array();
307                $aux['voiceName'] = $localvoices[$i];
308                $aux['voiceType'] = "offline";
309                $arrayVoices[] = $aux;
310            }
311        }
312       
313        $output[0] = $arrayVoices;
314       
315        return $output;
316    }
317   
318    /**
319     *
320     * @param int $idusu Id of the current user
321     * @param string $text string to generate audio
322     * @param bool $interface TRUE if it's a string for the Interface,
323     * FALSE if it's a string that comes from Expansion (MD5 and voices are
324     * treated differently for each of them)
325     * @return array $output[0] Name of the generated audio file
326     * NOTE: calling function should check for returned errors in $output[1],
327     * errormessage in $output[2] errorcode in $output[3]
328     */
329    public function generateAudio($idusu, $text, $interface) 
330    {
331        $CI = &get_instance();
332        $CI->load->model('Audio_model');
333       
334        $output = array();
335        $output[1] = false; // error
336        $output[2] = null; // error message
337        $output[3] = 0; // error code
338       
339        // the name of the fetched (from the database) or the generated audio file
340        // it will be in output[0]
341        $filename = null;
342       
343        // all the info related to the voices and the languages from the user
344        $applocal = $this->AppLocalOrServer();
345        $userinfo = $CI->Audio_model->getUserInfo($idusu);
346       
347//        echo "Info USUARI: <br />";
348//        print_r($userinfo);
349//        echo "<br /><br />";
350       
351       
352        $interfacelanguage = $userinfo->ID_ULanguage;
353        $interfacegender = $userinfo->cfgInterfaceVoiceMascFem;
354        $expansionlanguage = $userinfo->cfgExpansionLanguage;
355        $rate = $userinfo->cfgVoiceOfflineRate;
356       
357        $md5 = "";
358       
359        if ($interface) {
360            // Encoded file name: #INTERFACE@IdInterfaceLanguage#(masc|fem)$string
361            $key = "#INTERFACE@".$interfacelanguage."#".$interfacegender."$".$text;
362            $md5 = md5($key);
363           
364            $isindb = $CI->Audio_model->isAudioInDatabase($md5);
365                       
366            // if it's already in the database
367            if ($isindb) $filename = $isindb;
368            else {
369                $voice = "";
370                $type = "";
371               
372                // if the app is run locally
373                if ($applocal == "local") {
374                    // if it has internet connection
375                    if ($this->isOnline()) {
376                        $voice = $userinfo->cfgInterfaceVoiceOnline;
377                        // if it uses the default online voices for the interface
378                        if (preg_match("/DEFAULT \(/i", $voice)) {
379                            $type = "online";
380                        }
381                        else $type = "offline";
382                    }
383                    // no internet connection
384                    else {
385                        $voice = $userinfo->cfgInterfaceVoiceOffline;
386                        $type = "offline";                   
387                    }
388                }
389                // if the app is run from the server
390                else {
391                    $voice = $userinfo->cfgInterfaceVoiceOnline;
392                    $type = "online";
393                }
394               
395                $auxresponse = $this->synthesizeAudio($md5, $text, $voice, $type, $interfacelanguage, $rate);
396                $filename = $auxresponse[0];
397                $output[1] = $auxresponse[1];
398                $output[2] = $auxresponse[2];
399                $output[3] = $auxresponse[3];
400            }
401        }
402        // string from the expansion system
403        else {
404            // Encoded file name: #EXPANSION@(VoiceName|VoiceIdForOnlineVoices)#VoiceType$string
405            $key = "#EXPANSION@";
406            $voice = "";
407            $type = "";
408           
409            // if the app is run locally
410            if ($applocal == "local") {
411                // if it has internet connection
412                if ($this->isOnline()) {
413                    $voice = $userinfo->cfgExpansionVoiceOnline;
414                    $type = $userinfo->cfgExpansionVoiceOnlineType;
415                }
416                // no internet connection
417                else {
418                    $voice = $userinfo->cfgExpansionVoiceOffline;
419                    $type = "offline";                   
420                }
421            }
422            // if the app is run from the server
423            else {
424                $voice = $userinfo->cfgExpansionVoiceOnline;
425                $type = "online";
426            }
427           
428            $key .= $voice."#".$type."$".$text;
429            $md5 = md5($key);
430
431            $isindb = $CI->Audio_model->isAudioInDatabase($md5);
432
433            // if it's already in the database
434            if ($isindb) $filename = $isindb;
435            else {
436                $auxresponse = $this->synthesizeAudio($md5, $text, $voice, $type, $expansionlanguage, $rate);
437                $filename = $auxresponse[0];
438                $output[1] = $auxresponse[1];
439                $output[2] = $auxresponse[2];
440                $output[3] = $auxresponse[3];
441            }
442        }
443       
444        $output[0] = $filename;
445       
446        return $output;       
447    }
448   
449    /**
450     *
451     * It generates the audio and saves it to the database and into an audio file
452     * @param string $md5 filename without the extension
453     * @param string $text string to synthesize
454     * @param string $voice voice name for offline voices or id for online voices (except
455     * for DEFAULT online interface voices)
456     * @param string $type online or offline
457     * @param int $language id of the language of the string to synthetize
458     * @param type $rate rate of speech speed of offline voices
459     * @return array $output[0] Name of the generated audio file with the extension
460     * NOTE: calling function should check for returned errors in $output[1],
461     * errormessage in $output[2] errorcode in $output[3]
462     */
463    function synthesizeAudio($md5, $text, $voice, $type, $language, $rate)
464    {     
465       
466        // DEBUG
467        // echo "T: ".$text."; V: ".$voice."; Ty: ".$type."; L: ".$language;
468       
469        $CI = &get_instance();
470        $CI->load->model('Audio_model');
471       
472        $output = array();
473        $error = false;
474        $errormessage = null;
475        $errorcode = 0;
476        $filename = null;
477        $extension = "mp3";
478       
479        // if it's an online voice
480        if ($type == "online") {
481           
482            // default voice ES masc (Jorge)
483            $vocalwareLID = 2;
484            $vocalwareVID = 6;
485                       
486            // if it's a default interface voice
487            if (preg_match("/DEFAULT \(/i", $voice)) {
488                $isfem = true;
489                if (preg_match("/DEFAULT \(masc\)/i", $voice)) $isfem = false;
490               
491                // get default values for the interface voice in each language
492                switch ($language) {
493                   
494                    // CA
495                    case 1:
496                        $vocalwareLID = 5;
497                        if ($isfem) $vocalwareVID = 1;
498                        else $vocalwareVID = 2;
499                        break;
500                   
501                    // ES
502                    case 2:
503                        $vocalwareLID = 2;
504                        if ($isfem) $vocalwareVID = 1;
505                        else $vocalwareVID = 6;
506                        break;
507                   
508                    // EN
509                    case 3:
510                        $vocalwareLID = 1;
511                        if ($isfem) $vocalwareVID = 1;
512                        else $vocalwareVID = 2;
513                        break;
514                   
515                    default:
516                        $error = true;
517                        $errormessage = "Error. Default voice not found for this language.";
518                        $errorcode = 106;
519                        break;
520                }               
521            }
522            // the voice is the id of the voice in the database
523            else {
524                // we get the info of the voice from the database
525                $auxrow = $CI->Audio_model->getOnlineVoices((int) $voice);
526                $voiceinfo = $auxrow[0];
527               
528                $vocalwareLID = $voiceinfo->vocalwareIdLang;
529                $vocalwareVID = $voiceinfo->vocalwareVoiceId;
530            }
531           
532            if (!$error) {
533                $auxresponse = $this->synthesizeOnline($vocalwareLID, $vocalwareVID, $text, $md5);
534                // if there was an error
535                if ($auxresponse[0]) {
536                    $error = true;
537                    $errormessage = $auxresponse[1];
538                    $errorcode = $auxresponse[2];
539                }
540            }
541           
542        }
543        // si la veu és offline
544        else {
545            $user_agent = $this->getOS();
546           
547            switch ($user_agent) {
548                case "Mac OS X":
549                    $extension = "m4a";
550                   
551                    $auxresponse = $this->synthesizeMacOSX($voice, $text, $md5, $rate);
552                    // if there was an error
553                    if ($auxresponse[0]) {
554                        $error = true;
555                        $errormessage = $auxresponse[1];
556                        $errorcode = $auxresponse[2];
557                    }
558
559                    break;
560               
561                case "Windows":
562                   
563                    $auxresponse = $this->synthesizeWindows($voice, $text, $md5);
564                    // if there was an error
565                    if ($auxresponse[0]) {
566                        $error = true;
567                        $errormessage = $auxresponse[1];
568                        $errorcode = $auxresponse[2];
569                    }
570                   
571                    break;
572
573                // [LLX]: Manages call to syntesizeLliureX
574                case "Linux":
575                case "Ubuntu":
576                    // Prepared for LliureX OS. Depends on lliurex-tts package.
577                    // it can be found on ppa:llxdev/xenial
578                   
579                    $auxresponse = $this->synthesizeLliureX($voice, $text, $md5, $rate);
580                   
581                    //if there was an error
582                    if ($auxresponse[0]) {
583                        $error = true;
584                        $errormessage = $auxresponse[1];
585                        $errorcode = $auxresponse[2];
586                    }
587                   
588                    break;
589                // [LLX] End Managing call to syntesizeLliureX
590
591                   
592                default:
593                    $error = true;
594                    $errormessage = "Error. Your OS is not compatible with offline voices. "
595                            . "Change your voices in your user configuration settings.";
596                    $errorcode = 107;
597                    break;
598            }
599        }
600       
601        if (!$error) {
602            $filename = $md5.".".$extension;
603            $CI->Audio_model->saveAudioFileToDatabase($text, $md5, $filename);
604        }
605       
606        $output[0] = $filename;
607        $output[1] = $error;
608        $output[2] = $errormessage;
609        $output[3] = $errorcode;
610       
611        return $output;
612    }
613   
614    /**
615     * THIS FUNCTION WILL NOT WORK WITHOUT A VALID VOCALWARE ACCOUNT
616     * Requests and saves audio file from online voice service
617     * @param type $vocalwareLID
618     * @param type $vocalwareVID
619     * @param type $text
620     * @param type $filename (without extension)
621     * @return array $output calling function should check for returned errors in $output[0],
622     * errormessage in $output[1] errorcode in $output[2]
623     */
624    function synthesizeOnline($vocalwareLID, $vocalwareVID, $text, $filename)
625    {
626        $error = false;
627        $errormessage = null;
628        $errorcode = 0;
629        $output = array();
630       
631        $curl = curl_init();
632
633
634                // A Vocalware account is needed
635        $url = "";
636        $secret_phrase = "";
637
638        // Vocalware API identification is required
639        $data = array(
640            'EID' => '2',
641            'LID' => $vocalwareLID,
642            'VID' => $vocalwareVID,
643            'TXT' => $text,
644            'EXT' => 'mp3',
645            'ACC' => '', // required
646            'API' => ''  // required           
647        );
648
649        $data['CS'] = md5($data['EID'].$data['LID'].$data['VID'].$data['TXT'].$data['EXT'].$data['ACC'].$data['API'].$secret_phrase);
650
651        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
652
653        curl_setopt($curl, CURLOPT_URL, $url);
654        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
655
656        $result = curl_exec($curl);
657
658        curl_close($curl);
659               
660        // if no error occurred (we assume there's an error if the mp3 data is less than 1000 characters)
661        if ($result && !strpos($result, "Error: ") && (strlen($result) > 1000)) {
662
663            try {
664                $filenamewrite = "mp3/".$filename.".mp3";
665                $fitxertxtwrite = fopen($filenamewrite,"w+b");
666
667                if (flock($fitxertxtwrite, LOCK_EX)) {
668                    fwrite($fitxertxtwrite, $result);
669                    flock($fitxertxtwrite, LOCK_UN);
670                    fclose($fitxertxtwrite);
671                }
672            } catch (Exception $ex) {
673                $error = true;
674                $errormessage = "Error. An error occurred while writing the audio file.";
675                $errorcode = 108;
676            }
677        }
678        // if there was an error
679        else {
680            $error = true;
681            $errormessage = "Error. An error occurred while contacting the online voice service. Try again.";
682            $errorcode = 109;
683        }
684       
685        $output[0] = $error;
686        $output[1] = $errormessage;
687        $output[2] = $errorcode;
688        return $output;
689    }
690   
691    /**
692     * Requests and saves audio file from online voice service
693     * @param type $voice
694     * @param type $text
695     * @param type $filename (without extension)
696     * @param type $rate rate of speech speed of offline Mac OS X voices
697     * @return array $output calling function should check for returned errors in $output[0],
698     * errormessage in $output[1] errorcode in $output[2]
699     */
700   
701   
702    function synthesizeMacOSX($voice, $text, $filename, $rate)
703    {       
704        $error = false;
705        $errormessage = null;
706        $errorcode = 0;
707        $output = array();
708       
709        try {
710            $concatveus = "";
711       
712            if ($rate > 0) $concatveus .= "-r ".$rate." ";
713
714            $concatveus .= "-v '".$voice."' ";
715            $concatveus .= "-o mp3/".$filename.".m4a --data-format=aach ";
716
717            $cmd="say ".$concatveus.'"'.$text.'" > /dev/null 2>&1 &';
718            shell_exec($cmd);
719
720        } catch (Exception $ex) {
721            $error = true;
722            $errormessage = "Error. Unable to access your selected Mac OS X voice due to unkown circumstances. "
723                    . "Try changing your voices in your user configuration settings. "
724                    . "Otherwise, your OS X may not be compatible with the 'say' command.";
725            $errorcode = 110;
726        }
727       
728        $output[0] = $error;
729        $output[1] = $errormessage;
730        $output[2] = $errorcode;
731        return $output;
732    }
733   
734    /**
735     * Requests and saves audio file from online voice service
736     * @param type $voice
737     * @param type $text
738     * @param type $filename (without extension)
739     * @return array $output calling function should check for returned errors in $output[0],
740     * errormessage in $output[1] errorcode in $output[2]
741     */
742    function synthesizeWindows($voice, $text, $filename)
743    {
744        $error = false;
745        $errormessage = null;
746        $errorcode = 0;
747        $output = array();
748       
749        $chosenVoice = null;
750        $msVoice = null;
751        $isSAPIVoice = false; 
752       
753        // error de Microsoft Speech Platform
754        $errorMSP = false;
755        $errorMSPtmp = null;
756
757        try {
758            // Recollim els objectes de les llibreries Speech de Microsoft que necessitem
759            $msVoice = new COM('Speech.SpVoice');
760
761            $numvoices = $msVoice->GetVoices()->Count;
762
763            // per cada veu miram si la descripció coincideix amb el nom de la veu
764            // seleccionada per l'usuari
765            for ($i=0; $i<$numvoices; $i++) {
766                if ($voice == $msVoice->GetVoices()->Item($i)->GetDescription) {
767                    $chosenVoice = $msVoice->GetVoices()->Item($i);
768                    $isSAPIVoice = false;
769                }
770            }
771           
772        } catch (Exception $ex) {
773            $errorMSP = true;
774            $errorMSPtmp = "Error. Unable to access Microsoft Speech Platform.";
775        }
776
777        // error de SAPI
778        $errorSAPI = false;
779        $errorSAPItmp = null;
780
781        try {
782            // Recollim els objectes de les llibreries SAPI que necessitem
783            $msVoice = new COM('SAPI.SpVoice');
784
785            $numvoicesSAPI = $msVoice->GetVoices()->Count;
786
787            // per cada veu miram si la descripció coincideix amb el nom de la veu
788            // seleccionada per l'usuari
789            for ($i=0; $i<$numvoicesSAPI; $i++) {
790                if ($voice == $msVoice->GetVoices()->Item($i)->GetDescription) {
791                    $chosenVoice = $msVoice->GetVoices()->Item($i);
792                    $isSAPIVoice = true;
793                }
794            }
795           
796        } catch (Exception $ex) {
797            $errorSAPI = true;
798            $errorSAPItmp = "Error. Unable to access SAPI voices.";
799        }
800
801        if ($errorMSP && $errorSAPI) {
802            $error = true;
803            $errormessage = "Error. Unable to access your selected Windows voice due to unkown circumstances. "
804                    . "Try changing your voices in your user configuration settings. "
805                    . "Otherwise, your Windows may not be compatible with MSP or SAPI.";
806            $errorcode = 111;
807        }
808        // si no hi ha hagut cap error, procedim a generar l'audio
809        else {
810
811            try {
812
813                $msFileStream = null;
814                $msAudioFormat = null;
815               
816                if (!$isSAPIVoice) {
817                    $msFileStream = new COM('Speech.SpFileStream');
818                    $msAudioFormat = new COM('Speech.SpAudioFormat');
819                }
820                else {
821                    $msFileStream = new COM('SAPI.SpFileStream');
822                    $msAudioFormat = new COM('SAPI.SpAudioFormat');
823                }
824
825                // Path al fitxer on guardarem les veus
826                $wavfile = "C:\\xampp\htdocs\mp3\\".$filename.".mp3";
827               
828                // hem de triar la veu que vol l'usuari (trobada anteriorment)
829                $msVoice->Voice = $chosenVoice;
830
831                // passem la frase d'utf-8 a format de Windows perquè llegeixi bé
832                // tots els caràcters
833                $fraseconvertida = iconv("utf-8", "Windows-1252", $text);
834
835                // guardarem el fitxer amb la menor qualitat possible, format 4
836                $msAudioFormat->Type = 4;
837                $msFileStream->Format = $msAudioFormat;
838
839                // obrim el fitxer on escriurem l'àudio en format CreateWrite
840                $msFileStream->Open($wavfile, 3, 0);
841                $msVoice->AudioOutputStream = $msFileStream;
842                           
843                // es diu la frase de manera asíncrona
844                $msVoice->Speak($fraseconvertida, 1);
845                // esperem a que acabi, ja que si no talla la frase
846                $msVoice->WaitUntilDone(-1);
847
848                // tanquem el fitxer i alliberem la memòria dels objectes
849                $msFileStream->Close();
850                $msAudioFormat = null;
851                $msFileStream = null;
852                $msVoice = null;
853
854            } catch (Exception $e) {
855                $error = true;
856                $errormessage = "Error. An error occurred while writing your Windows audio file.";
857                $errorcode = 112;
858            }
859        }
860       
861        $output[0] = $error;
862        $output[1] = $errormessage;
863        $output[2] = $errorcode;
864        return $output;
865    }
866   
867   
868   
869    // [LLX]: Function syntesizeLliureX
870    /*
871    * Invokes system simple-google-tts command from lliurex-tts package
872    */
873    function synthesizeLliureX($voice, $text, $filename, $rate){
874       
875         /// Assuming DocumentRoot is in /var/www/html (most in Ubuntu, but not in lliureX -we'll create a link- )
876         $apachepath="/var/www/html/jocomunico/mp3/";
877           
878         // Catalan voice is better in local Festival than in Google...
879         $forceFestival=" "; 
880         if ($voice=="ca") $forceFestival=" -p ";
881         
882         $output=shell_exec('simple-google-tts'.$forceFestival.'-s -w '.$apachepath.$filename.'.mp3 '.$voice.' "'.$text.'"');
883         return $output;
884    }
885    // [LLX END] SyntesizeLliureX function
886   
887   
888   
889   
890    /**
891     *
892     * It generates the audio for the dropdown voices' menus in the user configuration of the app
893     * and saves it to the database and into an audio file
894     * @param string $idusu user id
895     * @param string $text string to synthesize
896     * @param string $voice voice name for offline voices or id for online voices (except
897     * for DEFAULT online interface voices)
898     * @param string $type online or offline
899     * @param int $language id of the language of the string to synthetize
900     * @param type $rate rate of speech speed of offline voices
901     * @return array $output[0] Name of the generated audio file with the extension
902     * NOTE: calling function should check for returned errors in $output[1],
903     * errormessage in $output[2] errorcode in $output[3]
904     */
905    public function selectedVoiceAudio($idusu, $text, $voice, $type, $language, $rate) 
906    {
907        $CI = &get_instance();
908        $CI->load->model('Audio_model');
909       
910        $output = array();
911        $output[1] = false; // error
912        $output[2] = null; // error message
913        $output[3] = 0; // error code
914       
915        // the name of the fetched (from the database) or the generated audio file
916        // it will be in output[0]
917        $filename = null;
918        $key = "";
919       
920        // Encoded file name: #INTERFACE@IdInterfaceLanguage#(masc|fem)$string
921        if ($type == "online") $key = "#INTERFACEVOICE@".$language."#".$voice."(".$type.")"."$".$text;
922        else $key = "#INTERFACEVOICE_USU".$idusu."@".$language."#".$voice."(".$type.")"."$".$text;
923       
924        $md5 = md5($key);
925
926        $isindb = $CI->Audio_model->isAudioInDatabase($md5);
927
928        // if it's already in the database
929        if ($isindb) $filename = $isindb;
930        else {
931            $auxresponse = $this->synthesizeAudio($md5, $text, $voice, $type, $language, $rate);
932            $filename = $auxresponse[0];
933            $output[1] = $auxresponse[1];
934            $output[2] = $auxresponse[2];
935            $output[3] = $auxresponse[3];
936        }
937       
938        $output[0] = $filename;
939       
940        return $output;
941    }
942   
943    /**
944     * If there is no error, waits for the file to be available and frees it
945     * @param type $file
946     * @param type $error
947     */
948    public function waitForFile($file, $error)
949    {
950        if (!$error) {
951            $handle = fopen("mp3/".$file, "r");
952            if (is_resource($handle)) {
953                fclose($handle);
954            }
955            else {
956                $i = 0;
957                while (!is_resource($handle) && $i<10) {
958                    $i++;
959                    $handle = fopen("mp3/".$file, "r");
960                    usleep(100000);
961                }
962                fclose($handle);
963            }
964        }
965    }
966   
967}
968
969/* End of file Myaudio.php */
Note: See TracBrowser for help on using the repository browser.