积累性代码更新(一股ms味)

0. 新增语言缓存清除功能
1. 新增语音音频文件格式选择
2. 修复语言设置不生效的问题
3. 因百度语言合成的限制,屏蔽部分语音库
4. 其他的一些小修小改与优 化
5. 第三次代码重构已在计划中(划掉)
main
lensfrex 3 years ago
parent 0fd9a6dfcb
commit 08f48c055b
Signed by: lensfrex
GPG Key ID: 0F69A0A2FBEE98A0
  1. 53
      Dogename/src/main/java/me/lensferno/dogename/configs/ConfigLoader.java
  2. 4
      Dogename/src/main/java/me/lensferno/dogename/configs/ConfigValuesBean.java
  3. 64
      Dogename/src/main/java/me/lensferno/dogename/configs/VoiceConfig.java
  4. 9
      Dogename/src/main/java/me/lensferno/dogename/controllers/MainInterfaceController.java
  5. 14
      Dogename/src/main/java/me/lensferno/dogename/controllers/SettingsPaneController.java
  6. 86
      Dogename/src/main/java/me/lensferno/dogename/controllers/VoiceSettingsPaneController.java
  7. 2
      Dogename/src/main/java/me/lensferno/dogename/data/History.java
  8. 1
      Dogename/src/main/java/me/lensferno/dogename/select/core/Worker.java
  9. 13
      Dogename/src/main/java/me/lensferno/dogename/utils/DialogMaker.java
  10. 53
      Dogename/src/main/java/me/lensferno/dogename/voice/VoicePlayer.java
  11. 53
      Dogename/src/main/resources/me/lensferno/dogename/FXMLs/AdvancedVoiceSettingsPane.fxml
  12. 2
      Dogename/src/main/resources/me/lensferno/dogename/FXMLs/MainInterface.fxml
  13. 2
      Dogename/src/main/resources/me/lensferno/dogename/FXMLs/NameManagerPane.fxml
  14. 139
      Dogename/src/main/resources/me/lensferno/dogename/FXMLs/VoiceSettingsPane.fxml

