flite 0.0.3.1-x64-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9f47422e32fece8cf60122e9ab327296c0ee34cd
4
+ data.tar.gz: 09e881454d870e0a7630bdf52c255cbefa09d80b
5
+ SHA512:
6
+ metadata.gz: 0cb5431e7ba2905d3f0156e6f05e65aeea134870a5fcd345999b1c378e2eeae450f44f8435071ae630c235eedc881c49da531f231431a2b5124a700206254fdf
7
+ data.tar.gz: f747c758f98ff8015183ab0190735b94e69b3b34929583ab7d51dd95e8948d0adced81cd7a4477ff2caf46f0612d700ff4091272ec592bfce34c533cc5be2fca
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in flite.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,28 @@
1
+ Copyright (C) 2015 Kubo Takehiro <kubo@jiubao.org>
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions are met:
5
+
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+
9
+ 2. Redistributions in binary form must reproduce the above
10
+ copyright notice, this list of conditions and the following
11
+ disclaimer in the documentation and/or other materials provided
12
+ with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR
15
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE
18
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ The views and conclusions contained in the software and documentation
27
+ are those of the authors and should not be interpreted as representing
28
+ official policies, either expressed or implied, of the authors.
data/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # ruby-flite
2
+
3
+ Ruby-flite is a small speech synthesis library for ruby using [CMU Flite](http://cmuflite.org).
4
+
5
+ CMU Flite (festival-lite) is a small, fast run-time synthesis engine developed
6
+ at CMU and primarily designed for small embedded machines and/or large
7
+ servers. Flite is designed as an alternative synthesis engine to [Festival](http://festvox.org/festival) for
8
+ voices built using the [FestVox](http://festvox.org/) suite of voice building tools.
9
+
10
+ ## Supported versions
11
+
12
+ * ruby 2.0.0 and uppper
13
+ * CMU Flite 1.4 and 2.0.
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'flite'
21
+ ```
22
+
23
+ Install [CMU Flite](http://cmuflite.org):
24
+
25
+ ```shell
26
+ # On ubuntu
27
+ sudo apt-get install flite1-dev
28
+
29
+ # On redhat
30
+ yum install flite flite-devel
31
+
32
+ # On Windows
33
+ # you have no need to install CMU Flite if you use the flite binary gem.
34
+ # CMU Flite is statically linked.
35
+ ```
36
+
37
+ And then execute:
38
+
39
+ $ bundle
40
+
41
+ Or install it yourself as:
42
+
43
+ $ gem install flite
44
+
45
+ Ruby-flite tries to link with **all voices and languages**.
46
+ If you want to reduce dependent libraries, execute the followings
47
+ instead of above commands.
48
+
49
+ $ bundle config --local build.flite --with-voices=kal --with-langs=eng
50
+ $ bundle
51
+
52
+ Or install it yourself as:
53
+
54
+ $ gem install flite -- --with-voices=kal --with-langs=eng
55
+
56
+ ## Simple Usage
57
+
58
+ ```ruby
59
+ require 'flite'
60
+
61
+ # output to the speeker.
62
+ "Hello World!".to_speech
63
+
64
+ # save as a WAVE file
65
+ "Hello World!".to_speech("hello_world.wave")
66
+
67
+ # write to an I/O object if it responds to 'write'.
68
+ File.open("hello_world.wave", "wb") do |f|
69
+ "Hello World!".to_speech(f)
70
+ end
71
+ ```
72
+ ## Advanced Usage
73
+
74
+ ```ruby
75
+ require 'flite'
76
+
77
+ # array of builtin voice names.
78
+ Flite.list_builtin_voices
79
+
80
+ # create a voice. 'slt' is a voice name.
81
+ voice = Flite::Voice.new("slt")
82
+
83
+ # output to the speeker.
84
+ voice.speech("Hello World!")
85
+
86
+ # save as a WAVE file
87
+ voice.speech("Hello World!", "hello_world.wave")
88
+
89
+ # write to an I/O object if it responds to 'write'.
90
+ File.open("hello_world.wave", "wb") do |f|
91
+ voice.speech("Hello World!", f)
92
+ end
93
+
94
+ # Change the voice used for String#to_speech
95
+ Flite.default_voice = 'rms'
96
+ ```
97
+
98
+ ## Sample Application
99
+
100
+ * [saytime.rb](https://github.com/kubo/ruby-flite/blob/master/bin/saytime.rb)
101
+
102
+ ## Restrictions
103
+
104
+ * `String#to_speech(io_object)` and `Flite::Voice#speech(text, io_object)`
105
+ are not thread-safe. You need to create `Flite::Voice` objects for
106
+ each threads and use `Flite::Voice#speech`.
107
+
108
+ * `String#to_speech("play")` and `Flite::Voice#speech(text, "play")`
109
+ don't save wave data to the specified file `play`. They output speech
110
+ data to the speaker instead.
111
+
112
+ * `String#to_speech("stream")`, `String#to_speech("none")`,
113
+ `Flite::Voice#speech(text, "stream")` and `Flite::Voice#speech(text, "none")`
114
+ don't save wave data to the specified file `stream` or `none`. They
115
+ synthesize speech and discard the result.
116
+
117
+ * When an error occurs in CMU Flite, the error message is outputted to
118
+ the standard error.
119
+
120
+ ## License
121
+
122
+ * Ruby-flite itself is licensed under 2-clause BSD-style license.
123
+ * CMU Flite is licensed under BSD-like license.
124
+ See http://www.festvox.org/flite/download.html
125
+
126
+ ## Contributing
127
+
128
+ 1. Fork it ( https://github.com/kubo/ruby-flite/fork )
129
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
130
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
131
+ 4. Push to the branch (`git push origin my-new-feature`)
132
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rake/extensiontask"
4
+
5
+ Rake::ExtensionTask.new("flite") do |ext|
6
+ ext.lib_dir = "lib/flite"
7
+ end
data/bin/saytime.rb ADDED
@@ -0,0 +1,71 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ require 'flite'
4
+ require 'optparse'
5
+
6
+ available_voices = Flite.list_builtin_voices
7
+ available_voices.delete('awb_time') # exclude awb_time
8
+
9
+ $cached_voices = {}
10
+
11
+ def saytime(voice_name)
12
+ sec, min, hour = Time.now.to_a
13
+
14
+ case hour
15
+ when 0
16
+ hour = 12
17
+ when 13 .. 23
18
+ hour -= 12
19
+ end
20
+
21
+ case min
22
+ when 0
23
+ min = " o'clock"
24
+ else
25
+ min = ':%02d' % min
26
+ end
27
+
28
+ case sec
29
+ when 0
30
+ sec = "exactly"
31
+ when 1
32
+ sec = "and #{sec} second"
33
+ else
34
+ sec = "and #{sec} seconds"
35
+ end
36
+
37
+ text = "The time is #{hour}#{min} #{sec}."
38
+
39
+ puts "text: #{text}"
40
+ puts "voice: #{voice_name}"
41
+
42
+ voice = ($cached_voices[voice_name] ||= Flite::Voice.new(voice_name))
43
+ voice.speech(text)
44
+ end
45
+
46
+ voices = []
47
+ loop_count = 1
48
+ interval = nil
49
+
50
+ OptionParser.new do |opts|
51
+ opts.on('--voices NAMES', "voice names (default: #{available_voices.join(',')})") {|v| voices += v.split(',')}
52
+ opts.on('--loop [COUNT]', Integer, 'loop count (default: 1)') {|v| loop_count = v}
53
+ opts.on('--interval INTERVAL', Integer, 'sleep interval between loops (default: 0)') {|v| interval = v}
54
+ end.parse!
55
+
56
+ if voices.size == 0
57
+ voices = available_voices
58
+ end
59
+
60
+ if loop_count && loop_count <= 0
61
+ puts "invalid loop_count #{loop_count}. It must be positive number."
62
+ exit(1)
63
+ end
64
+
65
+ srand()
66
+ saytime(voices.sample)
67
+ cnt = 1
68
+ while loop_count.nil? || (cnt += 1) <= loop_count
69
+ sleep(interval) if interval
70
+ saytime(voices.sample)
71
+ end
@@ -0,0 +1,90 @@
1
+ require "mkmf"
2
+
3
+ dir_config('flite')
4
+
5
+ unless have_library('flite', 'flite_init')
6
+ saved_libs = $libs
7
+ puts "checkign for audio libraries depended by flite ..."
8
+ unless [['asound'], ['winmm'], ['pulse-simple', 'pulse']].any? do |libs|
9
+ $libs = saved_libs
10
+ libs.all? { |lib| have_library(lib) } && have_library('flite', 'flite_init')
11
+ end
12
+ raise "Failed to find flite libraries."
13
+ end
14
+ end
15
+
16
+ have_func('flite_voice_load')
17
+ have_func('flite_add_lang')
18
+ have_struct_member('cst_audio_streaming_info', 'utt', 'flite/cst_audio.h')
19
+
20
+ langs = with_config('langs', 'eng,indic,grapheme')
21
+
22
+ langs.split(',').each do |lang|
23
+ lib = if lang == 'eng'
24
+ ['flite_usenglish', 'usenglish_init',
25
+ 'flite_cmulex', 'cmu_lex_init']
26
+ else
27
+ ["flite_cmu_#{lang}_lang", "cmu_#{lang}_lang_init",
28
+ "flite_cmu_#{lang}_lex", "cmu_#{lang}_lex_init"]
29
+ end
30
+ if have_library(lib[0], lib[1]) and have_library(lib[2], lib[3])
31
+ $defs << "-DHAVE_LANG_#{lang.upcase}"
32
+ end
33
+ end
34
+
35
+ builtin_voices = {
36
+ 'kal' => ['cmu_us_kal', 'cmu_us_kal_diphone'],
37
+ 'awb_time' => ['cmu_time_awb', 'cmu_time_awb_ldom'],
38
+ 'kal16' => ['cmu_us_kal16', 'cmu_us_kal16_diphone'],
39
+ 'awb' => ['cmu_us_awb', 'cmu_us_awb_cg'],
40
+ 'rms' => ['cmu_us_rms', 'cmu_us_rms_cg'],
41
+ 'slt' => ['cmu_us_slt', 'cmu_us_slt_cg'],
42
+ }
43
+
44
+ voices = with_config('voices', 'kal,awb_time,kal16,awb,rms,slt')
45
+
46
+ voices = voices.split(',').inject([]) do |memo, name|
47
+ v = builtin_voices[name]
48
+ if v
49
+ puts "checking for voice #{name}... "
50
+ if have_library("flite_#{v[0]}", "register_#{v[0]}")
51
+ memo << [name, *v]
52
+ end
53
+ else
54
+ puts "warning: #{name} is not a builtin voice."
55
+ end
56
+ memo
57
+ end
58
+
59
+ File.open('rbflite_builtin_voice_list.c', 'w') do |f|
60
+ f.write <<EOS
61
+ /*
62
+ * This file is automatically generated by extconf.rb.
63
+ * Don't edit this.
64
+ */
65
+ #include "rbflite.h"
66
+
67
+ EOS
68
+ voices.each do |v|
69
+ f.puts "cst_voice *register_#{v[1]}(const char *voxdir);"
70
+ end
71
+ f.puts ""
72
+ voices.each do |v|
73
+ f.puts "extern cst_voice *#{v[2]};"
74
+ end
75
+ f.write <<EOS
76
+
77
+ const rbflite_builtin_voice_t rbflite_builtin_voice_list[] = {
78
+ EOS
79
+ voices.each do |v|
80
+ f.puts(%Q[ {"#{v[0]}", register_#{v[1]}, &#{v[2]}},])
81
+ end
82
+ f.write <<EOS
83
+ {NULL, NULL, NULL},
84
+ };
85
+ EOS
86
+ end
87
+
88
+ RUBY_VERSION =~ /(\d+).(\d+)/
89
+ $defs << "-DInit_flite=Init_flite_#{$1}#{$2}0"
90
+ create_makefile("flite_#{$1}#{$2}0")
@@ -0,0 +1,377 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*-
2
+ *
3
+ * ruby-flite - a small speech synthesis module
4
+ * https://github.com/kubo/ruby-flite
5
+ *
6
+ * Copyright (C) 2015 Kubo Takehiro <kubo@jiubao.org>
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions are met:
10
+ *
11
+ * 1. Redistributions of source code must retain the above copyright
12
+ * notice, this list of conditions and the following disclaimer.
13
+ *
14
+ * 2. Redistributions in binary form must reproduce the above
15
+ * copyright notice, this list of conditions and the following
16
+ * disclaimer in the documentation and/or other materials provided
17
+ * with the distribution.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR
20
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE
23
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ *
31
+ * The views and conclusions contained in the software and documentation
32
+ * are those of the authors and should not be interpreted as representing
33
+ * official policies, either expressed or implied, of the authors.
34
+ */
35
+ #include <ruby.h>
36
+ #include <ruby/thread.h>
37
+ #include <ruby/encoding.h>
38
+ #include "rbflite.h"
39
+ #include <flite/flite_version.h>
40
+
41
+ #ifdef WORDS_BIGENDIAN
42
+ #define TO_LE4(num) SWAPINT(num)
43
+ #defien TO_LE2(num) SWAPSHORT(num)
44
+ #else
45
+ #define TO_LE4(num) (num)
46
+ #define TO_LE2(num) (num)
47
+ #endif
48
+
49
+ #ifdef HAVE_CST_AUDIO_STREAMING_INFO_UTT
50
+ /* flite 2.0.0 */
51
+ typedef struct cst_audio_streaming_info_struct *asc_last_arg_t;
52
+ #define ASC_LAST_ARG_TO_USERDATA(last_arg) (last_arg)->userdata
53
+ #else
54
+ /* flite 1.4.0 */
55
+ typedef void *asc_last_arg_t;
56
+ #define ASC_LAST_ARG_TO_USERDATA(last_arg) (last_arg)
57
+ #endif
58
+
59
+ void usenglish_init(cst_voice *v);
60
+ cst_lexicon *cmulex_init(void);
61
+
62
+ void cmu_indic_lang_init(cst_voice *v);
63
+ cst_lexicon *cmu_indic_lex_init(void);
64
+
65
+ void cmu_grapheme_lang_init(cst_voice *v);
66
+ cst_lexicon *cmu_grapheme_lex_init(void);
67
+
68
+ typedef struct {
69
+ cst_voice *voice;
70
+ } rbflite_voice_t;
71
+
72
+ typedef struct {
73
+ cst_voice *voice;
74
+ const char *text;
75
+ const char *outtype;
76
+ VALUE io;
77
+ int state;
78
+ } voice_speech_arg_t;
79
+
80
+ typedef struct {
81
+ VALUE io;
82
+ void *data;
83
+ long size;
84
+ } io_write_arg_t;
85
+
86
+ static VALUE rb_mFlite;
87
+ static VALUE rb_cVoice;
88
+ static ID id_write;
89
+
90
+ /*
91
+ * call graph:
92
+ *
93
+ * rbflite_audio_write_cb()
94
+ * --> rbfile_io_write_protect() via rb_thread_call_with_gvl()
95
+ * --> rbfile_io_write() via rb_protect()
96
+ */
97
+ static int rbflite_audio_write_cb(const cst_wave *w, int start, int size, int last, asc_last_arg_t last_arg);
98
+ static void *rbfile_io_write_protect(void *data);
99
+ static VALUE rbfile_io_write(VALUE data);
100
+
101
+ static VALUE
102
+ flite_s_list_builtin_voices(VALUE klass)
103
+ {
104
+ VALUE ary = rb_ary_new();
105
+ const rbflite_builtin_voice_t *builtin = rbflite_builtin_voice_list;
106
+
107
+ while (builtin->name != NULL) {
108
+ rb_ary_push(ary, rb_usascii_str_new_cstr(builtin->name));
109
+ builtin++;
110
+ }
111
+
112
+ return ary;
113
+ }
114
+
115
+ static void
116
+ rbfile_voice_free(rbflite_voice_t *voice)
117
+ {
118
+ if (voice->voice) {
119
+ delete_voice(voice->voice);
120
+ voice->voice = NULL;
121
+ }
122
+ }
123
+
124
+ static VALUE
125
+ rbflite_voice_s_allocate(VALUE klass)
126
+ {
127
+ rbflite_voice_t *voice;
128
+
129
+ return Data_Make_Struct(klass, rbflite_voice_t, NULL, rbfile_voice_free, voice);
130
+ }
131
+
132
+ #ifdef HAVE_FLITE_VOICE_LOAD
133
+ static void *
134
+ rbflite_voice_load(void *data)
135
+ {
136
+ return flite_voice_load((const char *)data);
137
+ }
138
+ #endif
139
+
140
+ static VALUE
141
+ rbflite_voice_initialize(int argc, VALUE *argv, VALUE self)
142
+ {
143
+ VALUE name;
144
+ const rbflite_builtin_voice_t *builtin = rbflite_builtin_voice_list;
145
+ rbflite_voice_t *voice = DATA_PTR(self);
146
+
147
+ rb_scan_args(argc, argv, "01", &name);
148
+ if (!NIL_P(name)) {
149
+ char *voice_name = StringValueCStr(name);
150
+ while (builtin->name != NULL) {
151
+ if (strcmp(voice_name, builtin->name) == 0) {
152
+ break;
153
+ }
154
+ builtin++;
155
+ }
156
+ if (builtin->name == NULL) {
157
+ #ifdef HAVE_FLITE_VOICE_LOAD
158
+ if (strchr(voice_name, '/') != NULL || strchr(voice_name, '.') != NULL) {
159
+ voice->voice = rb_thread_call_without_gvl(rbflite_voice_load, voice_name, NULL, NULL);
160
+ RB_GC_GUARD(name);
161
+ if (voice->voice != NULL) {
162
+ return self;
163
+ }
164
+ }
165
+ #endif
166
+ rb_raise(rb_eArgError, "Unkonw voice %s", voice_name);
167
+ }
168
+ }
169
+ *builtin->cached = NULL; /* disable voice caching in libflite.so. */
170
+ voice->voice = builtin->register_(NULL);
171
+ return self;
172
+ }
173
+
174
+ static void *
175
+ voice_speech_without_gvl(void *data)
176
+ {
177
+ voice_speech_arg_t *arg = (voice_speech_arg_t *)data;
178
+ flite_text_to_speech(arg->text, arg->voice, arg->outtype);
179
+ return NULL;
180
+ }
181
+
182
+ static int
183
+ rbflite_audio_write_cb(const cst_wave *w, int start, int size, int last, asc_last_arg_t last_arg)
184
+ {
185
+ voice_speech_arg_t *ud = (voice_speech_arg_t *)ASC_LAST_ARG_TO_USERDATA(last_arg);
186
+ io_write_arg_t arg;
187
+
188
+ arg.io = ud->io;
189
+
190
+ if (start == 0) {
191
+ /* write WAVE file header. */
192
+ struct {
193
+ const char riff_id[4];
194
+ int file_size;
195
+ const char wave_id[4];
196
+ const char fmt_id[4];
197
+ const int fmt_size;
198
+ const short format;
199
+ short channels;
200
+ int samplerate;
201
+ int bytepersec;
202
+ short blockalign;
203
+ short bitswidth;
204
+ const char data[4];
205
+ int data_size;
206
+ } header = {
207
+ {'R', 'I', 'F', 'F'},
208
+ 0,
209
+ {'W', 'A', 'V', 'E'},
210
+ {'f', 'm', 't', ' '},
211
+ TO_LE4(16),
212
+ TO_LE2(0x0001),
213
+ 0, 0, 0, 0, 0,
214
+ {'d', 'a', 't', 'a'},
215
+ 0,
216
+ };
217
+ int num_samples = cst_wave_num_samples(w);
218
+ int num_channels = cst_wave_num_channels(w);
219
+ int sample_rate = cst_wave_sample_rate(w);
220
+ int data_size = num_channels * num_samples * sizeof(short);
221
+
222
+ header.file_size = TO_LE4(sizeof(header) + data_size - 8);
223
+ header.channels = TO_LE2(num_channels);
224
+ header.samplerate = TO_LE2(sample_rate);
225
+ header.bytepersec = TO_LE4(sample_rate * num_channels * sizeof(short));
226
+ header.blockalign = TO_LE2(num_channels * sizeof(short));
227
+ header.bitswidth = TO_LE2(sizeof(short) * 8);
228
+ header.data_size = TO_LE4(data_size);
229
+
230
+ arg.data = &header;
231
+ arg.size = sizeof(header);
232
+ ud->state = (int)(VALUE)rb_thread_call_with_gvl(rbfile_io_write_protect, &arg);
233
+ if (ud->state != 0) {
234
+ return CST_AUDIO_STREAM_STOP;
235
+ }
236
+ }
237
+
238
+ arg.data = &w->samples[start];
239
+ arg.size = size * sizeof(short);
240
+ ud->state = (int)(VALUE)rb_thread_call_with_gvl(rbfile_io_write_protect, &arg);
241
+ if (ud->state != 0) {
242
+ return CST_AUDIO_STREAM_STOP;
243
+ }
244
+
245
+ return CST_AUDIO_STREAM_CONT;
246
+ }
247
+
248
+ static void *
249
+ rbfile_io_write_protect(void *data)
250
+ {
251
+ int state = 0;
252
+ rb_protect(rbfile_io_write, (VALUE)data, &state);
253
+ return (void*)(VALUE)state;
254
+ }
255
+
256
+ static VALUE
257
+ rbfile_io_write(VALUE data)
258
+ {
259
+ const io_write_arg_t *arg = (const io_write_arg_t *)data;
260
+ rb_funcall(arg->io, id_write, 1, rb_str_new(arg->data, arg->size));
261
+ return Qnil;
262
+ }
263
+
264
+ static VALUE
265
+ rbflite_voice_speech(int argc, VALUE *argv, VALUE self)
266
+ {
267
+ rbflite_voice_t *voice = DATA_PTR(self);
268
+ VALUE text;
269
+ VALUE out;
270
+ cst_audio_streaming_info *asi = NULL;
271
+ voice_speech_arg_t arg;
272
+
273
+ if (voice->voice == NULL) {
274
+ rb_raise(rb_eRuntimeError, "not initialized");
275
+ }
276
+
277
+ rb_scan_args(argc, argv, "11", &text, &out);
278
+ arg.voice = voice->voice;
279
+ arg.text = StringValueCStr(text);
280
+ arg.io = Qnil;
281
+ arg.state = 0;
282
+
283
+ if (NIL_P(out)) {
284
+ /* play audio */
285
+ arg.outtype = "play";
286
+ } else if (rb_respond_to(out, id_write)) {
287
+ /* write to an object */
288
+ asi = new_audio_streaming_info();
289
+ if (asi == NULL) {
290
+ rb_raise(rb_eNoMemError, "failed to allocate audio_streaming_info");
291
+ }
292
+ asi->asc = rbflite_audio_write_cb;
293
+ asi->userdata = (void*)&arg;
294
+ feat_set(voice->voice->features, "streaming_info", audio_streaming_info_val(asi));
295
+ arg.outtype = "stream";
296
+ arg.io = out;
297
+ } else {
298
+ /* write to a file */
299
+ out = rb_str_export_to_enc(out, rb_filesystem_encoding());
300
+ arg.outtype = StringValueCStr(out);
301
+ }
302
+
303
+ rb_thread_call_without_gvl(voice_speech_without_gvl, &arg, NULL, NULL);
304
+ RB_GC_GUARD(text);
305
+ RB_GC_GUARD(out);
306
+
307
+ if (asi != NULL) {
308
+ flite_feat_remove(voice->voice->features, "streaming_info");
309
+ if (arg.state != 0) {
310
+ rb_jump_tag(arg.state);
311
+ }
312
+ }
313
+ return self;
314
+ }
315
+
316
+ static VALUE
317
+ rbflite_voice_name(VALUE self)
318
+ {
319
+ rbflite_voice_t *voice = DATA_PTR(self);
320
+
321
+ if (voice->voice == NULL) {
322
+ rb_raise(rb_eRuntimeError, "not initialized");
323
+ }
324
+ return rb_usascii_str_new_cstr(voice->voice->name);
325
+ }
326
+
327
+ static VALUE
328
+ rbflite_voice_pathname(VALUE self)
329
+ {
330
+ rbflite_voice_t *voice = DATA_PTR(self);
331
+ const char *pathname;
332
+
333
+ if (voice->voice == NULL) {
334
+ rb_raise(rb_eRuntimeError, "not initialized");
335
+ }
336
+ pathname = get_param_string(voice->voice->features, "pathname", "");
337
+ if (pathname[0] == '\0') {
338
+ return Qnil;
339
+ }
340
+ return rb_usascii_str_new_cstr(pathname);
341
+ }
342
+
343
+ void
344
+ Init_flite(void)
345
+ {
346
+ VALUE cmu_flite_version;
347
+
348
+ id_write = rb_intern("write");
349
+
350
+ rb_mFlite = rb_define_module("Flite");
351
+
352
+ cmu_flite_version = rb_usascii_str_new_cstr(FLITE_PROJECT_VERSION);
353
+ OBJ_FREEZE(cmu_flite_version);
354
+ rb_define_const(rb_mFlite, "CMU_FLITE_VERSION", cmu_flite_version);
355
+
356
+ #ifdef HAVE_FLITE_ADD_LANG
357
+ #ifdef HAVE_LANG_ENG
358
+ flite_add_lang("eng", usenglish_init, cmulex_init);
359
+ flite_add_lang("usenglish", usenglish_init, cmulex_init);
360
+ #endif
361
+ #ifdef HAVE_LANG_INDIC
362
+ flite_add_lang("cmu_indic_lang", cmu_indic_lang_init, cmu_indic_lex_init);
363
+ #endif
364
+ #ifdef HAVE_LANG_GRAPHEME
365
+ flite_add_lang("cmu_grapheme_lang",cmu_grapheme_lang_init,cmu_grapheme_lex_init);
366
+ #endif
367
+ #endif
368
+
369
+ rb_define_singleton_method(rb_mFlite, "list_builtin_voices", flite_s_list_builtin_voices, 0);
370
+ rb_cVoice = rb_define_class_under(rb_mFlite, "Voice", rb_cObject);
371
+ rb_define_alloc_func(rb_cVoice, rbflite_voice_s_allocate);
372
+
373
+ rb_define_method(rb_cVoice, "initialize", rbflite_voice_initialize, -1);
374
+ rb_define_method(rb_cVoice, "speech", rbflite_voice_speech, -1);
375
+ rb_define_method(rb_cVoice, "name", rbflite_voice_name, 0);
376
+ rb_define_method(rb_cVoice, "pathname", rbflite_voice_pathname, 0);
377
+ }
@@ -0,0 +1,48 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*-
2
+ *
3
+ * ruby-flite - a small speech synthesis library
4
+ * https://github.com/kubo/ruby-flite
5
+ *
6
+ * Copyright (C) 2015 Kubo Takehiro <kubo@jiubao.org>
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions are met:
10
+ *
11
+ * 1. Redistributions of source code must retain the above copyright
12
+ * notice, this list of conditions and the following disclaimer.
13
+ *
14
+ * 2. Redistributions in binary form must reproduce the above
15
+ * copyright notice, this list of conditions and the following
16
+ * disclaimer in the documentation and/or other materials provided
17
+ * with the distribution.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR
20
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE
23
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ *
31
+ * The views and conclusions contained in the software and documentation
32
+ * are those of the authors and should not be interpreted as representing
33
+ * official policies, either expressed or implied, of the authors.
34
+ */
35
+ #ifndef RBFLITE_H
36
+ #define RBFLITE_H 1
37
+
38
+ #include "flite/flite.h"
39
+
40
+ typedef struct {
41
+ const char *name;
42
+ cst_voice *(*register_)(const char *voxdir);
43
+ cst_voice **cached;
44
+ } rbflite_builtin_voice_t;
45
+
46
+ extern const rbflite_builtin_voice_t rbflite_builtin_voice_list[];
47
+
48
+ #endif /* RBFLITE_H */
data/flite.gemspec ADDED
@@ -0,0 +1,48 @@
1
+ # -*- ruby -*-
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'flite/version'
6
+
7
+ if ARGV.include?("--") and ARGV[(ARGV.index("--") + 1)] == 'current'
8
+ gem_platform = 'current'
9
+ else
10
+ gem_platform = Gem::Platform::RUBY
11
+ end
12
+
13
+ Gem::Specification.new do |spec|
14
+ spec.name = "flite"
15
+ spec.version = Flite::VERSION
16
+ spec.authors = ["Kubo Takehiro"]
17
+ spec.email = ["kubo@jiubao.org"]
18
+ spec.extensions = ["ext/flite/extconf.rb"] if gem_platform == Gem::Platform::RUBY
19
+ spec.summary = %q{a small speech synthesis library}
20
+ spec.description = <<EOS
21
+ Ruby-flite is a small speech synthesis library using CMU flite[http://cmuflite.org].
22
+
23
+ CMU Flite (festival-lite) is a small, fast run-time synthesis engine
24
+ developed at CMU and primarily designed for small embedded machines
25
+ and/or large servers. Flite is designed as an alternative synthesis
26
+ engine to Festival for voices built using the FestVox suite of voice
27
+ building tools.
28
+ EOS
29
+ spec.homepage = "https://github.com/kubo/ruby-flite/"
30
+ spec.license = "2-clause BSD-style license"
31
+ spec.platform = gem_platform
32
+
33
+ files = `git ls-files -z`.split("\x0")
34
+ files.delete('build.bat')
35
+ files.delete('.gitignore')
36
+ if gem_platform == 'current'
37
+ files << 'lib/flite_200.so' << 'lib/flite_210.so'
38
+ end
39
+ spec.files = files
40
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
41
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
42
+ spec.require_paths = ["lib"]
43
+ spec.required_ruby_version = '>= 2.0.0'
44
+
45
+ spec.add_development_dependency "bundler", "~> 1.7"
46
+ spec.add_development_dependency "rake", "~> 10.0"
47
+ spec.add_development_dependency "rake-compiler", '~> 0'
48
+ end
data/lib/flite.rb ADDED
@@ -0,0 +1,58 @@
1
+ #
2
+ # ruby-flite - a small speech synthesis library
3
+ # https://github.com/kubo/ruby-flite
4
+ #
5
+ # Copyright (C) 2015 Kubo Takehiro <kubo@jiubao.org>
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions are met:
9
+ #
10
+ # 1. Redistributions of source code must retain the above copyright
11
+ # notice, this list of conditions and the following disclaimer.
12
+ #
13
+ # 2. Redistributions in binary form must reproduce the above
14
+ # copyright notice, this list of conditions and the following
15
+ # disclaimer in the documentation and/or other materials provided
16
+ # with the distribution.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR
19
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE
22
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28
+ # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ #
30
+ # The views and conclusions contained in the software and documentation
31
+ # are those of the authors and should not be interpreted as representing
32
+ # official policies, either expressed or implied, of the authors.
33
+
34
+ require "flite/version"
35
+ RUBY_VERSION =~ /(\d+).(\d+)/
36
+ require "flite_#{$1}#{$2}0"
37
+
38
+ module Flite
39
+ @@default_voice = Flite::Voice.new
40
+
41
+ def self.default_voice
42
+ @@default_voice
43
+ end
44
+
45
+ def self.default_voice=(name)
46
+ if name.is_a? Flite::Voice
47
+ @@default_voice = name
48
+ else
49
+ @@default_voice = Flite::Voice.new(name)
50
+ end
51
+ end
52
+ end
53
+
54
+ class String
55
+ def to_speech(out = nil)
56
+ Flite.default_voice.speech(self, out)
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module Flite
2
+ VERSION = "0.0.3.1"
3
+ end
data/lib/flite_200.so ADDED
Binary file
data/lib/flite_210.so ADDED
Binary file
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3.1
5
+ platform: x64-mingw32
6
+ authors:
7
+ - Kubo Takehiro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake-compiler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: |
56
+ Ruby-flite is a small speech synthesis library using CMU flite[http://cmuflite.org].
57
+
58
+ CMU Flite (festival-lite) is a small, fast run-time synthesis engine
59
+ developed at CMU and primarily designed for small embedded machines
60
+ and/or large servers. Flite is designed as an alternative synthesis
61
+ engine to Festival for voices built using the FestVox suite of voice
62
+ building tools.
63
+ email:
64
+ - kubo@jiubao.org
65
+ executables:
66
+ - saytime.rb
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - bin/saytime.rb
75
+ - ext/flite/extconf.rb
76
+ - ext/flite/rbflite.c
77
+ - ext/flite/rbflite.h
78
+ - flite.gemspec
79
+ - lib/flite.rb
80
+ - lib/flite/version.rb
81
+ - lib/flite_200.so
82
+ - lib/flite_210.so
83
+ homepage: https://github.com/kubo/ruby-flite/
84
+ licenses:
85
+ - 2-clause BSD-style license
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '>='
94
+ - !ruby/object:Gem::Version
95
+ version: 2.0.0
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.0.0
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: a small speech synthesis library
107
+ test_files: []