/*
* Copyright 2015, RagingGoblin <http://raginggoblin.wordpress.com>
*
* This file is part of SpeechLess.
*
* SpeechLess is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SpeechLess is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with SpeechLess. If not, see <http://www.gnu.org/licenses/>.
*/
package raging.goblin.speechless.speech;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import raging.goblin.speechless.Messages;
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
public class SoundEffect {
public enum Effect {
TRACT_SCALER, F0_SCALE, F0_ADD, RATE, ROBOT, WHISPER, STADIUM, CHORUS, FIR_FILTER, JET_PILOT
};
private static final Preferences PREFERENCES = Preferences.userNodeForPackage(SoundEffect.class);
private static final Messages MESSAGES = Messages.getInstance();
private static final List<SoundEffect> EFFECTS = new ArrayList<>();
private Effect effect;
private String name;
private String helpText;
private String format;
private Map<String, List<Double>> defaultLevels;
public static List<SoundEffect> getAllSoundEffects() {
if (EFFECTS.isEmpty()) {
EFFECTS.add(createTractScaler());
EFFECTS.add(createF0Add());
EFFECTS.add(createF0Scale());
EFFECTS.add(createRobot());
EFFECTS.add(createWhisper());
EFFECTS.add(createStadium());
EFFECTS.add(createChorus());
EFFECTS.add(createFirFilter());
EFFECTS.add(createJetPilot());
}
return EFFECTS;
}
public static String toMaryTTSString() {
return getAllSoundEffects().stream().filter(e -> e.isEnabled()).map(e -> e.getMaryTTSString())
.collect(Collectors.joining("+"));
}
public List<String> getLevelKeys() {
return new ArrayList<>(defaultLevels.keySet());
}
public void setLevel(String key, double value) {
if (defaultLevels.containsKey(key)) {
PREFERENCES.putDouble(effect + "_" + key, value);
}
}
public double getLevel(String key) {
return PREFERENCES.getDouble(effect + "_" + key, defaultLevels.get(key).get(0));
}
public void setDefaultLevels() {
for (String key : defaultLevels.keySet()) {
setLevel(key, defaultLevels.get(key).get(0));
}
}
public boolean isEnabled() {
return PREFERENCES.getBoolean(effect.name() + "_enabled", false);
}
public void setEnabled(boolean enabled) {
PREFERENCES.putBoolean(effect.name() + "_enabled", enabled);
}
private static SoundEffect createTractScaler() {
return new SoundEffect(Effect.TRACT_SCALER, MESSAGES.get("tract_scaler"), MESSAGES.get("tract_scaler_help"),
"TractScaler(amount=%.2f;)", createDefaultLevelsMap(Arrays.asList("amount"),
Arrays.asList(Arrays.asList(1.5, 0.25, 4.0, 0.1))));
}
private static SoundEffect createJetPilot() {
return new SoundEffect(Effect.JET_PILOT, MESSAGES.get("jet_pilot"), MESSAGES.get("jet_pilot_help"), "JetPilot",
new HashMap<>());
}
private static SoundEffect createF0Scale() {
return new SoundEffect(Effect.F0_SCALE, MESSAGES.get("f0_scaling"), MESSAGES.get("f0_scaling_help"),
"F0Scale(f0Scale=%.2f;)", createDefaultLevelsMap(Arrays.asList("f0Scale"),
Arrays.asList(Arrays.asList(2.0, 0.0, 3.0, 0.1))));
}
private static SoundEffect createF0Add() {
return new SoundEffect(Effect.F0_ADD, MESSAGES.get("f0_add"), MESSAGES.get("f0_add_help"), "F0Add(f0Add=%.2f;)",
createDefaultLevelsMap(Arrays.asList("f0Add"), Arrays.asList(Arrays.asList(50.0, -300.0, 300.0, 10.0))));
}
private static SoundEffect createRate() {
return new SoundEffect(Effect.RATE, MESSAGES.get("rate"), MESSAGES.get("rate_help"), "Rate(durScale=%.2f;)",
createDefaultLevelsMap(Arrays.asList("durScale"), Arrays.asList(Arrays.asList(1.5, 0.1, 3.0, 0.1))));
}
private static SoundEffect createRobot() {
return new SoundEffect(Effect.ROBOT, MESSAGES.get("robot"), MESSAGES.get("robot_help"), "Robot(amount=%.2f;)",
createDefaultLevelsMap(Arrays.asList("amount"), Arrays.asList(Arrays.asList(100.0, 0.0, 100.0, 10.0))));
}
private static SoundEffect createWhisper() {
return new SoundEffect(Effect.WHISPER, MESSAGES.get("whisper"), MESSAGES.get("whisper_help"),
"Whisper(amount=%.2f;)", createDefaultLevelsMap(Arrays.asList("amount"),
Arrays.asList(Arrays.asList(100.0, 0.0, 100.0, 10.0))));
}
private static SoundEffect createStadium() {
return new SoundEffect(Effect.STADIUM, MESSAGES.get("stadium"), MESSAGES.get("stadium_help"),
"Stadium(amount=%.2f;)", createDefaultLevelsMap(Arrays.asList("amount"),
Arrays.asList(Arrays.asList(100.0, 0.0, 200.0, 10.0))));
}
private static SoundEffect createChorus() {
return new SoundEffect(Effect.CHORUS, MESSAGES.get("chorus"), MESSAGES.get("chorus_help"),
"Chorus(delay1=%.2f; amp1=%.2f; delay2=%.2f; amp2=%.2f; delay3=%.2f; amp3=%.2f;)", createDefaultLevelsMap(
Arrays.asList("delay1", "amp1", "delay2", "amp2", "delay3", "amp3"),
Arrays.asList(Arrays.asList(466.0, 0.0, 5000.0, 100.0), Arrays.asList(0.54, -5.0, 5.0, 0.1),
Arrays.asList(600.0, 0.0, 5000.0, 100.0), Arrays.asList(-0.10, -5.0, 5.0, 0.1),
Arrays.asList(250.0, 0.0, 5000.0, 100.0), Arrays.asList(0.30, -5.0, 5.0, 0.1))));
}
private static SoundEffect createFirFilter() {
return new SoundEffect(Effect.FIR_FILTER, MESSAGES.get("fir_filter"), MESSAGES.get("fir_filter_help"),
"FIRFilter(type=%.2f; fc1=%.2f; fc2=%.2f;)", createDefaultLevelsMap(
Arrays.asList("type", "fc1", "fc2"),
Arrays.asList(Arrays.asList(3.0, 1.0, 4.0, 1.0), Arrays.asList(500.0, 0.0, 20000.0, 100.0),
Arrays.asList(2000.0, 0.0, 20000.0, 100.0))));
}
private static Map<String, List<Double>> createDefaultLevelsMap(List<String> keys, List<List<Double>> values) {
Map<String, List<Double>> defaultLevels = new LinkedHashMap<>();
for (int i = 0; i < keys.size(); i++) {
defaultLevels.put(keys.get(i), values.get(i));
}
return defaultLevels;
}
private String getMaryTTSString() {
List<Double> values = defaultLevels.keySet().stream().map(k -> getLevel(k)).collect(Collectors.toList());
return String.format(format, values.toArray());
}
}