Permalink
Browse files

Merge branch 'release/0.1.5'

  • Loading branch information...
benlangfeld committed Aug 25, 2011
2 parents 5e6029f + 31a11ac commit 66c0b3c26f5736bc92611ef9f98a4cb082b18195
View
@@ -1,3 +1,6 @@
+# 0.1.5
+ Feature: Now added support for SSML <audio/>
+
# 0.1.4
Bugfix: Speak#+ now returns a brand new Speak rather than modifying the original object
Bugfix: Speak#+ now re-sets the namespace on child elements to ensure no default namespace prefix is added
View
@@ -54,6 +54,7 @@ Check out the [YARD documentation](http://rdoc.info/github/benlangfeld/ruby_spee
* `<emphasis/>`
* `<say-as/>`
* `<break/>`
+* `<audio/>`
## TODO:
### SSML
@@ -65,7 +66,6 @@ Check out the [YARD documentation](http://rdoc.info/github/benlangfeld/ruby_spee
* `<meta/>` and `<metadata/>`
#### Misc
-* `<audio/>`
* `<mark/>`
* `<desc/>`
View
@@ -2,6 +2,7 @@ module RubySpeech
module SSML
extend ActiveSupport::Autoload
+ autoload :Audio
autoload :Break
autoload :Element
autoload :Emphasis
@@ -0,0 +1,56 @@
+module RubySpeech
+ module SSML
+ ##
+ # The audio element supports the insertion of recorded audio files (see Appendix A for required formats) and the insertion of other audio formats in conjunction with synthesized speech output. The audio element may be empty. If the audio element is not empty then the contents should be the marked-up text to be spoken if the audio document is not available. The alternate content may include text, speech markup, desc elements, or other audio elements. The alternate content may also be used when rendering the document to non-audible output and for accessibility (see the desc element). The required attribute is src, which is the URI of a document with an appropriate MIME type.
+ #
+ # An audio element is successfully rendered:
+ # * If the referenced audio source is played, or
+ # * If the synthesis processor is unable to execute #1 but the alternative content is successfully rendered, or
+ # * If the processor can detect that text-only output is required and the alternative content is successfully rendered.
+ #
+ # Deciding which conditions result in the alternative content being rendered is processor-dependent. If the audio element is not successfully rendered, a synthesis processor should continue processing and should notify the hosting environment. The processor may determine after beginning playback of an audio source that the audio cannot be played in its entirety. For example, encoding problems, network disruptions, etc. may occur. The processor may designate this either as successful or unsuccessful rendering, but it must document this behavior.
+ #
+ # http://www.w3.org/TR/speech-synthesis/#S3.3.1
+ #
+ class Audio < Element
+
+ VALID_CHILD_TYPES = [String, Audio, Break, Emphasis, Prosody, SayAs, Voice].freeze
+
+ ##
+ # Create a new SSML audio element
+ #
+ # @param [Hash] atts Key-value pairs of options mapping to setter methods
+ #
+ # @return [Break] an element for use in an SSML document
+ #
+ def self.new(atts = {}, &block)
+ super 'audio', atts, &block
+ end
+
+ ##
+ # The URI of a document with an appropriate MIME type
+ #
+ # @return [String]
+ #
+ def src
+ read_attr :src
+ end
+
+ ##
+ # @param [String] the source. Must be a valid URI
+ #
+ def src=(s)
+ write_attr :src, s
+ end
+
+ def <<(arg)
+ raise InvalidChildError, "An Audio can only accept String, Audio, Break, Emphasis, Mark, P, Phoneme, Prosody, SayAs, Sub, S, Voice as children" unless VALID_CHILD_TYPES.include? arg.class
+ super
+ end
+
+ def eql?(o)
+ super o, :src
+ end
+ end # Audio
+ end # SSML
+end # RubySpeech
@@ -8,7 +8,7 @@ module SSML
class Emphasis < Element
VALID_LEVELS = [:strong, :moderate, :none, :reduced].freeze
- VALID_CHILD_TYPES = [String, Break, Emphasis, Prosody, SayAs, Voice].freeze
+ VALID_CHILD_TYPES = [String, Audio, Break, Emphasis, Prosody, SayAs, Voice].freeze
##
# Create a new SSML emphasis element
@@ -16,7 +16,7 @@ class Prosody < Element
VALID_PITCHES = [:'x-low', :low, :medium, :high, :'x-high', :default].freeze
VALID_VOLUMES = [:silent, :'x-soft', :soft, :medium, :loud, :'x-loud', :default].freeze
VALID_RATES = [:'x-slow', :slow, :medium, :fast, :'x-fast', :default].freeze
- VALID_CHILD_TYPES = [String, Break, Emphasis, Prosody, SayAs, Voice].freeze
+ VALID_CHILD_TYPES = [String, Audio, Break, Emphasis, Prosody, SayAs, Voice].freeze
##
# Create a new SSML prosody element
@@ -8,7 +8,7 @@ module SSML
class Speak < Element
include XML::Language
- VALID_CHILD_TYPES = [String, Break, Emphasis, Prosody, SayAs, Voice].freeze
+ VALID_CHILD_TYPES = [String, Audio, Break, Emphasis, Prosody, SayAs, Voice].freeze
##
# Create a new SSML speak root element
@@ -9,7 +9,7 @@ class Voice < Element
include XML::Language
VALID_GENDERS = [:male, :female, :neutral].freeze
- VALID_CHILD_TYPES = [String, Break, Emphasis, Prosody, SayAs, Voice].freeze
+ VALID_CHILD_TYPES = [String, Audio,Break, Emphasis, Prosody, SayAs, Voice].freeze
##
# Create a new SSML voice element
@@ -1,3 +1,3 @@
module RubySpeech
- VERSION = "0.1.4"
+ VERSION = "0.1.5"
end
@@ -0,0 +1,107 @@
+require 'spec_helper'
+
+module RubySpeech
+ module SSML
+ describe Audio do
+ its(:name) { should == 'audio' }
+
+ describe "setting options in initializers" do
+ subject { Audio.new :src => 'http://whatever.you-say-boss.com', :content => 'Hello' }
+
+ its(:src) { should == 'http://whatever.you-say-boss.com' }
+ its(:content) { should == 'Hello' }
+ end
+
+ describe "#src" do
+ before { subject.src = 'http://whatever.you-say-boss.com' }
+
+ its(:src) { should == 'http://whatever.you-say-boss.com' }
+ end
+
+ describe "#content" do
+ context "with a valid value" do
+ before { subject.content = "Hello" }
+
+ its(:content) { should == "Hello" }
+ end
+ end
+
+ describe "<<" do
+ it "should accept String" do
+ lambda { subject << 'anything' }.should_not raise_error
+ end
+
+ it "should accept Audio" do
+ lambda { subject << Audio.new }.should_not raise_error
+ end
+
+ it "should accept Break" do
+ lambda { subject << Break.new }.should_not raise_error
+ end
+
+ it "should accept Emphasis" do
+ lambda { subject << Emphasis.new }.should_not raise_error
+ end
+
+ it "should accept Mark" do
+ pending
+ lambda { subject << Mark.new }.should_not raise_error
+ end
+
+ it "should accept P" do
+ pending
+ lambda { subject << P.new }.should_not raise_error
+ end
+
+ it "should accept Phoneme" do
+ pending
+ lambda { subject << Phoneme.new }.should_not raise_error
+ end
+
+ it "should accept Prosody" do
+ lambda { subject << Prosody.new }.should_not raise_error
+ end
+
+ it "should accept SayAs" do
+ lambda { subject << SayAs.new(:interpret_as => :foo) }.should_not raise_error
+ end
+
+ it "should accept Sub" do
+ pending
+ lambda { subject << Sub.new }.should_not raise_error
+ end
+
+ it "should accept S" do
+ pending
+ lambda { subject << S.new }.should_not raise_error
+ end
+
+ it "should accept Voice" do
+ lambda { subject << Voice.new }.should_not raise_error
+ end
+
+ it "should raise InvalidChildError with non-acceptable objects" do
+ lambda { subject << 1 }.should raise_error(InvalidChildError, "An Audio can only accept String, Audio, Break, Emphasis, Mark, P, Phoneme, Prosody, SayAs, Sub, S, Voice as children")
+ end
+ end
+
+ describe "comparing objects" do
+ it "should be equal if the content, and src are the same" do
+ Audio.new(:src => "one", :content => "Hello there").should == Audio.new(:src => "one", :content => "Hello there")
+ end
+
+ describe "when the content is different" do
+ it "should not be equal" do
+ Audio.new(:content => "Hello").should_not == Audio.new(:content => "Hello there")
+ end
+ end
+
+ describe "when the src is different" do
+ it "should not be equal" do
+ Audio.new(:src => 'one').should_not == Audio.new(:src => 'two')
+ end
+ end
+ end
+ end # Break
+ end # SSML
+end # RubySpeech
@@ -52,7 +52,6 @@ module SSML
end
it "should accept Audio" do
- pending
lambda { subject << Audio.new }.should_not raise_error
end
@@ -238,7 +238,6 @@ module SSML
end
it "should accept Audio" do
- pending
lambda { subject << Audio.new }.should_not raise_error
end
@@ -65,7 +65,6 @@ module SSML
end
it "should accept Audio" do
- pending
lambda { subject << Audio.new }.should_not raise_error
end
@@ -130,7 +130,6 @@ module SSML
end
it "should accept Audio" do
- pending
lambda { subject << Audio.new }.should_not raise_error
end
@@ -72,9 +72,19 @@ module RubySpeech
doc = RubySpeech::SSML.draw do
string "Hello world."
ssml_break
+ audio :src => "hello" do
+ string "HELLO?"
+ ssml_break
+ audio :src => "hello"
+ emphasis
+ prosody
+ say_as 'date'
+ voice
+ end
emphasis do
string "HELLO?"
ssml_break
+ audio :src => "hello"
emphasis
prosody
say_as 'date'
@@ -83,6 +93,7 @@ module RubySpeech
prosody :rate => :slow do
string "H...E...L...L...O?"
ssml_break
+ audio :src => "hello"
emphasis
prosody
say_as 'date'
@@ -97,6 +108,7 @@ module RubySpeech
"01/02/1960"
end
ssml_break
+ audio :src => "hello"
emphasis do
"I'm so old"
end
@@ -110,15 +122,25 @@ module RubySpeech
end
expected_doc = SSML::Speak.new(:content => "Hello world.")
expected_doc << SSML::Break.new
+ audio = SSML::Audio.new(:src => "hello", :content => "HELLO?")
+ audio << SSML::Break.new
+ audio << SSML::Audio.new(:src => "hello")
+ audio << SSML::Emphasis.new
+ audio << SSML::Prosody.new
+ audio << SSML::SayAs.new('date')
+ audio << SSML::Voice.new
+ expected_doc << audio
emphasis = SSML::Emphasis.new(:content => "HELLO?")
emphasis << SSML::Break.new
+ emphasis << SSML::Audio.new(:src => "hello")
emphasis << SSML::Emphasis.new
emphasis << SSML::Prosody.new
emphasis << SSML::SayAs.new('date')
emphasis << SSML::Voice.new
expected_doc << emphasis
prosody = SSML::Prosody.new(:rate => :slow, :content => "H...E...L...L...O?")
prosody << SSML::Break.new
+ prosody << SSML::Audio.new(:src => "hello")
prosody << SSML::Emphasis.new
prosody << SSML::Prosody.new
prosody << SSML::SayAs.new('date')
@@ -128,6 +150,7 @@ module RubySpeech
voice = SSML::Voice.new(:gender => :male, :name => 'fred', :content => "Hi, I'm Fred. The time is currently ")
voice << SSML::SayAs.new('date', :format => 'dmy', :content => "01/02/1960")
voice << SSML::Break.new
+ voice << SSML::Audio.new(:src => "hello")
voice << SSML::Emphasis.new(:content => "I'm so old")
voice << SSML::Prosody.new(:rate => :fast, :content => "And yet so spritely!")
voice << SSML::Voice.new(:age => 12, :content => "And I'm young Fred")

0 comments on commit 66c0b3c

Please sign in to comment.