use ssml_parser::elements::*; use ssml_parser::parser::parse_ssml; /// Example SSML taken from Appendix E in the SSML specification which /// can be found [here](https://www.w3.org/TR/speech-synthesis11). All copied /// sections will be marked with: /// /// "Speech Synthesis Markup Language (SSML) Version 1.1" _Copyright © 2010 W3C® (MIT, ERCIM, Keio), /// All Rights Reserved._ #[test] fn simple_example() { let ssml = r#"

You have 4 new messages. The first is from Stephanie Williams and arrived at 3:45pm. The subject is ski trip

"#; let result = parse_ssml(ssml).unwrap(); let whole_sentence = "You have 4 new messages. The first is from Stephanie Williams and arrived at 3:45pm. The subject is ski trip"; assert_eq!(result.get_text().trim(), whole_sentence); let tags = result.tags().collect::>(); assert_eq!(tags.len(), 7); if let ParsedElement::Speak(s) = &tags[0].element { assert_eq!(s.lang.as_ref().unwrap(), "en-US"); assert_eq!(result.get_text_from_span(tags[0]).trim(), whole_sentence); } else { panic!("Tag 0 wrong: {:?}", tags[0]); } if let ParsedElement::Paragraph = &tags[1].element { assert_eq!(result.get_text_from_span(tags[1]).trim(), whole_sentence); } else { panic!("Tag 1 wrong: {:?}", tags[1]); } if let ParsedElement::Sentence = &tags[2].element { assert_eq!( result.get_text_from_span(tags[2]).trim(), "You have 4 new messages." ); } else { panic!("Tag 2 wrong: {:?}", tags[2]); } if let ParsedElement::Sentence = &tags[3].element { assert_eq!( result.get_text_from_span(tags[3]).trim(), "The first is from Stephanie Williams and arrived at 3:45pm." ); } else { panic!("Tag 3 wrong: {:?}", tags[3]); } if let ParsedElement::Break(b) = &tags[4].element { assert_eq!(b.strength, None); assert_eq!(b.time, None); } else { panic!("Tag 4 wrong {:?}", tags[4]); } if let ParsedElement::Sentence = &tags[5].element { assert_eq!( result.get_text_from_span(tags[5]).trim(), "The subject is ski trip" ); } else { panic!("Tag 5 wrong: {:?}", tags[5]); } if let ParsedElement::Prosody(p) = &tags[6].element { assert_eq!(p.pitch, None); assert_eq!(p.contour, None); assert_eq!(p.range, None); assert_eq!( p.rate, Some(RateRange::Percentage(PositiveNumber::RoundNumber(20))) ); assert_eq!(p.duration, None); assert_eq!(p.volume, None); } else { panic!("Tag 6 wrong: {:?}", tags[6]); } // todo!() } #[test] fn break_tag_handling() { let ssml = r#" this is a test for parsing of break tags "#; let result = parse_ssml(ssml).unwrap(); let tags = result.tags().collect::>(); assert_eq!(tags.len(), 6); let tag_no = 0; if let ParsedElement::Break(b) = &tags[tag_no].element { assert_eq!(b.time.unwrap(), TimeDesignation::Seconds(2.0)); assert_eq!(b.strength.unwrap(), Strength::Medium); } else { panic!("Tag {:?} wrong {:?}", tag_no, tags[tag_no]); } let tag_no = 1; if let ParsedElement::Break(b) = &tags[tag_no].element { assert_eq!(b.time.unwrap(), TimeDesignation::Seconds(0.5)); assert_eq!(b.strength.unwrap(), Strength::Strong); } else { panic!("Tag {:?} wrong {:?}", tag_no, tags[tag_no]); } let tag_no = 2; if let ParsedElement::Break(b) = &tags[tag_no].element { assert_eq!(b.time.unwrap(), TimeDesignation::Seconds(0.5)); assert_eq!(b.strength.unwrap(), Strength::Weak); } else { panic!("Tag {:?} wrong {:?}", tag_no, tags[tag_no]); } let tag_no = 3; if let ParsedElement::Break(b) = &tags[tag_no].element { assert_eq!(b.time.unwrap(), TimeDesignation::Milliseconds(200.0)); assert_eq!(b.strength.unwrap(), Strength::ExtraStrong); } else { panic!("Tag {:?} wrong {:?}", tag_no, tags[tag_no]); } let tag_no = 4; if let ParsedElement::Break(b) = &tags[tag_no].element { assert_eq!(b.time.unwrap(), TimeDesignation::Milliseconds(200.1)); assert_eq!(b.strength.unwrap(), Strength::Medium); } else { panic!("Tag {:?} wrong {:?}", tag_no, tags[tag_no]); } let tag_no = 5; if let ParsedElement::Break(b) = &tags[tag_no].element { assert_eq!(b.time.unwrap(), TimeDesignation::Milliseconds(412200.123)); assert_eq!(b.strength.unwrap(), Strength::ExtraWeak); } else { panic!("Tag {:?} wrong {:?}", tag_no, tags[tag_no]); } } /// Example SSML taken from Appendix E in the SSML specification which /// can be found [here](https://www.w3.org/TR/speech-synthesis11). All copied /// sections will be marked with: /// /// "Speech Synthesis Markup Language (SSML) Version 1.1" _Copyright © 2010 W3C® (MIT, ERCIM, Keio), /// All Rights Reserved._ #[test] fn audio_example() { let ssml = r#"

