В комплекте к festival идёт такой скрипт text2wave с большим количеством скобок:
(load (path-append libdir "init.scm"))
;;; Process command line arguments
(define (text2wave_help)
(format t "%s\n"
"text2wave [options] textfile
Convert a textfile to a waveform
Options
-mode <string> Explicit tts mode.
-o ofile File to save waveform (default is stdout).
-otype <string> Output waveform type: ulaw, snd, aiff, riff, nist etc.
(default is riff)
-F <int> Output frequency.
-scale <float> Volume factor
-eval <string> File or lisp s-expression to be evaluated before
synthesis.
")
(quit))
;;; No gc messages
(gc-status nil)
;;; Default argument values
(defvar outfile "-")
(defvar output_type 'riff)
(defvar frequency nil) ;; default is no frequency modification
(defvar text_files '("-"))
(defvar mode nil)
(defvar volume "1.0")
(defvar wavefiles nil)
;;; Get options
(define (get_options)
(let ((files nil)
(o argv))
(if (or (member_string "-h" argv)
(member_string "-help" argv)
(member_string "--help" argv)
(member_string "-?" argv))
(text2wave_help))
(while o
(begin
(cond
((string-equal "-o" (car o))
(if (not (cdr o))
(text2wave_error "no output file specified"))
(set! outfile (car (cdr o)))
(set! o (cdr o)))
((string-equal "-otype" (car o))
(if (not (cdr o))
(text2wave_error "no output filetype specified"))
(set! output_type (car (cdr o)))
(set! o (cdr o)))
((or (string-equal "-f" (car o)) ;; for compatibility and memory loss
(string-equal "-F" (car o)))
(if (not (cdr o))
(text2wave_error "no frequency specified"))
(set! frequency (car (cdr o)))
(set! o (cdr o)))
((string-equal "-scale" (car o))
(if (not (cdr o))
(text2wave_error "no scale specified"))
(set! volume (car (cdr o)))
(set! o (cdr o)))
((string-equal "-mode" (car o))
(if (not (cdr o))
(text2wave_error "no mode specified"))
(set! mode (car (cdr o)))
(set! o (cdr o)))
((string-equal "-eval" (car o))
(if (not (cdr o))
(text2wave_error "no file specified to load"))
(if (string-matches (car (cdr o)) "^(.*")
(eval (read-from-string (car (cdr o))))
(load (car (cdr o))))
(set! o (cdr o)))
(t
(set! files (cons (car o) files))))
(set! o (cdr o))))
(if files
(set! text_files (reverse files)))))
(define (text2wave_error message)
(format stderr "%s: %s\n" "text2wave" message)
(text2wave_help))
(define (save_record_wave utt)
"Saves the waveform and records its so it can be joined into a
a single waveform at the end."
(let ((fn (make_tmp_filename)))
(utt.save.wave utt fn)
(set! wavefiles (cons fn wavefiles))
utt))
(define (combine_waves)
"Join all the waves together into the desired output file
and delete the intermediate ones."
(let ((wholeutt (utt.synth (Utterance Text ""))))
(mapcar
(lambda (d)
(utt.import.wave wholeutt d t)
(delete-file d))
(reverse wavefiles))
(if frequency
(utt.wave.resample wholeutt (parse-number frequency)))
(if (not (equal? volume "1.0"))
(begin
(utt.wave.rescale wholeutt (parse-number volume))))
(utt.save.wave wholeutt outfile output_type)
))
;;;
;;; Redefine what happens to utterances during text to speech
;;;
(set! tts_hooks (list utt.synth save_record_wave))
(define (main)
(get_options)
;; do the synthesis
(mapcar
(lambda (f)
(if mode
(tts_file f mode)
(tts_file f (tts_find_text_mode f auto-text-mode-alist))))
text_files)
;; Now put the waveforms together at again
(combine_waves)
)
;;; Do the work
(main)
С лиспом дела никогда не имел.
- Понятно, что функция main главная, ка в программе на С.
- Понятно, что вначале онв вызывает get_options, которая или выводит подсказку через text2wave_help, или анализирует параметры командной строки.
- Потом многократно, для каждоо файла из списка text_files ,вызвыается tts_file с параметром mode или с заданным умолчальным списком параметров.
- Затем они ввобираются воедино функцией combine_waves
- Задаётся локальная переменная wholeutt, в неё вводится пустой текст.
- Затем для каждого файла в списке wavefiles, записанном задом наперёд, вызывается функция utt.import.wave, которая записывает этот файл в конец wholeutt.
- Дальше идёт функция изменения частоты, но я её не задействовал, поэтому она не должна была вызыватьмя, т.к. (defvar frequency nil).
- Далее идёт изменение громгости, ео я его ноже не менял, поэтому (defvar volume «1.0»).
- Потом utt.save.wave сохраняет записанный во wholeutt звук в вэйвфайл.
Теперь вопрос: на создание промежуточных файлов уходят секунды, от силы —минуты. На их сборку воедино — на 1-2 порядка больше, и чем их больше, тем больше времени требуется на каждый байт текста. При ээтом объём свопфайла может скакать туда-сюда на полгигабайта. Как ускорить процесс сборки файлов с отдельными строками в целый большой файл?