mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 17:58:55 +00:00
Word audio spacing params + handler cleanup
This commit is contained in:
1 parent
4ce9909b4e
commit
7e302e7665
6 files changed
+114
-75
No files matched your search
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2015 Brandon Thomas <bt@brand.io>
|
||||
// TODO: This looks really bad now. Needs cleanup.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use config::Config;
|
||||
use crypto::digest::Digest;
|
||||
use crypto::sha1::Sha1;
|
||||
@@ -43,6 +44,10 @@ const VOLUME_PARAM : &'static str = "vol";
|
||||
const MONOPHONE_PADDING_START_PARAM : &'static str = "mps";
|
||||
const MONOPHONE_PADDING_END_PARAM : &'static str = "mpe";
|
||||
const POLYPHONE_PADDING_END_PARAM : &'static str = "ppe";
|
||||
const WORD_PADDING_START_PARAM : &'static str = "wps";
|
||||
const WORD_PADDING_END_PARAM : &'static str = "wpe";
|
||||
|
||||
type QueryParams = HashMap<String, Vec<String>>;
|
||||
|
||||
/// Represents a request to this endpoint.
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -82,6 +87,12 @@ struct SpeakRequest {
|
||||
|
||||
/** Padding after a polyphone. */
|
||||
pub polyphone_padding_end: Option<u16>,
|
||||
|
||||
/// Silent padding before a word (not one constructed from phones).
|
||||
pub word_padding_start: Option<u16>,
|
||||
|
||||
/// Silent padding after a word (not one constructed from phones).
|
||||
pub word_padding_end: Option<u16>,
|
||||
}
|
||||
|
||||
enum SpeakerRequestError {
|
||||
@@ -249,68 +260,11 @@ impl SpeakRequest {
|
||||
},
|
||||
};
|
||||
|
||||
let mps : Option<u16> = match map.get(MONOPHONE_PADDING_START_PARAM) {
|
||||
None => { None },
|
||||
Some(list) => {
|
||||
match list.get(0) {
|
||||
None => { None },
|
||||
Some(s) => {
|
||||
match s.trim().parse::<u16>() {
|
||||
Err(_) => None,
|
||||
Ok(i) => {
|
||||
if i == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let mpe : Option<u16> = match map.get(MONOPHONE_PADDING_END_PARAM) {
|
||||
None => { None },
|
||||
Some(list) => {
|
||||
match list.get(0) {
|
||||
None => { None },
|
||||
Some(s) => {
|
||||
match s.trim().parse::<u16>() {
|
||||
Err(_) => None,
|
||||
Ok(i) => {
|
||||
if i == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let ppe : Option<u16> = match map.get(POLYPHONE_PADDING_END_PARAM) {
|
||||
None => { None },
|
||||
Some(list) => {
|
||||
match list.get(0) {
|
||||
None => { None },
|
||||
Some(s) => {
|
||||
match s.trim().parse::<u16>() {
|
||||
Err(_) => None,
|
||||
Ok(i) => {
|
||||
if i == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
let mps = get_u16(map, MONOPHONE_PADDING_START_PARAM);
|
||||
let mpe = get_u16(map, MONOPHONE_PADDING_END_PARAM);
|
||||
let ppe = get_u16(map, POLYPHONE_PADDING_END_PARAM);
|
||||
let wps = get_u16(map, WORD_PADDING_START_PARAM);
|
||||
let wpe = get_u16(map, WORD_PADDING_END_PARAM);
|
||||
|
||||
Ok(SpeakRequest {
|
||||
sentence: sen,
|
||||
@@ -325,6 +279,8 @@ impl SpeakRequest {
|
||||
monophone_padding_start: mps,
|
||||
monophone_padding_end: mpe,
|
||||
polyphone_padding_end: ppe,
|
||||
word_padding_start: wps,
|
||||
word_padding_end: wpe,
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -413,7 +369,9 @@ impl AudioSynthHandler {
|
||||
request.speed,
|
||||
request.monophone_padding_start,
|
||||
request.monophone_padding_end,
|
||||
request.polyphone_padding_end);
|
||||
request.polyphone_padding_end,
|
||||
request.word_padding_start,
|
||||
request.word_padding_end);
|
||||
match generated {
|
||||
Err(e) => {
|
||||
println!("Error synthesizing: {:?}", e);
|
||||
@@ -475,3 +433,14 @@ impl AudioSynthHandler {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Parse an optional u16 out of query parameters. */
|
||||
fn get_u16(params: &QueryParams, param_name: &str) -> Option<u16> {
|
||||
params.get(param_name)
|
||||
.and_then(|v| v.get(0))
|
||||
.map(|s| s.trim())
|
||||
.map(|s| s.parse::<u16>())
|
||||
.and_then(|res| res.ok())
|
||||
.and_then(|d| if d == 0 { None } else { Some(d) } )
|
||||
}
|
||||
|
||||
+27
-7
@@ -57,7 +57,9 @@ impl Synthesizer {
|
||||
speed: Option<f32>,
|
||||
monophone_padding_start: Option<u16>,
|
||||
monophone_padding_end: Option<u16>,
|
||||
polyphone_padding_end: Option<u16>)
|
||||
polyphone_padding_end: Option<u16>,
|
||||
word_padding_start: Option<u16>,
|
||||
word_padding_end: Option<u16>)
|
||||
-> Result<WavBytes, SynthError> {
|
||||
|
||||
let mut words = split_sentence(sentence);
|
||||
@@ -83,7 +85,9 @@ impl Synthesizer {
|
||||
if use_words {
|
||||
word_added = self.concatenate_word(&mut concatenated_waveform,
|
||||
speaker,
|
||||
word);
|
||||
word,
|
||||
word_padding_start,
|
||||
word_padding_end);
|
||||
}
|
||||
|
||||
if !word_added && use_n_phones {
|
||||
@@ -131,17 +135,33 @@ impl Synthesizer {
|
||||
|
||||
/// Concatenate a word to the waveform we're building. Returns
|
||||
/// whether or not the word was successfully found and concatenated.
|
||||
fn concatenate_word(&self, concatenated_waveform: &mut Vec<i16>,
|
||||
speaker: &str, word: &str) -> bool {
|
||||
fn concatenate_word(&self,
|
||||
concatenated_waveform: &mut Vec<i16>,
|
||||
speaker: &str,
|
||||
word: &str,
|
||||
word_padding_start: Option<u16>,
|
||||
word_padding_end: Option<u16>) -> bool {
|
||||
match self.audiobank.get_word(speaker, word) {
|
||||
None => {
|
||||
// The word does not exist in the database.
|
||||
false
|
||||
},
|
||||
Some(waveform_data) => {
|
||||
// The word exists in the database.
|
||||
if word_padding_start.is_some() {
|
||||
let pause = generate_pause(word_padding_start.unwrap());
|
||||
concatenated_waveform.extend(pause);
|
||||
}
|
||||
|
||||
concatenated_waveform.extend(waveform_data);
|
||||
|
||||
if word_padding_end.is_some() {
|
||||
let pause = generate_pause(word_padding_end.unwrap());
|
||||
concatenated_waveform.extend(pause);
|
||||
}
|
||||
|
||||
true
|
||||
},
|
||||
None => {
|
||||
false
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
mps = $('input#monophone_padding_start').val(),
|
||||
mpe = $('input#monophone_padding_end').val(),
|
||||
ppe = $('input#polyphone_padding_end').val(),
|
||||
wps = $('input#word_padding_start').val(),
|
||||
wpe = $('input#word_padding_end').val(),
|
||||
query = encodeURIComponent(sentence),
|
||||
url = '/speak?v=' + speaker
|
||||
+ '&s=' + query
|
||||
@@ -71,6 +73,8 @@
|
||||
+ '&mps=' + mps
|
||||
+ '&mpe=' + mpe
|
||||
+ '&ppe=' + ppe
|
||||
+ '&wps=' + wps
|
||||
+ '&wpe=' + wpe
|
||||
+ '&up=' + up
|
||||
+ '&ud=' + ud
|
||||
+ '&un=' + un
|
||||
@@ -90,7 +94,9 @@
|
||||
ue,
|
||||
mps,
|
||||
mpe,
|
||||
ppe);
|
||||
ppe,
|
||||
wps,
|
||||
wpe);
|
||||
|
||||
Sound.play(url);
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
mps = Url.getMonophonePaddingStart() || 0,
|
||||
mpe = Url.getMonophonePaddingEnd() || 0,
|
||||
ppe = Url.getPolyphonePaddingEnd() || 600,
|
||||
wps = Url.getWordPaddingStart() || 600,
|
||||
wpe = Url.getWordPaddingEnd() || 600,
|
||||
urlPreviousState = false;
|
||||
|
||||
if (usePhonemes === null) usePhonemes = true;
|
||||
@@ -55,6 +57,8 @@
|
||||
$('input#monophone_padding_start').val(mps);
|
||||
$('input#monophone_padding_end').val(mpe);
|
||||
$('input#polyphone_padding_end').val(ppe);
|
||||
$('input#word_padding_start').val(wps);
|
||||
$('input#word_padding_end').val(wpe);
|
||||
|
||||
Library.load(function(library) { Ui.libraryLoadCallback(library); });
|
||||
Sound.install();
|
||||
|
||||
+32
-3
@@ -34,6 +34,8 @@
|
||||
_MONOPHONE_PADDING_START_KEY: 'mps',
|
||||
_MONOPHONE_PADDING_END_KEY: 'mpe',
|
||||
_POLYPHONE_PADDING_END_KEY: 'ppe',
|
||||
_WORD_PADDING_START_KEY: 'wps',
|
||||
_WORD_PADDING_END_KEY: 'wpe',
|
||||
|
||||
/** Get the sentence from the `window.location`. */
|
||||
getSentence: function() {
|
||||
@@ -157,6 +159,25 @@
|
||||
}
|
||||
},
|
||||
|
||||
getWordPaddingStart: function() {
|
||||
var state = this.parseState(window.location);
|
||||
if (!state || !(this._WORD_PADDING_START_KEY in state)) {
|
||||
return null;
|
||||
} else {
|
||||
return state[this._WORD_PADDING_START_KEY];
|
||||
}
|
||||
},
|
||||
|
||||
getWordPaddingEnd: function() {
|
||||
var state = this.parseState(window.location);
|
||||
if (!state || !(this._WORD_PADDING_END_KEY in state)) {
|
||||
return null;
|
||||
} else {
|
||||
return state[this._WORD_PADDING_END_KEY];
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// TODO: Independent functions to set both speaker and sentence separately.
|
||||
/** Set the `window.history` speaker, sentence, phoneme use, and word use. */
|
||||
setState: function(speaker,
|
||||
@@ -170,7 +191,9 @@
|
||||
useEnds,
|
||||
monophonePaddingStart,
|
||||
monophonePaddingEnd,
|
||||
polyphonePaddingEnd) {
|
||||
polyphonePaddingEnd,
|
||||
wordPaddingStart,
|
||||
wordPaddingEnd) {
|
||||
|
||||
var urlHash = this.fromParams(speaker,
|
||||
rawSentence,
|
||||
@@ -183,7 +206,9 @@
|
||||
useEnds,
|
||||
monophonePaddingStart,
|
||||
monophonePaddingEnd,
|
||||
polyphonePaddingEnd);
|
||||
polyphonePaddingEnd,
|
||||
wordPaddingStart,
|
||||
wordPaddingEnd);
|
||||
|
||||
console.log('set state, urlhash = ', urlHash);
|
||||
window.history.replaceState(null, null, urlHash);
|
||||
@@ -201,7 +226,9 @@
|
||||
useEnds,
|
||||
monophonePaddingStart,
|
||||
monophonePaddingEnd,
|
||||
polyphonePaddingEnd) {
|
||||
polyphonePaddingEnd,
|
||||
wordPaddingStart,
|
||||
wordPaddingEnd) {
|
||||
|
||||
var cleanedSentence = SentenceHelper.cleanSentence(rawSentence),
|
||||
cleanedSpeaker = speaker, // TODO: Check against speakers.
|
||||
@@ -222,6 +249,8 @@
|
||||
state[this._MONOPHONE_PADDING_START_KEY] = monophonePaddingStart;
|
||||
state[this._MONOPHONE_PADDING_END_KEY] = monophonePaddingEnd;
|
||||
state[this._POLYPHONE_PADDING_END_KEY] = polyphonePaddingEnd;
|
||||
state[this._WORD_PADDING_START_KEY] = wordPaddingStart;
|
||||
state[this._WORD_PADDING_END_KEY] = wordPaddingEnd;
|
||||
|
||||
json = JSON.stringify(state);
|
||||
|
||||
|
||||
+12
-1
@@ -51,7 +51,8 @@
|
||||
<div>
|
||||
<input type="checkbox" id="use_ends" name="use_ends"
|
||||
checked="checked">
|
||||
<label for="use_ends">Use ends of n-phones (new algorithm)</label>
|
||||
<label for="use_ends">
|
||||
Use ends of n-phones (new algorithm)</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -75,6 +76,16 @@
|
||||
<label for="polyphone_padding_end">
|
||||
Polyphone Padding End</label>
|
||||
</div>
|
||||
<div>
|
||||
<input id="word_padding_start" value="">
|
||||
<label for="word_padding_start">
|
||||
Word Padding Start</label>
|
||||
</div>
|
||||
<div>
|
||||
<input id="word_padding_end" value="">
|
||||
<label for="word_padding_end">
|
||||
Word Padding End</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
Reference in new issue
Block a user