@ -11,19 +11,17 @@ import me.lensferno.dogename.configs.adapters.DoublePropertyAdapter;
import me.lensferno.dogename.configs.adapters.IntegerPropertyAdapter; import me.lensferno.dogename.configs.adapters.IntegerPropertyAdapter;
import me.lensferno.dogename.configs.adapters.StringPropertyAdapter; import me.lensferno.dogename.configs.adapters.StringPropertyAdapter;
import me.lensferno.dogename.utils.FilePath; import me.lensferno.dogename.utils.FilePath;
import me.lensferno.dogename.voice.VoicePlayer;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
public class ConfigLoader { public class ConfigLoader {
private final String mainConfigLocation = FilePath.toSpecificPathForm("files/Config.json"); private final String mainConfigLocation = FilePath.toSpecificPathForm("files/Config.json");
private final String voiceConfigLocation = FilePath.toSpecificPathForm("files/VoiceConfig.json"); private final String voiceConfigLocation = FilePath.toSpecificPathForm("files/VoiceConfig.json");
//ConfigValuesBean config; //ConfigValuesBean config;
private MainConfig mainConfig; private MainConfig mainConfig;
private VoiceConfig voiceConfig;
public String getMainConfigLocation() { public String getMainConfigLocation() {
return mainConfigLocation; return mainConfigLocation;
@ -38,7 +36,6 @@ public class ConfigLoader {
} }
public MainConfig readConfigFromFile(String fileLocation) { public MainConfig readConfigFromFile(String fileLocation) {
//property属性应该要自定义一个json适配器才能解析出来 //property属性应该要自定义一个json适配器才能解析出来
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.registerTypeAdapter(SimpleBooleanProperty.class, new BooleanPropertyAdapter()) .registerTypeAdapter(SimpleBooleanProperty.class, new BooleanPropertyAdapter())
@ -48,7 +45,7 @@ public class ConfigLoader {
.setPrettyPrinting() .setPrettyPrinting()
.create(); .create();
String ConfigJSON; String configJson;
try { try {
File configFile = new File(fileLocation); File configFile = new File(fileLocation);
@ -60,9 +57,10 @@ public class ConfigLoader {
return mainConfig; return mainConfig;
} }
InputStream inputStream = new FileInputStream(configFile); InputStream inputStream = new FileInputStream(configFile);
ConfigJSON = IOUtils.toString(inputStream, StandardCharsets.UTF_8); configJson = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
inputStream.close();
mainConfig = gson.fromJson(ConfigJSON, MainConfig.class); mainConfig = gson.fromJson(configJson, MainConfig.class);
if (mainConfig == null) { if (mainConfig == null) {
mainConfig = new MainConfig(); mainConfig = new MainConfig();
@ -82,7 +80,6 @@ public class ConfigLoader {
} }
public VoiceConfig readVoiceConfigFromFile(String fileLocation) { public VoiceConfig readVoiceConfigFromFile(String fileLocation) {
//property属性应该要自定义一个json适配器才能解析出来 //property属性应该要自定义一个json适配器才能解析出来
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.registerTypeAdapter(SimpleBooleanProperty.class, new BooleanPropertyAdapter()) .registerTypeAdapter(SimpleBooleanProperty.class, new BooleanPropertyAdapter())
@ -92,7 +89,7 @@ public class ConfigLoader {
.setPrettyPrinting() .setPrettyPrinting()
.create(); .create();
String ConfigJSON; String configJson;
try { try {
File configFile = new File(fileLocation); File configFile = new File(fileLocation);
@ -100,38 +97,31 @@ public class ConfigLoader {
configFile.getParentFile().mkdirs(); configFile.getParentFile().mkdirs();
configFile.createNewFile(); configFile.createNewFile();
voiceConfig = new VoiceConfig(); VoicePlayer.voiceConfig = new VoiceConfig();
writeVoiceConfigToFile(voiceConfigLocation); writeVoiceConfigToFile(voiceConfigLocation);
return voiceConfig; return VoicePlayer.voiceConfig;
} }
InputStream inputStream = new FileInputStream(configFile); InputStream inputStream = new FileInputStream(configFile);
ConfigJSON = IOUtils.toString(inputStream, StandardCharsets.UTF_8); configJson = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
inputStream.close();
writeVoiceConfigToFile(voiceConfigLocation); VoicePlayer.voiceConfig = gson.fromJson(configJson, VoiceConfig.class);
voiceConfig = gson.fromJson(ConfigJSON, VoiceConfig.class);
if (voiceConfig == null) { if (VoicePlayer.voiceConfig == null) {
voiceConfig = new VoiceConfig(); VoicePlayer.voiceConfig = new VoiceConfig();
writeVoiceConfigToFile(voiceConfigLocation); writeVoiceConfigToFile(voiceConfigLocation);
return voiceConfig; return VoicePlayer.voiceConfig;
} }
} catch (Exception e) { } catch (Exception e) {
System.out.println("Error to load voice config file:" + e + "\nUse Default voice config."); System.out.println("Error to load voice config file:" + e + "\nUse Default voice config.");
voiceConfig = new VoiceConfig(); VoicePlayer.voiceConfig = new VoiceConfig();
writeVoiceConfigToFile(voiceConfigLocation); writeVoiceConfigToFile(voiceConfigLocation);
return voiceConfig; return VoicePlayer.voiceConfig;
} }
return this.voiceConfig; return VoicePlayer.voiceConfig;
}
//
public MainConfig setValuesToProperty() {
//mainconfig.set..(config.get..)
//...so on
//
return this.mainConfig;
} }
private String toJSON(MainConfig config) { private String toJSON(MainConfig config) {
@ -146,8 +136,7 @@ public class ConfigLoader {
return gson.toJson(config); return gson.toJson(config);
} }
private String VoiceConfigtoJSON(VoiceConfig config) { private String getConfigJson(VoiceConfig config) {
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.registerTypeAdapter(SimpleDoubleProperty.class, new DoublePropertyAdapter()) .registerTypeAdapter(SimpleDoubleProperty.class, new DoublePropertyAdapter())
.setPrettyPrinting() .setPrettyPrinting()
@ -168,7 +157,7 @@ public class ConfigLoader {
IOUtils.write(toJSON(this.mainConfig).getBytes(StandardCharsets.UTF_8), stream); IOUtils.write(toJSON(this.mainConfig).getBytes(StandardCharsets.UTF_8), stream);
OutputStream voiceConfigFileStream = new FileOutputStream(voiceConfigFile); OutputStream voiceConfigFileStream = new FileOutputStream(voiceConfigFile);
IOUtils.write(VoiceConfigtoJSON(this.voiceConfig).getBytes(StandardCharsets.UTF_8), voiceConfigFileStream); IOUtils.write(getConfigJson(VoicePlayer.voiceConfig).getBytes(StandardCharsets.UTF_8), voiceConfigFileStream);
} catch (Exception e) { } catch (Exception e) {
System.out.println("Error in writing all config:" + e); System.out.println("Error in writing all config:" + e);
@ -202,7 +191,7 @@ public class ConfigLoader {
outputFile.createNewFile(); outputFile.createNewFile();
} }
OutputStream voiceConfigFileStream = new FileOutputStream(voiceConfigFile); OutputStream voiceConfigFileStream = new FileOutputStream(voiceConfigFile);
IOUtils.write(VoiceConfigtoJSON(this.voiceConfig).getBytes(StandardCharsets.UTF_8), voiceConfigFileStream); IOUtils.write(getConfigJson(VoicePlayer.voiceConfig).getBytes(StandardCharsets.UTF_8), voiceConfigFileStream);
} catch (Exception e) { } catch (Exception e) {
System.out.println("Error in writing voice config:" + e); System.out.println("Error in writing voice config:" + e);

@ -1,4 +0,0 @@
package me.lensferno.dogename.configs;
public class ConfigValuesBean {
}

@ -1,43 +1,51 @@
package me.lensferno.dogename.configs; package me.lensferno.dogename.configs;
import com.google.gson.annotations.Expose;
import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent; import javafx.beans.property.SimpleIntegerProperty;
import javafx.fxml.FXML; import javafx.beans.property.SimpleStringProperty;
public class VoiceConfig { public class VoiceConfig {
@Expose
public static final int DEFAULT_SPEED = 5;
@Expose
public static final int DEFAULT_INTONATION = 5;
public final int DEFAULT_SPEED = 5; @Expose
public final int DEFAULT_INTONATION = 5; public static final int AUDIO_FORMAT_WAV = 6;
@Expose
public static final int AUDIO_FORMAT_MP3 = 3;
//度小宇=1,度小美=0,度逍遥=3,度丫丫=4 //度小宇=1,度小美=0,度逍遥=3,度丫丫=4
//度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5 //度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5
private String speaker; private String speakerIdString;
private int selectedSpeaker; private int audioFormat;
private int speaker;
private final SimpleDoubleProperty speed; private final SimpleDoubleProperty speed;
private final SimpleDoubleProperty intonation; private final SimpleDoubleProperty intonation;
public VoiceConfig() { public VoiceConfig() {
selectedSpeaker = 0; this.speaker = 0;
speaker = "1"; this.speakerIdString = "1";
speed = new SimpleDoubleProperty(DEFAULT_SPEED); this.speed = new SimpleDoubleProperty(DEFAULT_SPEED);
intonation = new SimpleDoubleProperty(DEFAULT_INTONATION); this.intonation = new SimpleDoubleProperty(DEFAULT_INTONATION);
this.audioFormat = AUDIO_FORMAT_WAV;
} }
public String getSpeaker() { public String getSpeakerIdString() {
return speaker; return speakerIdString;
} }
public void setSpeaker(String speaker) { public void setSpeakerIdString(String speakerIdString) {
this.speaker = speaker; this.speakerIdString = speakerIdString;
} }
public int getSelectedSpeaker() { public int getSpeaker() {
return selectedSpeaker; return speaker;
} }
public void setSelectedSpeaker(int selectedSpeaker) { public void setSpeaker(int speaker) {
this.selectedSpeaker = selectedSpeaker; this.speaker = speaker;
} }
public double getSpeed() { public double getSpeed() {
@ -64,10 +72,22 @@ public class VoiceConfig {
return intonation; return intonation;
} }
@FXML public void setAudioFormat(int audioFormat) {
void showAdvancedVoiceSettings(ActionEvent event) { this.audioFormat = audioFormat;
} }
public int getAudioFormat() {
return audioFormat;
}
public static String getAudioFileSuffix(int format) {
switch (format) {
case VoiceConfig.AUDIO_FORMAT_WAV:
return "wav";
case VoiceConfig.AUDIO_FORMAT_MP3:
return "mp3";
default:
return "cache";
}
}
} }

@ -24,6 +24,7 @@ import me.lensferno.dogename.select.Selector;
import me.lensferno.dogename.utils.DialogMaker; import me.lensferno.dogename.utils.DialogMaker;
import me.lensferno.dogename.utils.FilePath; import me.lensferno.dogename.utils.FilePath;
import me.lensferno.dogename.utils.ocr.OcrTool; import me.lensferno.dogename.utils.ocr.OcrTool;
import me.lensferno.dogename.voice.VoicePlayer;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -38,10 +39,10 @@ public final class MainInterfaceController {
History history = new History(); History history = new History();
MainConfig mainConfig; MainConfig mainConfig;
VoiceConfig voiceConfig;
Random random = new Random(); Random random = new Random();
Data data = new Data(); Data data = new Data();
Selector selector = new Selector(); Selector selector = new Selector();
@FXML @FXML
private Pane rootPane; private Pane rootPane;
@FXML @FXML
@ -88,7 +89,7 @@ public final class MainInterfaceController {
public void setUpConfig(ConfigLoader configLoader) { public void setUpConfig(ConfigLoader configLoader) {
mainConfig = configLoader.readConfigFromFile(FilePath.toSpecificPathForm("files/Config.json")); mainConfig = configLoader.readConfigFromFile(FilePath.toSpecificPathForm("files/Config.json"));
voiceConfig = configLoader.readVoiceConfigFromFile(FilePath.toSpecificPathForm("files/VoiceConfig.json")); VoicePlayer.voiceConfig = configLoader.readVoiceConfigFromFile(FilePath.toSpecificPathForm("files/VoiceConfig.json"));
} }
@FXML @FXML
@ -108,7 +109,7 @@ public final class MainInterfaceController {
} }
@FXML @FXML
void showNunberSetting(ActionEvent event) { void showNumberSetting(ActionEvent event) {
if (selector.isWorkerRunning()) { if (selector.isWorkerRunning()) {
new DialogMaker(rootPane).createMessageDialog("(・。・)", "安排中......\n为保证运行的稳定,此时还不能进行该操作哦。"); new DialogMaker(rootPane).createMessageDialog("(・。・)", "安排中......\n为保证运行的稳定,此时还不能进行该操作哦。");
@ -159,8 +160,6 @@ public final class MainInterfaceController {
settingsPaneController.setToggleGroup(); settingsPaneController.setToggleGroup();
settingsPaneController.bindProperties(mainConfig); settingsPaneController.bindProperties(mainConfig);
settingsPaneController.setVoiceConfig(voiceConfig);
settingsPaneController.setRootPane(rootPane); settingsPaneController.setRootPane(rootPane);
settingsPaneController.setData(data); settingsPaneController.setData(data);

@ -13,14 +13,14 @@ import me.lensferno.dogename.configs.MainConfig;
import me.lensferno.dogename.configs.VoiceConfig; import me.lensferno.dogename.configs.VoiceConfig;
import me.lensferno.dogename.data.Data; import me.lensferno.dogename.data.Data;
import me.lensferno.dogename.utils.DialogMaker; import me.lensferno.dogename.utils.DialogMaker;
import me.lensferno.dogename.voice.VoicePlayer;
public class SettingsPaneController extends VBox { public class SettingsPaneController extends VBox {
MainConfig mainConfig; MainConfig mainConfig;
VoiceConfig voiceConfig;
Pane rootPane; Pane rootPane;
Data data; Data data;
@FXML @FXML
private JFXCheckBox showSayingBtn; private JFXCheckBox showSayingBtn;
@FXML @FXML
@ -42,7 +42,6 @@ public class SettingsPaneController extends VBox {
@FXML @FXML
private JFXRadioButton fixedTimes; private JFXRadioButton fixedTimes;
public SettingsPaneController() { public SettingsPaneController() {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/SettingsPane.fxml")); FXMLLoader loader = new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/SettingsPane.fxml"));
loader.setRoot(this); loader.setRoot(this);
@ -58,10 +57,6 @@ public class SettingsPaneController extends VBox {
this.mainConfig = mainConfig; this.mainConfig = mainConfig;
} }
public void setVoiceConfig(VoiceConfig voiceConfig) {
this.voiceConfig = voiceConfig;
}
public void setRootPane(Pane rootPane) { public void setRootPane(Pane rootPane) {
this.rootPane = rootPane; this.rootPane = rootPane;
} }
@ -107,8 +102,8 @@ public class SettingsPaneController extends VBox {
@FXML @FXML
void showVoiceSettingsPane(ActionEvent event) { void showVoiceSettingsPane(ActionEvent event) {
VoiceSettingsPaneController voiceSettingsPaneController = new VoiceSettingsPaneController(); VoiceSettingsPaneController voiceSettingsPaneController = new VoiceSettingsPaneController(rootPane);
voiceSettingsPaneController.bindPropertied(voiceConfig); voiceSettingsPaneController.bindPropertied();
new DialogMaker(rootPane).createDialogWithOneBtn("语音设置", voiceSettingsPaneController); new DialogMaker(rootPane).createDialogWithOneBtn("语音设置", voiceSettingsPaneController);
} }
@ -116,7 +111,6 @@ public class SettingsPaneController extends VBox {
void showEqualMode(ActionEvent event) { void showEqualMode(ActionEvent event) {
new DialogMaker(rootPane).createMessageDialog("什么?", new DialogMaker(rootPane).createMessageDialog("什么?",
"//有待补充。;-)"); "//有待补充。;-)");
} }
@FXML @FXML

@ -1,34 +1,51 @@
package me.lensferno.dogename.controllers; package me.lensferno.dogename.controllers;
import com.jfoenix.controls.JFXComboBox; import com.jfoenix.controls.JFXComboBox;
import com.jfoenix.controls.JFXRadioButton;
import com.jfoenix.controls.JFXSlider; import com.jfoenix.controls.JFXSlider;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import me.lensferno.dogename.configs.VoiceConfig; import me.lensferno.dogename.configs.VoiceConfig;
import me.lensferno.dogename.utils.DialogMaker;
import me.lensferno.dogename.voice.VoicePlayer;
import java.io.File;
import java.util.HashMap;
import java.util.logging.Logger; import java.util.logging.Logger;
public class VoiceSettingsPaneController extends VBox { public class VoiceSettingsPaneController extends VBox {
public static final ObservableList<String> shownSpeakerList = FXCollections.observableArrayList(); private static final ObservableList<String> speakerList = FXCollections.observableArrayList();
//度小宇=1,度小美=0,度逍遥=3,度丫丫=4
//度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5
private final String[] speakers = { private final String[] speakers = {
"1", "0", "3", "4", "1", "0", "3", "4",
"106", "110", "111", "103", "5"}; "106", "110", "111", "103", "5"};
Logger log = Logger.getLogger("VoiceSettingsPaneControllerLogger"); Logger log = Logger.getLogger("VoiceSettingsPaneControllerLogger");
VoiceConfig voiceConfig = new VoiceConfig();
@FXML @FXML
private JFXSlider intonationBar; private JFXSlider intonationBar;
@FXML @FXML
private JFXComboBox<String> speakerSelectBar; private JFXComboBox<String> speakerSelectBar;
@FXML @FXML
private JFXSlider voiceSpeedBar; private JFXSlider voiceSpeedBar;
//度小宇=1,度小美=0,度逍遥=3,度丫丫=4 @FXML
//度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5 private JFXRadioButton wavFormatButton;
@FXML
private JFXRadioButton mp3FormatButton;
private final Pane rootPane;
public VoiceSettingsPaneController() { public VoiceSettingsPaneController(Pane rootPane) {
this.rootPane = rootPane;
FXMLLoader loader = new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/VoiceSettingsPane.fxml")); FXMLLoader loader = new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/VoiceSettingsPane.fxml"));
loader.setRoot(this); loader.setRoot(this);
loader.setController(this); loader.setController(this);
@ -37,41 +54,50 @@ public class VoiceSettingsPaneController extends VBox {
} catch (Exception e) { } catch (Exception e) {
log.warning("Error to load settings pane FXML: " + e); log.warning("Error to load settings pane FXML: " + e);
} }
if (shownSpeakerList.isEmpty()) { if (speakerList.isEmpty()) {
shownSpeakerList.addAll( speakerList.addAll(
"度小宇=1", "度小美=0", "度逍遥=3", "度丫丫=4", "度小宇=1", "度小美=0", "度逍遥=3", "度丫丫=4"
"度博文=106", "度小童=110", "度小萌=111", "度米朵=103", "度小娇=5"); // 非高级API用户,这些精品音频库用不了(等把“高级设置”弄出来再说吧...)
/*, "度博文=106", "度小童=110", "度小萌=111", "度米朵=103", "度小娇=5"*/);
} }
speakerSelectBar.setItems(shownSpeakerList); speakerSelectBar.setItems(speakerList);
} }
public void bindPropertied(VoiceConfig voiceConfig) { @FXML
ToggleGroup audioFormatToggleGroup = new ToggleGroup();
this.voiceConfig = voiceConfig; HashMap<Integer, Toggle> audioFormatMap = new HashMap<>();
//speakerSelectBar. public void bindPropertied() {
wavFormatButton.setToggleGroup(audioFormatToggleGroup);
mp3FormatButton.setToggleGroup(audioFormatToggleGroup);
audioFormatMap.put(VoiceConfig.AUDIO_FORMAT_WAV, wavFormatButton);
audioFormatMap.put(VoiceConfig.AUDIO_FORMAT_MP3, mp3FormatButton);
speakerSelectBar.selectionModelProperty().addListener((observable, oldValue, newValue) -> { audioFormatToggleGroup.selectToggle(audioFormatMap.get(VoicePlayer.voiceConfig.getAudioFormat()));
System.out.println("what?" + newValue.getSelectedIndex()); audioFormatToggleGroup.selectedToggleProperty().addListener((observable, oldValue, selectBtn) ->
this.voiceConfig.setSpeaker(speakers[newValue.getSelectedIndex()]); VoicePlayer.voiceConfig.setAudioFormat(selectBtn.equals(wavFormatButton) ? VoiceConfig.AUDIO_FORMAT_WAV : VoiceConfig.AUDIO_FORMAT_MP3));
this.voiceConfig.setSelectedSpeaker(newValue.getSelectedIndex());
});
//speakerSelectBar.setValue(this.voiceConfig.getSpeaker()); speakerSelectBar.getSelectionModel().select(VoicePlayer.voiceConfig.getSpeaker());
speakerSelectBar.valueProperty().addListener((observable, oldValue, newValue) -> {
int selectedSpeakerIndex = speakerSelectBar.getSelectionModel().getSelectedIndex();
voiceSpeedBar.valueProperty().bindBidirectional(voiceConfig.speedProperty()); VoicePlayer.voiceConfig.setSpeakerIdString(speakers[selectedSpeakerIndex]);
intonationBar.valueProperty().bindBidirectional(voiceConfig.intonationProperty()); VoicePlayer.voiceConfig.setSpeaker(selectedSpeakerIndex);
});
speakerSelectBar.getSelectionModel().select(this.voiceConfig.getSelectedSpeaker()); voiceSpeedBar.valueProperty().bindBidirectional(VoicePlayer.voiceConfig.speedProperty());
intonationBar.valueProperty().bindBidirectional(VoicePlayer.voiceConfig.intonationProperty());
} }
@FXML @FXML
void showAdvancedVoiceSettings(ActionEvent event) { void clearCache(ActionEvent event) {
File[] cacheFiles = new File(VoicePlayer.cachePath).listFiles();
if (cacheFiles != null) {
for (File cacheFile : cacheFiles) {
cacheFile.delete();
}
}
new DialogMaker(rootPane).createMessageDialog("嘿咻~","缓存已清除");
} }
}
}

@ -27,7 +27,7 @@ public class History {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(historyFile)); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(historyFile));
history = (ArrayList<String>) ois.readObject(); history = (ArrayList<String>) ois.readObject();
ois.close();
} catch (EOFException e) { } catch (EOFException e) {
history = new ArrayList<>(); history = new ArrayList<>();
System.out.println("History file is empty."); System.out.println("History file is empty.");

@ -3,6 +3,7 @@ package me.lensferno.dogename.select.core;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
import me.lensferno.dogename.configs.MainConfig; import me.lensferno.dogename.configs.MainConfig;
import me.lensferno.dogename.configs.VoiceConfig;
import me.lensferno.dogename.data.Data; import me.lensferno.dogename.data.Data;
import me.lensferno.dogename.data.History; import me.lensferno.dogename.data.History;
import me.lensferno.dogename.utils.Random; import me.lensferno.dogename.utils.Random;

@ -3,6 +3,7 @@ package me.lensferno.dogename.utils;
import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog; import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialogLayout; import com.jfoenix.controls.JFXDialogLayout;
import com.jfoenix.controls.events.JFXDialogEvent;
import javafx.beans.NamedArg; import javafx.beans.NamedArg;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
@ -21,7 +22,6 @@ public class DialogMaker {
Pane rootPane; Pane rootPane;
JFXDialog dialog; JFXDialog dialog;
public DialogMaker(@NamedArg("rootPane") Pane rootPane) { public DialogMaker(@NamedArg("rootPane") Pane rootPane) {
this.rootPane = rootPane; this.rootPane = rootPane;
} }
@ -39,7 +39,7 @@ public class DialogMaker {
} }
//创建只有一个按钮的dialog //创建只有一个按钮的dialog
public void createDialogWithOneBtn(@NamedArg("title") String title, @NamedArg("theBody") Node body) { public void createDialogWithOneBtn(@NamedArg("title") String title, @NamedArg("theBody") Node body, @NamedArg("OKEvent") EventHandler<JFXDialogEvent> event) {
//dialog.setPrefHeight(rootPane.getPrefHeight()); //dialog.setPrefHeight(rootPane.getPrefHeight());
//dialog.setPrefWidth(rootPane.getPrefWidth()); //dialog.setPrefWidth(rootPane.getPrefWidth());
@ -47,12 +47,21 @@ public class DialogMaker {
OKButton.setFont(Font.font("Microsoft YaHei", FontWeight.BOLD, 12)); OKButton.setFont(Font.font("Microsoft YaHei", FontWeight.BOLD, 12));
OKButton.setPrefWidth(60); OKButton.setPrefWidth(60);
OKButton.setPrefHeight(30); OKButton.setPrefHeight(30);
OKButton.addEventHandler(ActionEvent.ACTION, e -> dialog.close());
createDialog(title, body, OKButton); createDialog(title, body, OKButton);
if (event != null) {
dialog.setOnDialogClosed(event);
}
dialog.show(); dialog.show();
} }
public void createDialogWithOneBtn(@NamedArg("title") String title, @NamedArg("theBody") Node body) {
createDialogWithOneBtn(title, body, null);
}
//创建有OK和cancel按钮的dialog //创建有OK和cancel按钮的dialog
public void createDialogWithOKAndCancel(@NamedArg("title") String title, @NamedArg("message") String message, @NamedArg("OKEvent") EventHandler<ActionEvent> OKEvent) { public void createDialogWithOKAndCancel(@NamedArg("title") String title, @NamedArg("message") String message, @NamedArg("OKEvent") EventHandler<ActionEvent> OKEvent) {
//dialog.setPrefHeight(rootPane.getPrefHeight()); //dialog.setPrefHeight(rootPane.getPrefHeight());

@ -1,39 +1,38 @@
package me.lensferno.dogename.voice; package me.lensferno.dogename.voice;
import com.goxr3plus.streamplayer.stream.StreamPlayer;
import com.goxr3plus.streamplayer.stream.StreamPlayerException;
import me.lensferno.dogename.configs.VoiceConfig; import me.lensferno.dogename.configs.VoiceConfig;
import me.lensferno.dogename.utils.FilePath; import me.lensferno.dogename.utils.FilePath;
import me.lensferno.dogename.utils.IOUtil; import me.lensferno.dogename.utils.IOUtil;
import me.lensferno.dogename.utils.NetworkUtil; import me.lensferno.dogename.utils.NetworkUtil;
import javax.sound.sampled.*;
import java.io.File; import java.io.File;
import java.net.URLEncoder; import java.net.URLEncoder;
public class VoicePlayer { public class VoicePlayer {
private final String VOICE_API = "https://tsn.baidu.com/text2audio"; private static final String VOICE_API = "https://tsn.baidu.com/text2audio";
String cachePath = FilePath.toSpecificPathForm("caches/voice/"); public static final String cachePath = FilePath.toSpecificPathForm("caches/voice/");
Token token; private final Token token;
StreamPlayer streamPlayer = new StreamPlayer();
private final VoiceConfig voiceConfig; public static VoiceConfig voiceConfig;
public VoicePlayer(Token token, VoiceConfig voiceConfig) { public VoicePlayer(Token token, VoiceConfig voiceConfig) {
this.token = token; this.token = token;
this.voiceConfig = voiceConfig; VoicePlayer.voiceConfig = voiceConfig;
} }
public void playVoice(String name) { public void playVoice(String name) {
String speaker = voiceConfig.getSpeaker(); String speaker = voiceConfig.getSpeakerIdString();
String intonation = String.valueOf(voiceConfig.getIntonation()); String intonation = String.valueOf(voiceConfig.getIntonation());
String speed = String.valueOf(voiceConfig.getSpeed()); String speed = String.valueOf(voiceConfig.getSpeed());
String cacheName = String.format("%s_%s_%s_%s", name, speaker, speed, intonation); String cacheName = String.format("%s_%s_%s_%s", name, speaker, speed, intonation);
File cache = new File(cachePath + cacheName + ".mp3"); File cache = new File(String.format("%s%s.%s", cachePath, cacheName, VoiceConfig.getAudioFileSuffix(voiceConfig.getAudioFormat())));
new Thread(() -> { new Thread(() -> {
if (!cache.exists()) { if (!cache.exists()) {
@ -52,13 +51,14 @@ public class VoicePlayer {
boolean success; boolean success;
try { try {
String requestUrl = String.format( String requestUrl = String.format(
"%s?ctp=1&lan=zh&tok=%s&cuid=%s&spd=%s&pit=%s&per=%s&aue=3&tex=%s", "%s?ctp=1&lan=zh&tok=%s&cuid=%s&spd=%s&pit=%s&per=%s&aue=%s&tex=%s",
VOICE_API, VOICE_API,
token.getAccessToken(), token.getAccessToken(),
NetworkUtil.getMacMD5(), NetworkUtil.getMacMD5(),
speed, speed,
intonation, intonation,
speaker, speaker,
voiceConfig.getAudioFormat(),
URLEncoder.encode(name, "UTF-8") URLEncoder.encode(name, "UTF-8")
); );
@ -92,12 +92,31 @@ public class VoicePlayer {
private void playSound(File file) { private void playSound(File file) {
try { try {
streamPlayer.open(file); AudioInputStream sourceAudioInputStream = AudioSystem.getAudioInputStream(file);
streamPlayer.play();
//streamPlayer.setGain(voiceConfig.getVolume() * 0.1); AudioFormat sourceFormat = sourceAudioInputStream.getFormat();
} catch (StreamPlayerException e) { AudioFormat targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
e.printStackTrace(); sourceFormat.getSampleRate(), 16, sourceFormat.getChannels(),
file.delete(); sourceFormat.getChannels() * 2, sourceFormat.getSampleRate(), false);
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(targetFormat, sourceAudioInputStream);
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, targetFormat, AudioSystem.NOT_SPECIFIED);
SourceDataLine audioLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
audioLine.open(targetFormat);
audioLine.start();
byte[] buffer = new byte[1024];
int length = audioInputStream.read(buffer);
while (length > 0) {
audioLine.write(buffer, 0, length);
length = audioInputStream.read(buffer);
}
audioLine.drain();
audioLine.stop();
audioLine.close();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

@ -1,53 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXTextField?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="143.0" prefWidth="546.0" spacing="5.0" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<padding>
<Insets left="10.0" right="10.0" top="10.0" />
</padding>
<children>
<Label text="您可以自定义百度语音合成的API KEY和SEC KEY,而不必使用作者提供的信息。" wrapText="true">
<font>
<Font name="Microsoft YaHei" size="14.0" />
</font>
</Label>
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0">
<children>
<Label text="API Key:">
<font>
<Font name="Microsoft YaHei" size="14.0" />
</font>
<HBox.margin>
<Insets />
</HBox.margin>
</Label>
<JFXTextField prefHeight="29.0" prefWidth="436.0" promptText="在此输入API Key">
<font>
<Font name="Microsoft YaHei" size="14.0" />
</font>
</JFXTextField>
</children>
</HBox>
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0">
<children>
<Label text="Secret Key:">
<font>
<Font name="Microsoft YaHei" size="14.0" />
</font>
<HBox.margin>
<Insets />
</HBox.margin>
</Label>
<JFXTextField prefHeight="23.0" prefWidth="418.0" promptText="在此输入Secret Key">
<font>
<Font name="Microsoft YaHei" size="14.0" />
</font>
</JFXTextField>
</children>
</HBox>
</children>
</fx:root>

@ -52,7 +52,7 @@
<Font name="Microsoft YaHei UI" size="17.0" /> <Font name="Microsoft YaHei UI" size="17.0" />
</font> </font>
</JFXRadioButton> </JFXRadioButton>
<JFXButton layoutX="698.0" layoutY="502.0" onAction="#showNunberSetting" prefHeight="36.0" prefWidth="92.0" ripplerFill="#00eafff7" text="调整数字"> <JFXButton layoutX="698.0" layoutY="502.0" onAction="#showNumberSetting" prefHeight="36.0" prefWidth="92.0" ripplerFill="#00eafff7" text="调整数字">
<font> <font>
<Font name="Microsoft YaHei UI" size="17.0" /> <Font name="Microsoft YaHei UI" size="17.0" />
</font> </font>

@ -50,7 +50,7 @@
<Font name="Microsoft YaHei" size="17.0" /> <Font name="Microsoft YaHei" size="17.0" />
</font> </font>
</JFXButton> </JFXButton>
<JFXButton buttonType="RAISED" onAction="#copyTo" prefHeight="35.0" prefWidth="176.0" style="-fx-background-color: rgb(255, 255, 255);" text="粘贴剪贴板内容"> <JFXButton buttonType="RAISED" onAction="#paste" prefHeight="35.0" prefWidth="176.0" style="-fx-background-color: rgb(255, 255, 255);" text="粘贴剪贴板内容">
<font> <font>
<Font name="Microsoft YaHei" size="17.0" /> <Font name="Microsoft YaHei" size="17.0" />
</font> </font>

@ -1,61 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXButton?> <?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXComboBox?> <?import com.jfoenix.controls.JFXComboBox?>
<?import com.jfoenix.controls.JFXSlider?> <?import com.jfoenix.controls.JFXRadioButton?>
<?import javafx.geometry.Insets?> <?import com.jfoenix.controls.JFXSlider?>
<?import javafx.scene.control.Label?> <?import javafx.geometry.Insets?>
<?import javafx.scene.layout.*?> <?import javafx.scene.control.Label?>
<?import javafx.scene.text.Font?> <?import javafx.scene.layout.HBox?>
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="176.0" prefWidth="487.0" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> <?import javafx.scene.layout.VBox?>
<children> <?import javafx.scene.text.Font?>
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0">
<children> <fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="197.0" prefWidth="487.0" type="VBox" xmlns="http://javafx.com/javafx/8.0.321" xmlns:fx="http://javafx.com/fxml/1">
<Label text="朗读人:"> <children>
<font> <HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0">
<Font name="Microsoft YaHei" size="16.0" /> <children>
</font> <Label text="朗读人:">
</Label> <font>
<JFXComboBox fx:id="speakerSelectBar" prefHeight="23.0" prefWidth="138.0" style="-fx-font-family: Microsoft YaHei;" /> <Font name="Microsoft YaHei" size="16.0" />
</children> </font>
<padding> </Label>
<Insets left="10.0" /> <JFXComboBox fx:id="speakerSelectBar" prefHeight="23.0" prefWidth="138.0" style="-fx-font-family: Microsoft YaHei;" />
</padding> </children>
</HBox> <padding>
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0"> <Insets left="10.0" />
<children> </padding>
<Label text="语速:"> </HBox>
<font> <HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0">
<Font name="Microsoft YaHei" size="16.0" /> <children>
</font> <Label text="语速:">
</Label> <font>
<JFXSlider fx:id="voiceSpeedBar" majorTickUnit="1.0" max="15.0" minorTickCount="1" prefHeight="14.0" prefWidth="395.0" showTickLabels="true" snapToTicks="true" value="5.0" /> <Font name="Microsoft YaHei" size="16.0" />
</children> </font>
<padding> </Label>
<Insets left="10.0" /> <JFXSlider fx:id="voiceSpeedBar" majorTickUnit="1.0" max="15.0" minorTickCount="1" prefHeight="14.0" prefWidth="395.0" showTickLabels="true" snapToTicks="true" value="5.0" />
</padding> </children>
</HBox> <padding>
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0"> <Insets left="10.0" />
<children> </padding>
<Label text="语调:"> </HBox>
<font> <HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0">
<Font name="Microsoft YaHei" size="16.0" /> <children>
</font> <Label text="语调:">
</Label> <font>
<JFXSlider fx:id="intonationBar" majorTickUnit="1.0" max="15.0" minorTickCount="1" prefHeight="14.0" prefWidth="395.0" showTickLabels="true" snapToTicks="true" value="5.0" /> <Font name="Microsoft YaHei" size="16.0" />
</children> </font>
<padding> </Label>
<Insets left="10.0" /> <JFXSlider fx:id="intonationBar" majorTickUnit="1.0" max="15.0" minorTickCount="1" prefHeight="14.0" prefWidth="395.0" showTickLabels="true" snapToTicks="true" value="5.0" />
</padding> </children>
</HBox> <padding>
<Pane nodeOrientation="LEFT_TO_RIGHT" prefHeight="40.0" prefWidth="487.0"> <Insets left="10.0" />
<children> </padding>
<JFXButton layoutX="14.0" layoutY="9.0" onAction="#showAdvancedVoiceSettings" text="高级设置"> </HBox>
<font> <HBox alignment="CENTER_LEFT" prefHeight="69.0" prefWidth="487.0" spacing="10.0">
<Font name="Microsoft YaHei" size="13.0" /> <children>
</font> <Label text="音频格式:">
</JFXButton> <font>
</children> <Font size="16.0" />
</Pane> </font>
</children> </Label>
</fx:root> <VBox alignment="CENTER_LEFT" spacing="10.0">
<children>
<JFXRadioButton fx:id="wavFormatButton" selected="true" text="WAV(音质好,缓存体积较大(约20kb))" />
<JFXRadioButton fx:id="mp3FormatButton" text="MP3(音质较差,缓存体积小(约3kb))" />
</children>
</VBox>
<JFXButton onAction="#clearCache" prefHeight="34.0" prefWidth="94.0" ripplerFill="#70e9ff" style="-fx-background-color: #2689da;" text="清除缓存" textFill="WHITE">
<font>
<Font size="16.0" />
</font>
</JFXButton>
</children>
<padding>
<Insets left="10.0" />
</padding>
</HBox>
</children>
</fx:root>

Loading…
Cancel
Save