voicevox.rb 0.1.0
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 +7 -0
- data/.rubocop.yml +21 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +19 -0
- data/LICENSE +21 -0
- data/README.md +46 -0
- data/Rakefile +7 -0
- data/Steepfile +29 -0
- data/examples/cli.rb +48 -0
- data/examples/outputs/.gitkeep +0 -0
- data/examples/repl_core.rb +48 -0
- data/examples/repl_wrapper.rb +33 -0
- data/lib/voicevox/core.rb +448 -0
- data/lib/voicevox/error.rb +79 -0
- data/lib/voicevox/version.rb +6 -0
- data/lib/voicevox/wrapper/audio_query.rb +213 -0
- data/lib/voicevox/wrapper/info.rb +113 -0
- data/lib/voicevox/wrapper/manager.rb +137 -0
- data/lib/voicevox/wrapper/utils.rb +45 -0
- data/lib/voicevox.rb +15 -0
- data/rbs_collection.lock.yaml +100 -0
- data/rbs_collection.yaml +15 -0
- data/sig/ffi.rbs +16 -0
- data/sig/voicevox/core.rbs +126 -0
- data/sig/voicevox/error.rbs +53 -0
- data/sig/voicevox/wrapper/info.rbs +26 -0
- data/sig/voicevox/wrapper/manager.rbs +31 -0
- data/sig/voicevox/wrapper/utils.rbs +9 -0
- data/sig/voicevox.rbs +3 -0
- data/voicevox.gemspec +42 -0
- metadata +88 -0
@@ -0,0 +1,213 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
class Voicevox
|
5
|
+
#
|
6
|
+
# テキストからAudioQueryを生成します。
|
7
|
+
#
|
8
|
+
# @param [String] text 生成するAudioQueryのテキスト。
|
9
|
+
# @param [Voicevox::CharacterInfo, Voicevox::StyleInfo, Integer] speaker 話者、または話者のID。
|
10
|
+
# @param [Boolean] kana textをAquesTalkライクな記法として解釈するかどうか。デフォルトはfalse。
|
11
|
+
#
|
12
|
+
# @return [Voicevox::AudioQuery] 生成されたAudioQuery。
|
13
|
+
#
|
14
|
+
# @see Voicevox#synthesis
|
15
|
+
#
|
16
|
+
def audio_query(text, speaker, kana: false)
|
17
|
+
options = Voicevox::Core.voicevox_make_default_audio_query_options
|
18
|
+
options[:kana] = kana
|
19
|
+
speaker_id = speaker.is_a?(Integer) ? speaker : speaker.id
|
20
|
+
load_model speaker_id
|
21
|
+
return_ptr = FFI::MemoryPointer.new(:pointer)
|
22
|
+
Voicevox.process_result Voicevox::Core.voicevox_audio_query(
|
23
|
+
text,
|
24
|
+
speaker_id,
|
25
|
+
options,
|
26
|
+
return_ptr
|
27
|
+
)
|
28
|
+
return_str_ptr = return_ptr.read_pointer
|
29
|
+
json = return_str_ptr.read_string
|
30
|
+
Voicevox::Core.voicevox_audio_query_json_free return_str_ptr
|
31
|
+
|
32
|
+
AudioQuery.new JSON.parse(json, symbolize_names: true)
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# AudioQueryから音声を生成します。
|
37
|
+
#
|
38
|
+
# @param [AudioQuery] query AudioQuery。
|
39
|
+
# @param [Voicevox::CharacterInfo, Voicevox::StyleInfo, Integer] speaker 話者、または話者のID。
|
40
|
+
# @param [Boolran] enable_interrogative_upspeak 疑問文の調整を有効にするかどうか。デフォルトはtrue。
|
41
|
+
#
|
42
|
+
# @return [String] 生成された音声のwavデータ。
|
43
|
+
#
|
44
|
+
def synthesis(query, speaker, enable_interrogative_upspeak: true)
|
45
|
+
size_ptr = FFI::MemoryPointer.new(:int)
|
46
|
+
return_ptr = FFI::MemoryPointer.new(:pointer)
|
47
|
+
id = speaker.is_a?(Integer) ? speaker : speaker.id
|
48
|
+
load_model id
|
49
|
+
options = Voicevox::Core::VoicevoxSynthesisOptions.new
|
50
|
+
options[:enable_interrogative_upspeak] = enable_interrogative_upspeak
|
51
|
+
Voicevox.process_result(
|
52
|
+
Voicevox::Core.voicevox_synthesis(
|
53
|
+
query.to_json,
|
54
|
+
id,
|
55
|
+
options,
|
56
|
+
size_ptr,
|
57
|
+
return_ptr
|
58
|
+
)
|
59
|
+
)
|
60
|
+
data_ptr = return_ptr.read_pointer
|
61
|
+
size_ptr.free
|
62
|
+
data = data_ptr.read_string(size_ptr.read_int)
|
63
|
+
Voicevox::Core.voicevox_wav_free(data_ptr)
|
64
|
+
data
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# 音声合成用のクエリ。
|
69
|
+
#
|
70
|
+
class AudioQuery
|
71
|
+
# @return [Array<AccentPhrase>] アクセント句のリスト。
|
72
|
+
attr_accessor :accent_phrases
|
73
|
+
# @return [Float] 全体の話速。
|
74
|
+
attr_accessor :speed_scale
|
75
|
+
# @return [Float] 全体の音高。
|
76
|
+
attr_accessor :pitch_scale
|
77
|
+
# @return [Float] 全体の抑揚。
|
78
|
+
attr_accessor :intonation_scale
|
79
|
+
# @return [Float] 全体の音量。
|
80
|
+
attr_accessor :volume_scale
|
81
|
+
# @return [Float] 音声の前の無音時間。
|
82
|
+
attr_accessor :pre_phoneme_length
|
83
|
+
# @return [Float] 音声の後の無音時間。
|
84
|
+
attr_accessor :post_phoneme_length
|
85
|
+
# @return [Integer] 音声データの出力サンプリングレート。
|
86
|
+
attr_accessor :output_sampling_rate
|
87
|
+
# @return [Boolean] 音声データをステレオ出力するか否か。
|
88
|
+
attr_accessor :output_stereo
|
89
|
+
# @return [String] AquesTalkライクな読み仮名。
|
90
|
+
attr_reader :kana
|
91
|
+
|
92
|
+
def initialize(query)
|
93
|
+
@accent_phrases = query[:accent_phrases].map { |ap| AccentPhrase.new ap }
|
94
|
+
@speed_scale = query[:speed_scale]
|
95
|
+
@pitch_scale = query[:pitch_scale]
|
96
|
+
@intonation_scale = query[:intonation_scale]
|
97
|
+
@volume_scale = query[:volume_scale]
|
98
|
+
@pre_phoneme_length = query[:pre_phoneme_length]
|
99
|
+
@post_phoneme_length = query[:post_phoneme_length]
|
100
|
+
@output_sampling_rate = query[:output_sampling_rate]
|
101
|
+
@output_stereo = query[:output_stereo]
|
102
|
+
@kana = query[:kana]
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# AudioQueryをHashにします。
|
107
|
+
#
|
108
|
+
# @return [Hash]
|
109
|
+
#
|
110
|
+
def to_hash
|
111
|
+
{
|
112
|
+
accent_phrases: @accent_phrases.map(&:to_hash),
|
113
|
+
pitch_scale: @pitch_scale,
|
114
|
+
speed_scale: @speed_scale,
|
115
|
+
intonation_scale: @intonation_scale,
|
116
|
+
volume_scale: @volume_scale,
|
117
|
+
pre_phoneme_length: @pre_phoneme_length,
|
118
|
+
post_phoneme_length: @post_phoneme_length,
|
119
|
+
output_sampling_rate: @output_sampling_rate,
|
120
|
+
output_stereo: @output_stereo,
|
121
|
+
kana: @kana
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
#
|
126
|
+
# AudioQueryをjsonにします。
|
127
|
+
#
|
128
|
+
# @return [String]
|
129
|
+
#
|
130
|
+
def to_json(...)
|
131
|
+
to_hash.to_json(...)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# アクセント句ごとの情報。
|
137
|
+
#
|
138
|
+
class AccentPhrase
|
139
|
+
# @return [Array<Mora>] モーラのリスト。
|
140
|
+
attr_reader :moras
|
141
|
+
# @return [Integer] アクセント箇所。
|
142
|
+
attr_reader :accent
|
143
|
+
# @return [Mora, nil] 後ろに無音を付けるかどうか。
|
144
|
+
attr_reader :pause_mora
|
145
|
+
# @return [Boolean] 疑問系かどうか。
|
146
|
+
attr_reader :is_interrogative
|
147
|
+
alias interrogative? is_interrogative
|
148
|
+
|
149
|
+
def initialize(query)
|
150
|
+
@moras = query[:moras].map { |ap| Mora.new ap }
|
151
|
+
@accent = query[:accent]
|
152
|
+
@pause_mora = query[:pause_mora] && Mora.new(query[:pause_mora])
|
153
|
+
@is_interrogative = query[:is_interrogative]
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# AccentPhraseをHashにします。
|
158
|
+
#
|
159
|
+
# @return [Hash]
|
160
|
+
#
|
161
|
+
def to_hash
|
162
|
+
{
|
163
|
+
moras: @moras.map(&:to_hash),
|
164
|
+
accent: @accent,
|
165
|
+
pause_mora: @pause_mora&.to_hash,
|
166
|
+
is_interrogative: @is_interrogative
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
# モーラ(子音+母音)ごとの情報。
|
172
|
+
#
|
173
|
+
class Mora
|
174
|
+
# @return [String] 文字。
|
175
|
+
attr_reader :text
|
176
|
+
# @return [String] 子音の音素。
|
177
|
+
attr_reader :consonant
|
178
|
+
# @return [Float] 子音の音長。
|
179
|
+
attr_reader :consonant_length
|
180
|
+
# @return [String] 母音の音素。
|
181
|
+
attr_reader :vowel
|
182
|
+
# @return [Float] 母音の音長。
|
183
|
+
attr_reader :vowel_length
|
184
|
+
# @return [Float] 音高。
|
185
|
+
attr_reader :pitch
|
186
|
+
|
187
|
+
def initialize(query)
|
188
|
+
@text = query[:text]
|
189
|
+
@consonant = query[:consonant]
|
190
|
+
@consonant_length = query[:consonant_length]
|
191
|
+
@vowel = query[:vowel]
|
192
|
+
@vowel_length = query[:vowel_length]
|
193
|
+
@pitch = query[:pitch]
|
194
|
+
end
|
195
|
+
|
196
|
+
#
|
197
|
+
# MoraをHashにします。
|
198
|
+
#
|
199
|
+
# @return [Hash]
|
200
|
+
#
|
201
|
+
def to_hash
|
202
|
+
{
|
203
|
+
text: @text,
|
204
|
+
consonant: @consonant,
|
205
|
+
consonant_length: @consonant_length,
|
206
|
+
vowel: @vowel,
|
207
|
+
vowel_length: @vowel_length,
|
208
|
+
pitch: @pitch
|
209
|
+
}
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
class Voicevox
|
6
|
+
# サポートされているデバイスを表すStruct。
|
7
|
+
SupportedDevices = Struct.new(:cpu, :cuda, :dml, keyword_init: true)
|
8
|
+
|
9
|
+
# キャラクターの情報を表すStruct。
|
10
|
+
CharacterInfo =
|
11
|
+
Struct.new(:name, :styles, :speaker_uuid, :version, keyword_init: true) do
|
12
|
+
#
|
13
|
+
# キャラクターの最初のスタイルのIDを返します。
|
14
|
+
# @note ほとんどの場合はノーマルになります。
|
15
|
+
#
|
16
|
+
# @return [Integer] スタイルのID。
|
17
|
+
#
|
18
|
+
def id
|
19
|
+
styles[0].id
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# キャラクターのスタイルが全てロードされているかを返します。
|
24
|
+
#
|
25
|
+
# @return [Boolean] 全てロードされている場合はtrue、そうでない場合はfalse。
|
26
|
+
#
|
27
|
+
def loaded?
|
28
|
+
styles.map(&:loaded?).all?
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# キャラクターのスタイルを全てロードします。
|
33
|
+
#
|
34
|
+
# @return [void]
|
35
|
+
#
|
36
|
+
def load
|
37
|
+
Voicevox.initialize_required
|
38
|
+
styles.map(&:load)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
StyleInfo =
|
42
|
+
Struct.new(:name, :id, keyword_init: true) do
|
43
|
+
#
|
44
|
+
# スタイルがロードされているかを返します。
|
45
|
+
#
|
46
|
+
# @return [Boolean] ロードされている場合はtrue、そうでない場合はfalse。
|
47
|
+
#
|
48
|
+
def loaded?
|
49
|
+
Voicevox::Core.is_model_loaded(id)
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# スタイルをロードします。
|
54
|
+
#
|
55
|
+
# @return [void]
|
56
|
+
#
|
57
|
+
def load
|
58
|
+
Voicevox.initialize_required
|
59
|
+
Voicevox.process_result Voicevox::Core.voicevox_load_model(id)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class << self
|
64
|
+
#
|
65
|
+
# サポートしているデバイスを取得します。
|
66
|
+
#
|
67
|
+
# @return [Voicevox::SupportedDevices] サポートしているデバイス。
|
68
|
+
#
|
69
|
+
def supported_devices
|
70
|
+
SupportedDevices.new(
|
71
|
+
**JSON.parse(Voicevox::Core.voicevox_get_supported_devices_json)
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# キャラクターの一覧を取得します。
|
77
|
+
#
|
78
|
+
# @return [Array<CharacterInfo>] キャラクターの一覧。
|
79
|
+
#
|
80
|
+
def characters
|
81
|
+
JSON
|
82
|
+
.parse(Voicevox::Core.voicevox_get_metas_json)
|
83
|
+
.map do |meta|
|
84
|
+
CharacterInfo.new(
|
85
|
+
**{
|
86
|
+
**meta,
|
87
|
+
"styles" => meta["styles"].map { |style| StyleInfo.new(**style) }
|
88
|
+
}
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# GPUをサポートしているかを返します。
|
95
|
+
#
|
96
|
+
# @note CUDA、またはDirectMLが使える場合にtrueを返します。
|
97
|
+
#
|
98
|
+
# @return [Boolean] GPUをサポートしているかどうか。
|
99
|
+
#
|
100
|
+
def gpu_supported?
|
101
|
+
Voicevox.supported_devices.cuda || Voicevox.supported_devices.dml
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# コアのバージョンを取得します。
|
106
|
+
#
|
107
|
+
# @return [String] コアのバージョン。
|
108
|
+
#
|
109
|
+
def core_version
|
110
|
+
Voicevox::Core.voicevox_get_version
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "etc"
|
4
|
+
require "objspace"
|
5
|
+
|
6
|
+
class Voicevox
|
7
|
+
@initialized = false
|
8
|
+
# @return [:cpu, :gpu] ハードウェアアクセラレーションモード。
|
9
|
+
attr_reader :acceleration_mode
|
10
|
+
# @return [Integer] スレッド数。
|
11
|
+
attr_reader :cpu_num_threads
|
12
|
+
# @return [Boolean] 起動時に全てのモデルを読み込むかどうか。
|
13
|
+
attr_reader :load_all_models
|
14
|
+
|
15
|
+
#
|
16
|
+
# GPUモードで動作しているかどうか。
|
17
|
+
#
|
18
|
+
# @return [Boolean] GPUモードで動作している場合はtrue、そうでない場合はfalse。
|
19
|
+
#
|
20
|
+
def gpu?
|
21
|
+
@acceleration_mode == :gpu
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# CPUモードで動作しているかどうか。
|
26
|
+
#
|
27
|
+
# @return [Boolean] CPUモードで動作している場合はtrue、そうでない場合はfalse。
|
28
|
+
#
|
29
|
+
def cpu?
|
30
|
+
@acceleration_mode == :cpu
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Voicevoxのコアを初期化します。
|
35
|
+
#
|
36
|
+
# @param [String] openjtalk_dict_path OpenJTalkの辞書へのパス。
|
37
|
+
# @param [:cpu, :gpu, :auto] acceleration_mode ハードウェアアクセラレーションモード。:autoを指定するとコア側で自動的に決定されます。
|
38
|
+
# @param [Integer] cpu_num_threads スレッド数。省略する、または0を渡すとコア側で自動的に決定されます。
|
39
|
+
# @param [Boolean] load_all_models 全てのモデルを読み込むかどうか。省略するとfalseになります。
|
40
|
+
#
|
41
|
+
def initialize(
|
42
|
+
openjtalk_dict_path,
|
43
|
+
acceleration_mode: :auto,
|
44
|
+
cpu_num_threads: nil,
|
45
|
+
load_all_models: false
|
46
|
+
)
|
47
|
+
acceleration_mode_enum =
|
48
|
+
{
|
49
|
+
auto: :voicevox_acceleration_mode_auto,
|
50
|
+
gpu: :voicevox_acceleration_mode_gpu,
|
51
|
+
cpu: :voicevox_acceleration_mode_cpu
|
52
|
+
}.fetch(acceleration_mode) do
|
53
|
+
raise ArgumentError, "無効なacceleration_mode: #{acceleration_mode}"
|
54
|
+
end
|
55
|
+
@cpu_num_threads = cpu_num_threads || 0
|
56
|
+
@load_all_models = load_all_models
|
57
|
+
@openjtalk_dict_path = openjtalk_dict_path
|
58
|
+
options = Voicevox::Core.voicevox_make_default_initialize_options
|
59
|
+
options[:acceleration_mode] = acceleration_mode_enum
|
60
|
+
options[:cpu_num_threads] = @cpu_num_threads
|
61
|
+
options[:load_all_models] = @load_all_models
|
62
|
+
options[:openjtalk_dict_path] = FFI::MemoryPointer.from_string(
|
63
|
+
openjtalk_dict_path
|
64
|
+
)
|
65
|
+
|
66
|
+
Voicevox.process_result Voicevox::Core.voicevox_initialize(options)
|
67
|
+
@acceleration_mode = Voicevox::Core.voicevox_is_gpu_mode ? :gpu : :cpu
|
68
|
+
at_exit { Voicevox::Core.voicevox_finalize } unless self.class.initialized
|
69
|
+
self.class.initialized = true
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Voicevoxのコアをファイナライズします。
|
74
|
+
#
|
75
|
+
def finalize
|
76
|
+
Voicevox::Core.voicevox_finalize
|
77
|
+
self.class.initialized = false
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# 話者のモデルを読み込みます。
|
82
|
+
#
|
83
|
+
# @param [Voicevox::CharacterInfo, Voicevox::StyleInfo, Integer] speaker 話者、または話者のID。
|
84
|
+
#
|
85
|
+
def load_model(speaker)
|
86
|
+
id = speaker.is_a?(Integer) ? speaker : speaker.id
|
87
|
+
|
88
|
+
Voicevox.process_result Voicevox::Core.voicevox_load_model(id)
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# モデルが読み込まれているかどうかを返します。
|
93
|
+
#
|
94
|
+
# @param [Voicevox::CharacterInfo, Voicevox::StyleInfo, Integer] speaker 話者、または話者のID。
|
95
|
+
#
|
96
|
+
# @return [Boolean] 読み込まれているかどうか。
|
97
|
+
#
|
98
|
+
def model_loaded?(speaker)
|
99
|
+
id = speaker.is_a?(Integer) ? speaker : speaker.id
|
100
|
+
|
101
|
+
Voicevox::Core.voicevox_is_model_loaded(id)
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# voicevox_ttsを使って音声を生成します。
|
106
|
+
#
|
107
|
+
# @param [String] text 生成する音声のテキスト。
|
108
|
+
# @param [Voicevox::CharacterInfo, Voicevox::StyleInfo, Integer] speaker 話者、または話者のID。
|
109
|
+
# @param [Boolean] kana textをAquesTalkライクな記法として解釈するかどうか。デフォルトはfalse。
|
110
|
+
# @param [Boolran] enable_interrogative_upspeak 疑問文の調整を有効にするかどうか。デフォルトはtrue。
|
111
|
+
#
|
112
|
+
# @return [String] 生成された音声のwavデータ。
|
113
|
+
#
|
114
|
+
def tts(text, speaker, kana: false, enable_interrogative_upspeak: true)
|
115
|
+
size_ptr = FFI::MemoryPointer.new(:int)
|
116
|
+
return_ptr = FFI::MemoryPointer.new(:pointer)
|
117
|
+
id = speaker.is_a?(Integer) ? speaker : speaker.id
|
118
|
+
load_model id
|
119
|
+
options = Voicevox::Core.voicevox_make_default_tts_options
|
120
|
+
options[:kana] = kana
|
121
|
+
options[:enable_interrogative_upspeak] = enable_interrogative_upspeak
|
122
|
+
Voicevox.process_result(
|
123
|
+
Voicevox::Core.voicevox_tts(text, id, options, size_ptr, return_ptr)
|
124
|
+
)
|
125
|
+
data_ptr = return_ptr.read_pointer
|
126
|
+
data = data_ptr.read_string(size_ptr.read_int)
|
127
|
+
size_ptr.free
|
128
|
+
Voicevox::Core.voicevox_wav_free(data_ptr)
|
129
|
+
data
|
130
|
+
end
|
131
|
+
|
132
|
+
class << self
|
133
|
+
attr_accessor :initialized
|
134
|
+
|
135
|
+
alias initialized? initialized
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "etc"
|
4
|
+
|
5
|
+
class Voicevox
|
6
|
+
class << self
|
7
|
+
#
|
8
|
+
# Voicevoxが初期化されていなかったらエラーを出す。
|
9
|
+
#
|
10
|
+
def initialize_required
|
11
|
+
raise Voicevox::Error, "Voicevoxが初期化されていません" unless Voicevox.initialized?
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# voicevox_result_codeに対応するエラーをraiseします。
|
16
|
+
#
|
17
|
+
# @param [Symbol] result voicevox_result_code。
|
18
|
+
#
|
19
|
+
def process_result(result)
|
20
|
+
return if result == :voicevox_result_succeed
|
21
|
+
raise "#{result}はSymbolではありません" unless result.is_a?(Symbol)
|
22
|
+
|
23
|
+
raise Voicevox::CoreError.from_code(result)
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# 製品版Voicevoxのパスを返します。
|
28
|
+
#
|
29
|
+
# @return [String] Voicevoxへの絶対パス。
|
30
|
+
# @return [nil] Voicevoxが見付からなかった場合。zip版やLinux版ではnilを返します。
|
31
|
+
#
|
32
|
+
def voicevox_path
|
33
|
+
paths =
|
34
|
+
if Gem.win_platform?
|
35
|
+
[File.join(ENV.fetch("LOCALAPPDATA", ""), "Programs", "VOICEVOX")]
|
36
|
+
else
|
37
|
+
[
|
38
|
+
"/Applications/VOICEVOX",
|
39
|
+
"/Users/#{Etc.getlogin}/Library/Application Support/VOICEVOX"
|
40
|
+
]
|
41
|
+
end
|
42
|
+
paths.find { |path| Dir.exist?(path) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/voicevox.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "voicevox/core"
|
4
|
+
require_relative "voicevox/version"
|
5
|
+
require_relative "voicevox/error"
|
6
|
+
require_relative "voicevox/wrapper/utils"
|
7
|
+
require_relative "voicevox/wrapper/info"
|
8
|
+
require_relative "voicevox/wrapper/manager"
|
9
|
+
require_relative "voicevox/wrapper/audio_query"
|
10
|
+
|
11
|
+
#
|
12
|
+
# voicevox_coreのラッパー。
|
13
|
+
#
|
14
|
+
class Voicevox # rubocop:disable Lint/EmptyClass
|
15
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
---
|
2
|
+
sources:
|
3
|
+
- name: ruby/gem_rbs_collection
|
4
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
5
|
+
revision: main
|
6
|
+
repo_dir: gems
|
7
|
+
path: ".gem_rbs_collection"
|
8
|
+
gems:
|
9
|
+
- name: activesupport
|
10
|
+
version: '6.0'
|
11
|
+
source:
|
12
|
+
type: git
|
13
|
+
name: ruby/gem_rbs_collection
|
14
|
+
revision: e920cbaa517738b75f3b1e70223a0e51da80d5aa
|
15
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
16
|
+
repo_dir: gems
|
17
|
+
- name: ast
|
18
|
+
version: '2.4'
|
19
|
+
source:
|
20
|
+
type: git
|
21
|
+
name: ruby/gem_rbs_collection
|
22
|
+
revision: e920cbaa517738b75f3b1e70223a0e51da80d5aa
|
23
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
24
|
+
repo_dir: gems
|
25
|
+
- name: i18n
|
26
|
+
version: '1.10'
|
27
|
+
source:
|
28
|
+
type: git
|
29
|
+
name: ruby/gem_rbs_collection
|
30
|
+
revision: e920cbaa517738b75f3b1e70223a0e51da80d5aa
|
31
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
32
|
+
repo_dir: gems
|
33
|
+
- name: io-console
|
34
|
+
version: '0'
|
35
|
+
source:
|
36
|
+
type: stdlib
|
37
|
+
- name: json
|
38
|
+
version: '0'
|
39
|
+
source:
|
40
|
+
type: stdlib
|
41
|
+
- name: listen
|
42
|
+
version: '3.2'
|
43
|
+
source:
|
44
|
+
type: git
|
45
|
+
name: ruby/gem_rbs_collection
|
46
|
+
revision: e920cbaa517738b75f3b1e70223a0e51da80d5aa
|
47
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
48
|
+
repo_dir: gems
|
49
|
+
- name: minitest
|
50
|
+
version: '0'
|
51
|
+
source:
|
52
|
+
type: stdlib
|
53
|
+
- name: parallel
|
54
|
+
version: '1.20'
|
55
|
+
source:
|
56
|
+
type: git
|
57
|
+
name: ruby/gem_rbs_collection
|
58
|
+
revision: e920cbaa517738b75f3b1e70223a0e51da80d5aa
|
59
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
60
|
+
repo_dir: gems
|
61
|
+
- name: rainbow
|
62
|
+
version: '3.0'
|
63
|
+
source:
|
64
|
+
type: git
|
65
|
+
name: ruby/gem_rbs_collection
|
66
|
+
revision: e920cbaa517738b75f3b1e70223a0e51da80d5aa
|
67
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
68
|
+
repo_dir: gems
|
69
|
+
- name: steep
|
70
|
+
version: 1.1.1
|
71
|
+
source:
|
72
|
+
type: rubygems
|
73
|
+
- name: monitor
|
74
|
+
version: '0'
|
75
|
+
source:
|
76
|
+
type: stdlib
|
77
|
+
- name: date
|
78
|
+
version: '0'
|
79
|
+
source:
|
80
|
+
type: stdlib
|
81
|
+
- name: singleton
|
82
|
+
version: '0'
|
83
|
+
source:
|
84
|
+
type: stdlib
|
85
|
+
- name: logger
|
86
|
+
version: '0'
|
87
|
+
source:
|
88
|
+
type: stdlib
|
89
|
+
- name: mutex_m
|
90
|
+
version: '0'
|
91
|
+
source:
|
92
|
+
type: stdlib
|
93
|
+
- name: time
|
94
|
+
version: '0'
|
95
|
+
source:
|
96
|
+
type: stdlib
|
97
|
+
- name: pathname
|
98
|
+
version: '0'
|
99
|
+
source:
|
100
|
+
type: stdlib
|
data/rbs_collection.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Download sources
|
2
|
+
sources:
|
3
|
+
- name: ruby/gem_rbs_collection
|
4
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
5
|
+
revision: main
|
6
|
+
repo_dir: gems
|
7
|
+
|
8
|
+
# A directory to install the downloaded RBSs
|
9
|
+
path: .gem_rbs_collection
|
10
|
+
|
11
|
+
gems:
|
12
|
+
# Skip loading rbs gem's RBS.
|
13
|
+
# It's unnecessary if you don't use rbs as a library.
|
14
|
+
- name: rbs
|
15
|
+
ignore: true
|
data/sig/ffi.rbs
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module FFI
|
2
|
+
module Library
|
3
|
+
def ffi_lib: (Array[String] | String) -> void
|
4
|
+
|
5
|
+
def enum: (Symbol, Array[Symbol | Integer]) -> void
|
6
|
+
|
7
|
+
def attach_function: (Symbol, Array[Symbol], Symbol) -> void
|
8
|
+
end
|
9
|
+
|
10
|
+
class Pointer
|
11
|
+
end
|
12
|
+
|
13
|
+
class MemoryPointer < Pointer
|
14
|
+
def initialize: (Symbol `type`) -> void
|
15
|
+
end
|
16
|
+
end
|