mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-26 02:59:37 +00:00
Read CPU Arpabet dictionary
This commit is contained in:
@@ -35471,7 +35471,7 @@ DZIUBA JH IY0 UW1 B AH0
|
||||
DZIUK JH IY0 UW1 K
|
||||
DZOKHAR JH OW2 K AA1 R
|
||||
D_C D IY1 S IY1
|
||||
DÉJÀ D EY2 JH AA1
|
||||
DEJA D EY2 JH AA1
|
||||
E IY1
|
||||
E'S IY1 Z
|
||||
E-MAIL IY1 M EY2 L
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2016 Brandon Thomas <bt@brand.io, echelon@gmail.com>
|
||||
|
||||
use error::Error;
|
||||
use std::collections::HashMap;
|
||||
use regex::Regex;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::io::BufRead;
|
||||
use std::io::Read;
|
||||
|
||||
pub type Word = String;
|
||||
pub type Phoneme = String;
|
||||
pub type Polyphone = Vec<Phoneme>;
|
||||
|
||||
pub struct ArpabetDictionary {
|
||||
/// A map of lowercase words to polyphone breakdown (phones are uppercase).
|
||||
/// eg. 'jungle' -> [JH, AH1, NG, G, AH0, L]
|
||||
dictionary: HashMap<Word, Polyphone>
|
||||
}
|
||||
|
||||
impl ArpabetDictionary {
|
||||
/// Read CMU's Arpabet Dictionary.
|
||||
/// See http://www.speech.cs.cmu.edu/cgi-bin/cmudict
|
||||
pub fn load_from_file(filename: &str) -> Result<ArpabetDictionary, Error> {
|
||||
let mut f = try!(File::open(filename));
|
||||
let mut reader = BufReader::new(f);
|
||||
|
||||
let mut map = HashMap::new();
|
||||
let mut buffer = String::new();
|
||||
|
||||
// Format resembles the following,
|
||||
// ABBREVIATE AH0 B R IY1 V IY0 EY2 T
|
||||
let re = Regex::new(r"^(\w+)\s+(.*)\n$").unwrap();
|
||||
|
||||
while try!(reader.read_line(&mut buffer)) > 0 {
|
||||
match re.captures(&buffer) {
|
||||
None => {},
|
||||
Some(caps) => {
|
||||
let word_match = caps.at(1);
|
||||
let phonemes_match = caps.at(2);
|
||||
|
||||
if word_match.is_some() && phonemes_match.is_some() {
|
||||
let word = word_match.unwrap().to_lowercase();
|
||||
let split = phonemes_match.unwrap().split(" ");
|
||||
let v1 = split.collect::<Vec<&str>>();
|
||||
let v2 = v1.iter().map(|s| s.to_string()).collect::<Vec<String>>();
|
||||
map.insert(word, v2);
|
||||
}
|
||||
},
|
||||
}
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
if map.is_empty() {
|
||||
Err(Error::EmptyFile)
|
||||
} else {
|
||||
Ok(ArpabetDictionary { dictionary: map })
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a polyphone from the dictionary.
|
||||
pub fn get(&self, word: &str) -> Option<Polyphone> {
|
||||
self.dictionary.get(word).and_then(|p| {
|
||||
Some(p.iter().map(|s| s.to_string()).collect::<Vec<String>>())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2016 Brandon Thomas <bt@brand.io, echelon@gmail.com>
|
||||
|
||||
use std::error;
|
||||
use std::io;
|
||||
use std::fmt;
|
||||
use std::convert::From;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// The file was empty or did not have parsable contents.
|
||||
EmptyFile,
|
||||
|
||||
/// Wraps an IoError.
|
||||
IoError { cause: io::Error },
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(error: io::Error) -> Error {
|
||||
Error::IoError { cause: error }
|
||||
}
|
||||
}
|
||||
|
||||
+22
-7
@@ -6,6 +6,7 @@ extern crate hound;
|
||||
extern crate iron;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate regex;
|
||||
extern crate resolve;
|
||||
extern crate router;
|
||||
extern crate rustc_serialize;
|
||||
@@ -13,26 +14,28 @@ extern crate time;
|
||||
extern crate toml;
|
||||
extern crate urlencoded;
|
||||
|
||||
pub mod arpabet;
|
||||
pub mod atom;
|
||||
pub mod error;
|
||||
pub mod config;
|
||||
pub mod dictionary;
|
||||
pub mod handlers;
|
||||
pub mod logger;
|
||||
pub mod words;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use arpabet::ArpabetDictionary;
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use iron::prelude::*;
|
||||
use router::Router;
|
||||
use resolve::hostname;
|
||||
use config::Config;
|
||||
|
||||
use dictionary::VocabularyLibrary;
|
||||
use handlers::audio_synth_handler::AudioSynthHandler;
|
||||
use handlers::error_filter::ErrorFilter;
|
||||
use handlers::file_server_handler::FileServerHandler;
|
||||
use handlers::vocab_list_handler::VocabListHandler;
|
||||
use iron::prelude::*;
|
||||
use logger::SimpleLogger;
|
||||
use dictionary::VocabularyLibrary;
|
||||
use resolve::hostname;
|
||||
use router::Router;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn main() {
|
||||
SimpleLogger::init().unwrap();
|
||||
@@ -56,6 +59,8 @@ fn main() {
|
||||
|
||||
get_hostname();
|
||||
|
||||
read_arpabet();
|
||||
|
||||
start_server(&config, port);
|
||||
}
|
||||
|
||||
@@ -105,3 +110,13 @@ fn get_hostname() {
|
||||
let err = unsafe {gethostname (vec::raw::to_mut_ptr(buf) as *mut i8, len as u64)};
|
||||
if err != 0 { println("oops, gethostname failed"); return; }*/
|
||||
}
|
||||
|
||||
fn read_arpabet() {
|
||||
// TODO: Configurable path.
|
||||
let dict = ArpabetDictionary::load_from_file("./dictionary/cmudict-0.7b").unwrap();
|
||||
|
||||
let result = dict.get("nintendo");
|
||||
|
||||
println!("Result: {:?}", result);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user