Skip to content

Commit 354c429

Browse files
authored
Merge pull request #15 from umjammer/0.0.14
0.0.14
2 parents 1376acd + 7eeda8b commit 354c429

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1194
-533
lines changed

README.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
# vavi-speech2
77

8+
<img alt="yukkuries" src="https://github.com/umjammer/vavi-speech2/assets/493908/5ccc63da-5dc8-40ac-b6f6-d8dce89b7cf7" width="300" />
9+
810
Text to Speech and Speech to Text (JSAPI2) engines for Java
911

1012
| **Type** | **Description** | **Sythesizer** | **Recognizer** | **Quality** | **Comment** |
@@ -35,21 +37,24 @@ Text to Speech and Speech to Text (JSAPI2) engines for Java
3537
* [get token as json](https://cloud.google.com/text-to-speech/docs/quickstart-client-libraries)
3638
* set environment variable `"GOOGLE_APPLICATION_CREDENTIALS"` `your_json_path`
3739

38-
### Rococoa
39-
40-
* locate `librococoa.dylib` into one of class paths
41-
* if you use maven it's already done, you can find it at `target/test-classes`.
42-
4340
### Open JTalk
4441

45-
* make `libjtalk.dylib` from `https://github.com/rosmarinus/jtalkdll`
46-
* locate `libjtalk.dylib` into `DYLD_LIBRARY_PATH`
42+
* make `libjtalk.dylib` from https://github.com/rosmarinus/jtalkdll
43+
* locate `libjtalk.dylib` into java classpath or `jna.library.path` system property
4744

4845
### VOICEVOX
4946

5047
* [download](https://voicevox.hiroshiba.jp/) the application
5148
* run the application before using this library
5249

50+
## Usage
51+
52+
### user
53+
54+
* [zundamod](https://github.com/umjammer/zundamod)
55+
* [w/ chatGPT](https://github.com/umjammer/vavi-speech-sandbox/)
56+
* [RPC](https://github.com/umjammer/vavi-speech-rpc/)
57+
5358
## Reference
5459

5560
* [jsr113](https://github.com/JVoiceXML/jsapi)

pom.xml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
<groupId>vavi</groupId>
1010
<artifactId>vavi-speech2</artifactId>
11-
<version>0.0.13</version>
11+
<version>0.0.14</version>
1212

1313
<name>vavi-speech2</name>
1414
<description/>
@@ -21,8 +21,8 @@
2121
</issueManagement>
2222

2323
<properties>
24-
<jsapi2.groupId>com.github.umjammer.jsapi</jsapi2.groupId> <!-- org.jvoicexml / com.github.umjammer.jsapi -->
25-
<jsapi2.version>0.6.6</jsapi2.version>
24+
<jsapi2.groupId>com.github.umjammer.jsapi2</jsapi2.groupId> <!-- org.jvoicexml / com.github.umjammer.jsapi2 -->
25+
<jsapi2.version>0.6.9</jsapi2.version>
2626

2727
<jersey.version>3.1.5</jersey.version>
2828
</properties>
@@ -106,7 +106,10 @@
106106
<artifactId>maven-surefire-plugin</artifactId>
107107
<version>3.2.2</version>
108108
<configuration>
109-
<argLine>-Djava.util.logging.config.file=${project.build.testOutputDirectory}/logging.properties</argLine>
109+
<argLine>
110+
-Djava.util.logging.config.file=${project.build.testOutputDirectory}/logging.properties
111+
-Dvavi.util.logging.VaviFormatter.extraClassMethod=sun\.util\.logging\.internal\.LoggingProviderImpl\$JULWrapper#log
112+
</argLine>
110113
<reuseForks>false</reuseForks>
111114
<trimStackTrace>false</trimStackTrace>
112115
<includes>
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
* Copyright (c) 2024 by Naohide Sano, All rights reserved.
3+
*
4+
* Programmed by Naohide Sano
5+
*/
6+
7+
package vavi.speech;
8+
9+
import java.lang.System.Logger;
10+
import java.lang.System.Logger.Level;
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
import java.util.Locale;
14+
import javax.speech.EngineList;
15+
import javax.speech.EngineMode;
16+
import javax.speech.synthesis.SynthesizerMode;
17+
18+
import static java.lang.System.getLogger;
19+
20+
21+
/**
22+
* BaseEnginFactory.
23+
*
24+
* @author <a href="mailto:umjammer@gmail.com">Naohide Sano</a> (nsano)
25+
* @version 0.00 2024-03-14 nsano initial version <br>
26+
*/
27+
public abstract class BaseEnginFactory<V> {
28+
29+
private static final Logger logger = getLogger(BaseEnginFactory.class.getName());
30+
31+
/**
32+
* Used to be able to generate a list of voices based on unique
33+
* combinations of domain/locale pairs.
34+
*/
35+
protected static class DomainLocale<V> {
36+
37+
/** The domain. */
38+
private final String domain;
39+
40+
/** The locale. */
41+
private final Locale locale;
42+
43+
/** Voices for the current domain and locale. */
44+
private final List<WrappedVoice<V>> voices;
45+
46+
/**
47+
* Constructs a new object.
48+
*
49+
* @param domain the domain to use
50+
* @param locale the locale to use
51+
*/
52+
public DomainLocale(String domain, Locale locale) {
53+
this.domain = domain;
54+
this.locale = locale;
55+
this.voices = new ArrayList<>();
56+
}
57+
58+
/**
59+
* See if two DomainLocale objects are equal.
60+
* The voices are NOT compared.
61+
*
62+
* @param o, the object to compare to
63+
* @return true if the domain and locale are both equal, else
64+
* false
65+
*/
66+
public boolean equals(Object o) {
67+
if (!(o instanceof DomainLocale)) {
68+
return false;
69+
}
70+
return (domain.equals(((DomainLocale<?>) o).getDomain())
71+
&& locale.equals(((DomainLocale<?>) o).getLocale()));
72+
}
73+
74+
/**
75+
* Gets the domain.
76+
*
77+
* @return the domain
78+
*/
79+
public String getDomain() {
80+
return domain;
81+
}
82+
83+
/**
84+
* Gets the locale.
85+
*
86+
* @return the locale
87+
*/
88+
public Locale getLocale() {
89+
return locale;
90+
}
91+
92+
/**
93+
* Adds a voice to this instance.
94+
*
95+
* @param voice the voice to add
96+
*/
97+
public void addVoice(WrappedVoice<V> voice) {
98+
voices.add(voice);
99+
}
100+
101+
/**
102+
* Gets the voices of this instance.
103+
*
104+
* @return all of the voices that have been added to this
105+
* instance.
106+
*/
107+
public List<WrappedVoice<V>> getVoices() {
108+
return voices;
109+
}
110+
}
111+
112+
/** Retrieves all voices. */
113+
protected abstract List<WrappedVoice<V>> geAlltVoices();
114+
115+
/** */
116+
protected abstract SynthesizerMode createSynthesizerMode(DomainLocale<V> domainLocale, List<WrappedVoice<V>> voices);
117+
118+
/** */
119+
protected EngineList createEngineListForSynthesizer(EngineMode require) {
120+
// Must be a synthesizer.
121+
if (require != null && !(require instanceof SynthesizerMode)) {
122+
return null;
123+
}
124+
logger.log(Level.TRACE, getClass().getSimpleName() + " --------");
125+
126+
// get all voices available
127+
List<WrappedVoice<V>> voices = geAlltVoices();
128+
logger.log(Level.TRACE, "voices: " + voices.size());
129+
130+
// We want to get all combinations of domains and locales
131+
List<DomainLocale<V>> domainLocaleList = new ArrayList<>();
132+
for (WrappedVoice<V> voice : voices) {
133+
DomainLocale<V> dl = new DomainLocale<>(voice.getDomain(), voice.getLocale());
134+
// If we find the domain locale in the set, add the existing one
135+
// otherwise add the template
136+
DomainLocale<V> dlentry = getItem(domainLocaleList, dl);
137+
if (dlentry == null) {
138+
domainLocaleList.add(dl);
139+
dlentry = dl;
140+
}
141+
dlentry.addVoice(voice);
142+
}
143+
144+
// SynthesizerModes that will be created from combining domain/locale
145+
// with voice names
146+
List<SynthesizerMode> synthesizerModes = new ArrayList<>();
147+
148+
// build list of SynthesizerModeDesc's for each domain/locale
149+
// combination
150+
for (DomainLocale<V> domainLocale : domainLocaleList) {
151+
152+
// iterate through the voices in a different order
153+
voices = domainLocale.getVoices();
154+
155+
SynthesizerMode mode = createSynthesizerMode(domainLocale, voices);
156+
157+
if (require == null || mode.match(require)) {
158+
synthesizerModes.add(mode);
159+
logger.log(Level.TRACE, "MODE: " + mode + ", voices: " + voices.size());
160+
}
161+
}
162+
163+
EngineList el;
164+
if (synthesizerModes.isEmpty()) {
165+
el = null;
166+
} else {
167+
logger.log(Level.DEBUG, "-------- " + getClass().getSimpleName() + " MODES: " + synthesizerModes.size() + ", voices: " + synthesizerModes.stream().mapToInt(m -> m.getVoices().length).sum());
168+
el = new EngineList(synthesizerModes.toArray(EngineMode[]::new));
169+
}
170+
return el;
171+
}
172+
173+
/**
174+
* Gets an item out of a vector.
175+
*
176+
* @param vector the vector to search
177+
* @param o the object to look for using vector.get(i).equals(o)
178+
* @return the item if it exists in the vector, else null
179+
*/
180+
private DomainLocale<V> getItem(List<DomainLocale<V>> vector, DomainLocale<V> o) {
181+
int index = vector.indexOf(o);
182+
if (index < 0) {
183+
return null;
184+
}
185+
return vector.get(index);
186+
}
187+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2024 by Naohide Sano, All rights reserved.
3+
*
4+
* Programmed by Naohide Sano
5+
*/
6+
7+
package vavi.speech;
8+
9+
import java.util.List;
10+
import java.util.Locale;
11+
import javax.speech.SpeechLocale;
12+
import javax.speech.synthesis.Voice;
13+
14+
15+
/**
16+
* WrappedVoice.
17+
*
18+
* @author <a href="mailto:umjammer@gmail.com">Naohide Sano</a> (nsano)
19+
* @version 0.00 2024-03-14 nsano initial version <br>
20+
*/
21+
public abstract class WrappedVoice<V> extends Voice {
22+
23+
/** */
24+
protected V nativeVoice;
25+
26+
/** */
27+
protected WrappedVoice(V nativeVoice) {
28+
this.nativeVoice = nativeVoice;
29+
}
30+
31+
/** */
32+
protected WrappedVoice(SpeechLocale locale, String name, int gender, int age, int variant, V nativeVoice) {
33+
super(locale, name, gender, age, variant);
34+
this.nativeVoice = nativeVoice;
35+
}
36+
37+
/** */
38+
public V getNativeVoice() {
39+
return nativeVoice;
40+
}
41+
42+
/** */
43+
public abstract List<V> getAllNativeVoices();
44+
45+
/** */
46+
public abstract List<WrappedVoice<V>> getAllVoices();
47+
48+
/** */
49+
public abstract String getDomain();
50+
51+
/** */
52+
public abstract Locale getLocale();
53+
}

0 commit comments

Comments
 (0)