Today we preview the latest romantic music from Example. Hear what the Software Reviews said about Example's newest hit.

He sings about issues that touch us all.

Here's a sample.

"#; let result = parse_ssml(ssml).unwrap(); assert_eq!(result.get_text().trim(), "Today we preview the latest romantic music from Example. Hear what the Software Reviews said about Example's newest hit. He sings about issues that touch us all. Here's a sample. Would you like to buy it?"); //todo!() } /// Example SSML taken from Appendix E in the SSML specification which /// can be found [here](https://www.w3.org/TR/speech-synthesis11). All copied /// sections will be marked with: /// /// "Speech Synthesis Markup Language (SSML) Version 1.1" _Copyright © 2010 W3C® (MIT, ERCIM, Keio), /// All Rights Reserved._ #[test] fn mixed_language_example() { let ssml = r#" The title of the movie is: "La vita è bella" (Life is beautiful), which is directed by Roberto Benigni. "#; let result = parse_ssml(ssml).unwrap(); assert_eq!( result.get_text().trim(), r#"The title of the movie is: "La vita è bella" (Life is beautiful), which is directed by Roberto Benigni."# ); } /// Example SSML taken from Appendix E in the SSML specification which /// can be found [here](https://www.w3.org/TR/speech-synthesis11). All copied /// sections will be marked with: /// /// "Speech Synthesis Markup Language (SSML) Version 1.1" _Copyright © 2010 W3C® (MIT, ERCIM, Keio), /// All Rights Reserved._ #[test] fn ipa_support() { let ssml = r#" The title of the movie is: La vita è bella (Life is beautiful), which is directed by Roberto Benigni "#; let result = parse_ssml(ssml).unwrap(); assert_eq!( result.get_text().trim(), r#"The title of the movie is: La vita è bella (Life is beautiful), which is directed by Roberto Benigni"# ); let phonemes = vec![ (Some(PhonemeAlphabet::Ipa), "ˈlɑ ˈviːɾə ˈʔeɪ ˈbɛlə"), (Some(PhonemeAlphabet::Ipa), "ɹəˈbɛːɹɾoʊ bɛˈniːnji"), ]; let mut index = 0; let tags: Vec = { use SsmlElement::*; vec![Speak, Phoneme, Phoneme] }; for (parsed, expected) in result.tags().zip(tags.iter()) { let actual_tag = SsmlElement::from(&parsed.element); assert_eq!(actual_tag, *expected); if let ParsedElement::Phoneme(p) = &parsed.element { assert_eq!(p.alphabet, phonemes[index].0); assert_eq!(p.ph, phonemes[index].1); index += 1; } } } #[test] fn google_tts_example() { let ssml = r#" Here are SSML samples. I can pause . I can play a sound . I can speak in cardinals. Your number is 10. Or I can speak in ordinals. You are 10 in line. Or I can even speak in digits. The digits for ten are 10. I can also substitute phrases, like the W3C. Finally, I can speak a paragraph with two sentences.

This is sentence one.This is sentence two.

"#; let result = parse_ssml(ssml).unwrap(); assert_eq!( result.get_text().trim(), r#"Here are SSML samples. I can pause . I can play a sound didn't get your MP3 audio file. I can speak in cardinals. Your number is 10. Or I can speak in ordinals. You are 10 in line. Or I can even speak in digits. The digits for ten are 10. I can also substitute phrases, like the W3C. Finally, I can speak a paragraph with two sentences. This is sentence one. This is sentence two."# ); // todo!(); } #[test] fn microsoft_custom_tags() { // I've had to modify the Microsoft example as: // 1. It was invalid XML (closing an already closed tag) // 2. Invalid parameter values that don't match the standard let ssml = r#"

"#; let result = parse_ssml(ssml).unwrap(); assert_eq!(result.get_text().trim(), ""); let tags: Vec = { use SsmlElement::*; vec![ Speak, Custom("mstts:backgroundaudio".to_string()), Voice, Audio, Custom("bookmark".to_string()), Break, Emphasis, Lang, Lexicon, Custom("math".to_string()), Custom("mstts:express-as".to_string()), Custom("mstts:silence".to_string()), Custom("mstts:viseme".to_string()), Paragraph, Phoneme, Prosody, Sentence, SayAs, Sub, ] }; for (parsed, expected) in result.tags().zip(tags.iter()) { let actual_tag = SsmlElement::from(&parsed.element); assert_eq!(actual_tag, *expected); if let ParsedElement::Break(b) = &parsed.element { assert_eq!(b.strength, Some(Strength::Medium)); assert_eq!(b.time, Some(TimeDesignation::Seconds(5.0))); } else if let ParsedElement::Phoneme(p) = &parsed.element { assert_eq!( p.alphabet.as_ref().unwrap(), &PhonemeAlphabet::Other("string".to_string()) ); assert_eq!(p.ph, "string"); } } }