Skip to content

Commit 0e5f87c

Browse files
committed
less than three
1 parent d58c94b commit 0e5f87c

File tree

5 files changed

+260
-4
lines changed

5 files changed

+260
-4
lines changed

TTSJava/pom.xml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>simplexity.clitts</groupId>
8+
<artifactId>TTSJava</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<build>
12+
<plugins>
13+
<plugin>
14+
<groupId>org.apache.maven.plugins</groupId>
15+
<artifactId>maven-jar-plugin</artifactId>
16+
<version>3.1.0</version>
17+
<configuration>
18+
<archive>
19+
<manifest>
20+
<mainClass>simplexity.clitts.Main</mainClass>
21+
</manifest>
22+
</archive>
23+
</configuration>
24+
</plugin>
25+
<plugin>
26+
<groupId>org.apache.maven.plugins</groupId>
27+
<artifactId>maven-shade-plugin</artifactId>
28+
<version>3.4.1</version>
29+
<executions>
30+
<execution>
31+
<phase>package</phase>
32+
<goals>
33+
<goal>shade</goal>
34+
</goals>
35+
</execution>
36+
</executions>
37+
</plugin>
38+
</plugins>
39+
</build>
40+
<properties>
41+
<maven.compiler.source>17</maven.compiler.source>
42+
<maven.compiler.target>17</maven.compiler.target>
43+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
44+
</properties>
45+
46+
<dependencies>
47+
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-polly -->
48+
<dependency>
49+
<groupId>com.amazonaws</groupId>
50+
<artifactId>aws-java-sdk-polly</artifactId>
51+
<version>1.11.77</version>
52+
</dependency>
53+
<!-- https://mvnrepository.com/artifact/com.googlecode.soundlibs/jlayer -->
54+
<dependency>
55+
<groupId>com.googlecode.soundlibs</groupId>
56+
<artifactId>jlayer</artifactId>
57+
<version>1.0.1-1</version>
58+
</dependency>
59+
<dependency>
60+
<groupId>com.typesafe</groupId>
61+
<artifactId>config</artifactId>
62+
<version>1.4.3</version>
63+
</dependency>
64+
65+
</dependencies>
66+
67+
68+
</project>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package simplexity.clitts;
2+
3+
import com.amazonaws.regions.Region;
4+
import com.amazonaws.regions.Regions;
5+
import com.amazonaws.services.polly.model.VoiceId;
6+
import com.typesafe.config.Config;
7+
import com.typesafe.config.ConfigFactory;
8+
9+
import java.util.HashMap;
10+
11+
public class TTSConfig {
12+
13+
private static final HashMap<String, String> replaceText = new HashMap<>();
14+
private static final HashMap<String, VoiceId> voicePrefixes = new HashMap<>();
15+
public static Region AWS_REGION;
16+
public static VoiceId defaultVoice;
17+
18+
19+
public static void reloadConfig() {
20+
Config config = ConfigFactory.load();
21+
replaceText.clear();
22+
voicePrefixes.clear();
23+
config.getConfig("replace-text").entrySet().forEach(entry -> {
24+
replaceText.put(entry.getKey(), entry.getValue().unwrapped().toString());
25+
});
26+
config.getConfig("voice-prefixes").entrySet().forEach(entry -> {
27+
try {
28+
VoiceId voiceId = VoiceId.fromValue(String.valueOf(entry.getValue().unwrapped()));
29+
voicePrefixes.put(entry.getKey(), voiceId);
30+
} catch (IllegalArgumentException e) {
31+
System.out.println("Error: " + entry.getValue().unwrapped() + " is not a valid voice. " +
32+
"Please make sure you are only choosing from standard voices"
33+
+ "\nStandard voices can be found here: " + "https://docs.aws.amazon.com/polly/latest/dg/voicelist.html");
34+
}
35+
});
36+
String region = config.getString("aws-region");
37+
try {
38+
AWS_REGION = Region.getRegion(Regions.valueOf(region));
39+
} catch (IllegalArgumentException e) {
40+
System.out.println("Error: " + region + " is not a valid region. "
41+
+ "\nAWS Regions can be found here: " + "https://aws.amazon.com/about-aws/global-infrastructure/regions_az/");
42+
AWS_REGION = Region.getRegion(Regions.US_EAST_1); // Default to US East 1 if region is invalid.
43+
System.out.println("Using default region: " + AWS_REGION.getName());
44+
System.out.println("Please update your config file to use the correct region.");
45+
}
46+
String voice = config.getString("default-voice");
47+
try {
48+
VoiceId.valueOf(voice);
49+
} catch (IllegalArgumentException e) {
50+
System.out.println("Error: " + voice + " is not a valid voice. " +
51+
"Please make sure you are only choosing from standard voices"
52+
+ "\nStandard voices can be found here: " + "https://docs.aws.amazon.com/polly/latest/dg/voicelist.html");
53+
defaultVoice = VoiceId.Kimberly; // Default to Kimberly if voice is invalid.
54+
System.out.println("Using default voice: " + VoiceId.Kimberly);
55+
}
56+
}
57+
58+
public static HashMap<String, String> getReplaceText() {
59+
return replaceText;
60+
}
61+
62+
63+
public static HashMap<String, VoiceId> getVoicePrefixes() {
64+
return voicePrefixes;
65+
}
66+
67+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package simplexity.clitts;
2+
3+
import com.amazonaws.ClientConfiguration;
4+
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
5+
import com.amazonaws.regions.Region;
6+
import com.amazonaws.regions.Regions;
7+
import com.amazonaws.services.polly.AmazonPolly;
8+
import com.amazonaws.services.polly.AmazonPollyClient;
9+
import com.amazonaws.services.polly.model.OutputFormat;
10+
import com.amazonaws.services.polly.model.SynthesizeSpeechRequest;
11+
import com.amazonaws.services.polly.model.SynthesizeSpeechResult;
12+
import javazoom.jl.decoder.JavaLayerException;
13+
import javazoom.jl.player.advanced.AdvancedPlayer;
14+
import javazoom.jl.player.advanced.PlaybackEvent;
15+
import javazoom.jl.player.advanced.PlaybackListener;
16+
17+
import java.io.InputStream;
18+
import java.util.Scanner;
19+
20+
public class TextToSpeech {
21+
22+
private static final Region AWS_REGION = Region.getRegion(Regions.US_EAST_1);
23+
private static final String VOICE_ID = "Joanna"; // Change the voice ID as needed
24+
private static final Scanner scanner = new Scanner(System.in);
25+
private static AmazonPollyClient polly;
26+
private static boolean runProgram = true;
27+
28+
public TextToSpeech() {
29+
polly = new AmazonPollyClient(new DefaultAWSCredentialsProviderChain(), new ClientConfiguration());
30+
polly.setRegion(AWS_REGION);
31+
}
32+
33+
public InputStream synthesizeSpeech(AmazonPolly polly, String text) {
34+
SynthesizeSpeechRequest synthesizeSpeechRequest = new SynthesizeSpeechRequest().withText(text).withVoiceId(VOICE_ID).withOutputFormat(OutputFormat.Mp3);
35+
SynthesizeSpeechResult synthesizeSpeechResult = polly.synthesizeSpeech(synthesizeSpeechRequest);
36+
return synthesizeSpeechResult.getAudioStream();
37+
}
38+
39+
public InputStream synthesizeSSMLSpeech(AmazonPolly polly, String text) {
40+
SynthesizeSpeechRequest synthesizeSpeechRequest = new SynthesizeSpeechRequest().withText(text).withTextType("ssml").withVoiceId(VOICE_ID).withOutputFormat(OutputFormat.Mp3);
41+
SynthesizeSpeechResult synthesizeSpeechResult = polly.synthesizeSpeech(synthesizeSpeechRequest);
42+
return synthesizeSpeechResult.getAudioStream();
43+
}
44+
45+
public String replaceText(String text) {
46+
for (String key : TTSConfig.getReplaceText().keySet()) {
47+
text = text.replace(key, TTSConfig.getReplaceText().get(key));
48+
}
49+
return text;
50+
}
51+
52+
53+
public static void main(String[] args) {
54+
System.out.println("Type your text, press Enter to convert to speech. Type 'exit' to end the program.");
55+
TextToSpeech tts = new TextToSpeech();
56+
InputStream speechStream;
57+
TTSConfig.reloadConfig();
58+
while (runProgram) {
59+
System.out.println("Enter text:");
60+
String text = scanner.nextLine();
61+
String textRef = text;
62+
switch (text) {
63+
case ("--exit") -> {
64+
runProgram = false;
65+
System.out.println("Program ended.");
66+
}
67+
case ("--help") ->
68+
System.out.println("Type your text, press Enter to convert to speech. Type '--exit' to end the program.");
69+
case ("--reload") -> {
70+
TTSConfig.reloadConfig();
71+
System.out.println("Config reloaded.");
72+
}
73+
default -> {
74+
text = tts.replaceText(text);
75+
boolean useSSML = !textRef.equals(text);
76+
try {
77+
if (!useSSML) {
78+
speechStream = tts.synthesizeSpeech(polly, text);
79+
} else {
80+
speechStream = tts.synthesizeSSMLSpeech(polly, text);
81+
}
82+
AdvancedPlayer player = new AdvancedPlayer(speechStream, javazoom.jl.player.FactoryRegistry.systemRegistry().createAudioDevice());
83+
player.setPlayBackListener(new PlaybackListener() {
84+
@Override
85+
public void playbackStarted(PlaybackEvent event) {
86+
System.out.println("Playing speech...");
87+
}
88+
89+
@Override
90+
public void playbackFinished(PlaybackEvent event) {
91+
System.out.println("Speech finished playing.");
92+
}
93+
});
94+
player.play();
95+
} catch (JavaLayerException e) {
96+
System.out.println("Error playing speech. " + e);
97+
}
98+
}
99+
}
100+
}
101+
}
102+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
aws-region = "US_EAST_1"
2+
default-voice = "Kimberly"
3+
replace-text {
4+
"/_" = "</emphasis>"
5+
"_/" = "</emphasis>"
6+
"++" = "<prosody volume=\"x-loud\" rate=\"fast\">"
7+
"/+" = "</prosody>"
8+
"+/" = "</prosody>"
9+
"!!" = "<say-as interpret-as=\"expletive\">"
10+
"/!" = "</say-as>"
11+
"!/" = "</say-as>"
12+
"-" = "<break time=\"300ms\"/>"
13+
}
14+
voice-prefixes {
15+
"R:" = "Salli"
16+
"E:" = "Kimberly"
17+
"D-" = "Brian"
18+
}

text_replace.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"++": "<prosody volume=\"x-loud\" rate=\"fast\">",
1212
"/+": "</prosody>",
1313
"+/": "</prosody>",
14-
"##": "<say-as interpret-as=\"expletive\">",
15-
"#/": "</say-as>",
16-
"/#": "</say-as>"
17-
}
14+
"!!": "<say-as interpret-as=\"expletive\">",
15+
"/!": "</say-as>",
16+
"!/": "</say-as>",
17+
"-": "<break time=\"300ms\"/>"
18+
}

0 commit comments

Comments
 (0)