audio_glue 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1c31ccdeefe481d8de76901107ceba5892ddbaac
4
+ data.tar.gz: 2b91e5f9b841f4a6f6bd19aabe790e227f91e5d0
5
+ SHA512:
6
+ metadata.gz: c30e801164ff09e7b0295a8f4b84a5e5c10ab9cc7e11d4b8eaa38d0d01439664df941463064b52d133a0adc1a24ac21846adc1297b91ecdcf22e063eaf881dfd
7
+ data.tar.gz: d1b7c8166a480ae8a67ee2dac987056f25258bfea178476d09a8daf5f80bdc1c26a612ea669f0d159eb2e9fc7057870f775099d277343e51585a547544466da3
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 TMX Credit, author Potapov Sergey
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,148 @@
1
+ # AudioGlue
2
+
3
+ [![Build Status](https://travis-ci.org/TMXCredit/audio_glue.png?branch=master)](https://travis-ci.org/TMXCredit/audio_glue)
4
+
5
+ Audio template engine (aka ERB/HAML for audio).
6
+
7
+ ## Usage
8
+
9
+ An example:
10
+
11
+ ```ruby
12
+ require 'audio_glue'
13
+
14
+ # We need to use one of the adapters.
15
+ # This one comes from the audio_glue-sox_adapter gem:
16
+ require 'audio_glue/sox_adapter'
17
+
18
+
19
+ # Create a template class:
20
+ class HelloWorldTemplate < AudioGlue::Template
21
+ # Specify the characteristics of an output audio file:
22
+ head do
23
+ format :mp3
24
+ rate 44100
25
+ channels 2
26
+ end
27
+
28
+ # Lets concatenate 2 mp3 files:
29
+ body do
30
+ - file("/sounds/hello.mp3") # Local file
31
+
32
+ if @say_name
33
+ - url("http://some-service.com/my-name-is-glue.mp3") # Remote file
34
+ end
35
+ end
36
+ end
37
+
38
+ # Initialize a template:
39
+ template = HelloWorldTemplate.new(:say_name => true)
40
+
41
+ # Optionally, build using an adapter:
42
+ adapter = AudioGlue::PlainSoxAdapter.new
43
+ builder = AudioGlue::Builder.new(adapter)
44
+
45
+ # Process a template to get audio data:
46
+ audio = builder.build(template) # => audio as a binary string
47
+
48
+ # Write the result to a local file:
49
+ File.binwrite("/hello_world.mp3", audio)
50
+ ```
51
+
52
+ ### Templates
53
+
54
+ A glue template is a template file (e.g. like ERB or HAML) which defines how
55
+ the output audio should be built.
56
+ In Ruby terms, it's a subclass of `AudioGlue::Template`.
57
+
58
+ #### Glue templates
59
+
60
+ In the example above, the template inherits from `AudioGlue::Template`.
61
+ But you can also store templates in `.glue` files.
62
+ For example `/path/to/templates/hello_world.glue`:
63
+
64
+ ```ruby
65
+ head {
66
+ format :mp3
67
+ rate 44100
68
+ channels 2
69
+ }
70
+
71
+ body {
72
+ - file("/sounds/hello.mp3")
73
+ if @say_name
74
+ - url("http://some-service.com/my-name-is-glue.mp3")
75
+ end
76
+ }
77
+ ```
78
+
79
+ And then we can load it with `AudioGlue::TemplateLoader`:
80
+
81
+ ```ruby
82
+ # Create an instance of the loader with a basic directory,
83
+ # where templates are located:
84
+ loader = TemplateLoader.new("/path/to/templates")
85
+
86
+ # Load and cache the template:
87
+ loader.get("hello_world") # => anonymous subclass of AudioGlue::Template
88
+ ```
89
+
90
+ #### Glue Syntax
91
+
92
+ Each glue template has 2 sections:
93
+
94
+ * `head` - contains the parameters of the output file (`format`, `rate`, `channels`)
95
+ * `body` - specifies how to build the output
96
+
97
+ The `body` references the audio snippets that will be used to build the output
98
+ audio. There a few types of snippets:
99
+
100
+ * `file` - points to an audio file in the local file system
101
+ * `url` - contains a URL to a remote audio file
102
+
103
+ To make a snippet be added to the output it should have a dash prefix (`-`).
104
+
105
+
106
+ ### Custom adapters
107
+
108
+ You may want to create your own adapter to concatenate audio files, if you
109
+ think the existing one is not efficient, or if you want to add some caching.
110
+
111
+ The responsibility of adapters is to build audio data from
112
+ `AudioGlue::SnippetPacket`. The snippet packet is a collection of audio
113
+ snippets and output file characteristics(format, rate, channels).
114
+
115
+ A very simple adapter could look like this:
116
+
117
+ ```ruby
118
+ # Doesn't support :url snippets, only files in local file system.
119
+ # Doesn't handle rate and channels.
120
+ class SimpleAdapter < AudioGlue::BaseAdapter
121
+ # Only this method is required to be implemented.
122
+ def build(snippet_packet)
123
+ # Extract file paths from snippets.
124
+ # Ensure only :file snippets are present.
125
+ file_paths = snippet_packet.snippets.map do |snippet|
126
+ unless snippet.type == :file
127
+ raise(AudioGlue::Error, "Only file snippets are supported")
128
+ end
129
+ snippets.source
130
+ end
131
+
132
+ # Build cat command
133
+ command = "cat #{file_paths.join(' ')}"
134
+
135
+ # Concatenate files and return result
136
+ %{command}
137
+ end
138
+ end
139
+ ```
140
+
141
+
142
+ ## Credits
143
+
144
+ * [Sergey Potapov](https://github.com/greyblake)
145
+
146
+ ## Copyright
147
+
148
+ Copyright (c) 2013 TMX Credit.
@@ -0,0 +1,35 @@
1
+ require 'forwardable'
2
+ require 'fileutils'
3
+ require 'tempfile'
4
+
5
+ require 'audio_glue/snippet'
6
+ require 'audio_glue/snippet_packet'
7
+ require 'audio_glue/template/head_context'
8
+ require 'audio_glue/template'
9
+ require 'audio_glue/base_adapter'
10
+ require 'audio_glue/builder'
11
+
12
+ require 'audio_glue/template_loader'
13
+
14
+
15
+ # AudioGlue is a library to concatenate audio snippets using templates.
16
+ # Consider it like ERB or HAML for audio files, where input is not text
17
+ # snippets, but audio snippets, and output is not text, but audio.
18
+ module AudioGlue
19
+ # Basic error for AudioGlue errors.
20
+ class Error < StandardError
21
+ end
22
+
23
+ # Raised on an attempt to call an unimplemented method of an object which
24
+ # a class inherits from an abstract class.
25
+ class AbstractMethodCallError < Error
26
+ end
27
+
28
+ # Raised on a failed attempt to load a glue template.
29
+ class LoadTemplateError < Error
30
+ end
31
+
32
+ # Raised when audio data fails to be built.
33
+ class BuildError < Error
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ module AudioGlue
2
+ # Base adapter that specifies interface for all adapters.
3
+ # The responsibility of an adapter is to build an output audio file
4
+ # from a {AudioGlue::SnippetPacket snippet packet}, which provides
5
+ # a collection of input audio sources and some parameters for the output file
6
+ # (rate, number of channels).
7
+ #
8
+ # An adapter can rely on different tools and libraries to process audio
9
+ # files. Also an adapter is responsible for correctly processing remote files
10
+ # (e.g. downloading them as temporary files if necessary).
11
+ class BaseAdapter
12
+ # Build audio file from a snippet packet and return result as binary string.
13
+ #
14
+ # @param snippet_packet [AudioGlue::SnippetPacket]
15
+ #
16
+ # @return [String]
17
+ def build(snippet_packet)
18
+ raise AbstractMethodCallError, __method__
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,40 @@
1
+ module AudioGlue
2
+ # Builds audio from a {AudioGlue::Template template} instance.
3
+ #
4
+ # @example
5
+ # # Instantiate the builder with an adapter:
6
+ # builder = AudioGlue::Builder.new(AudioGlue::PlainSoxAdapter.new)
7
+ #
8
+ # # Create the template instance:
9
+ # template = HiTemplate.new(:with_smalltalk => true)
10
+ #
11
+ # # Build the output audio:
12
+ # builder.build(template) # => audio as a binary string
13
+ class Builder
14
+ # @param adapter [AudioGlue::BaseAdapter] instance of an adapter
15
+ def initialize(adapter)
16
+ @adapter = adapter
17
+ end
18
+
19
+ # Build an audio file and return the result as a binary string.
20
+ #
21
+ # @param template [AudioGlue::Template]
22
+ # @param opts [Hash]
23
+ #
24
+ # @option opts :format [Symbol, String]
25
+ # @option opts :rate [Integer, String]
26
+ # @option opts :channels [Integer, String]
27
+ #
28
+ # @return [String]
29
+ def build(template, opts = {})
30
+ format, rate, channels = opts[:format], opts[:rate], opts[:channels]
31
+
32
+ packet = template.build_snippet_packet
33
+ packet.format = format if format
34
+ packet.rate = rate if rate
35
+ packet.channels = channels if channels
36
+
37
+ @adapter.build(packet)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ module AudioGlue
2
+ # Represents an audio partial which will be used to build an output audio.
3
+ # There are a few types of snippets:
4
+ # * :file - represents audio file in local file system
5
+ # * :url - represents remote audio file
6
+ #
7
+ # Other custom types can be created if custom adapter will support them.
8
+ #
9
+ # {AudioGlue::BaseAdapter adapters} are responsible for processing every
10
+ # particular snippet type.
11
+ class Snippet
12
+ attr_reader :type, :source, :snippet_packet, :opts
13
+
14
+ # @param type [Symbol] :file, :url or anything else that can be handled by
15
+ # the adapter
16
+ # @param source [String] Can be location, URL, or whatever depending on type
17
+ # @param snippet_packet [AudioGlue::SnippetPacket] the snippet packet used
18
+ # to add the audio snippet to the packet when `-` unary method is called
19
+ # @param opts [Hash] any specific options which are supported by adapter
20
+ def initialize(type, source, snippet_packet, opts = {})
21
+ @type = type
22
+ @source = source
23
+ @snippet_packet = snippet_packet
24
+ @opts = opts
25
+ end
26
+
27
+ # Add self to the snippet packet.
28
+ # It's used to support dash syntax in +.glue+ files, like:
29
+ # - file('/audio.mp3')
30
+ #
31
+ # @return [void]
32
+ def -@
33
+ @snippet_packet << self
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ module AudioGlue
2
+ # SnippetPacket is a collection of {AudioGlue::Snippet snippets} with
3
+ # some additional info about the output file
4
+ # (format, rate, number of channels).
5
+ #
6
+ # It's supposed to be built by {AudioGlue::Template}. And then it's passed
7
+ # to an adapter which builds the audio output.
8
+ class SnippetPacket
9
+ extend Forwardable
10
+ def_delegators :@snippets, :<<
11
+
12
+ attr_accessor :format, :rate, :channels
13
+ attr_reader :snippets
14
+
15
+ # @param format [Symbol, String]
16
+ # @param rate [Numeric, String]
17
+ # @param channels [Numeric, String]
18
+ def initialize(format, rate, channels)
19
+ @format = format
20
+ @rate = rate
21
+ @channels = channels
22
+ @snippets = []
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,152 @@
1
+ module AudioGlue
2
+ # Represents an audio template.
3
+ # Every particular template is a subclass of {AudioGlue::Template}.
4
+ # Quite often the classes can be anonymous. (That's why +inspect+ is redefined
5
+ # to provide more information.)
6
+ #
7
+ # The Template class owns +format+, +rate+, +channels+, and also a block used
8
+ # to create an {AudioGlue::SnippetPacket}
9
+ # ("render", in terms of the view templates).
10
+ #
11
+ # A Template instance differs from the Template class. It has instance
12
+ # variables, that can be used in the +body+ block.
13
+ #
14
+ # @example
15
+ # class HiTemplate < AudioGlue::Template
16
+ # # Output file information
17
+ # head do
18
+ # format :mo3
19
+ # rate 22050
20
+ # channels 2
21
+ # end
22
+ #
23
+ # # Block to "render" template
24
+ # body do
25
+ # - file('/hi.mp3')
26
+ # if @with_smalltalk
27
+ # - url('http://say.it/how-are-you.mp3')
28
+ # end
29
+ # end
30
+ # end
31
+ #
32
+ # # Create an instance of Template. We wonder how our friend is doing so
33
+ # # we pass ":with_smalltalk => true", to add a remote URL snippet.
34
+ # template = HiTemplate.new(:with_smalltalk => true)
35
+ #
36
+ # # Let's create a snippet packet:
37
+ # packet = template.build_snippet_packet => # <AudioGlue::SnippetPacket ..>
38
+ # # Now we can pass a snippet packet to the adapter to build output audio.
39
+ class Template
40
+ extend Forwardable
41
+ def_delegators 'self.class', :format, :rate, :channels, :path, :body_proc
42
+
43
+ class << self
44
+ attr_accessor :format, :rate, :channels, :path, :body_proc
45
+ end
46
+
47
+ # Process the +head+ block in a +.glue+ template.
48
+ #
49
+ # @yield block which will be executed in context of
50
+ # {AudioGlue::Template::HeadContext} object.
51
+ #
52
+ # @return [void]
53
+ def self.head(&block)
54
+ HeadContext.new(self).instance_eval(&block)
55
+ end
56
+
57
+ # Process the +body+ block in a +.glue+ template.
58
+ #
59
+ # @yield block which will be executed in context of
60
+ # {AudioGlue::Template::BodyContext} object. It should define body of
61
+ # audio template.
62
+ # @return [void]
63
+ def self.body(&block)
64
+ self.body_proc = block
65
+ end
66
+
67
+ # Redefine the +inspect+ method to provide more information when the
68
+ # template is an anonymous class.
69
+ #
70
+ # @return [String]
71
+ def self.inspect
72
+ if self.name
73
+ super
74
+ else
75
+ info = "<AudioGlue::Template(class)"
76
+ info << " path=#{path.inspect}" if path
77
+ info << ">"
78
+ end
79
+ end
80
+
81
+
82
+ # @param variables [Hash] hash of parameters which can be used as instance
83
+ # variables in +body+ statement of +.glue+ template.
84
+ def initialize(variables = {})
85
+ variables.each do |var, value|
86
+ instance_variable_set("@#{var}", value)
87
+ end
88
+ end
89
+
90
+ # Execute the body of the template to build a snippet packet.
91
+ #
92
+ # @return [AudioGlue::SnippetPacket]
93
+ def build_snippet_packet
94
+ @__packet__ = SnippetPacket.new(format, rate, channels)
95
+ instance_eval(&body_proc)
96
+ @__packet__
97
+ end
98
+
99
+ # Redefine +inspect+ to provide more information if the class of the
100
+ # template object is anonymous.
101
+ #
102
+ # @return [String]
103
+ def inspect
104
+ if self.class.name
105
+ super
106
+ else
107
+ info = "<AudioGlue::Template"
108
+ info << "(path=#{path.inspect})" if path
109
+
110
+ instance_variables.each do |var|
111
+ info << " #{var}="
112
+ info << instance_variable_get(var).inspect
113
+ end
114
+
115
+ info << ">"
116
+ end
117
+ end
118
+
119
+
120
+ # Create a snippet (with the +:file+ type) for the given audio file.
121
+ #
122
+ # @param file_path [String] path to an audio file in local file system
123
+ #
124
+ # @return [AudioGlue::Snippet]
125
+ def file(file_path)
126
+ create_snippet(:file, file_path)
127
+ end
128
+ private :file
129
+
130
+ # Create a snippet (with +:url+ type) for the given audio URL.
131
+ #
132
+ # @param remote_url [String] remote location of audio file
133
+ #
134
+ # @return [AudioGlue::Snippet]
135
+ def url(remote_url)
136
+ create_snippet(:url, remote_url)
137
+ end
138
+ private :url
139
+
140
+ # Create snippet.
141
+ #
142
+ # @param type [Symbol] snippet type
143
+ # @param source [String]
144
+ # @param opts [Hash] any options supported by adapter
145
+ #
146
+ # @return [AudioGlue::Snippet]
147
+ def create_snippet(type, source, opts = {})
148
+ Snippet.new(type, source, @__packet__, opts)
149
+ end
150
+ private :create_snippet
151
+ end
152
+ end
@@ -0,0 +1,40 @@
1
+ module AudioGlue
2
+ class Template
3
+ # The context in which the +head+ statement of a +.glue+ template is
4
+ # executed. It's used to set the +format+, +rate+ and +channels+ on
5
+ # the template.
6
+ class HeadContext
7
+ # @param template [Class] subclass of {AudioGlue::Template}
8
+ def initialize(template)
9
+ @template = template
10
+ end
11
+
12
+ # Set the audio format on the template ("mp3", "ogg", "wav", etc).
13
+ #
14
+ # @param format_value [Symbol, String]
15
+ #
16
+ # @return [void]
17
+ def format(format_value)
18
+ @template.format = format_value
19
+ end
20
+
21
+ # Set the audio bitrate on the template.
22
+ #
23
+ # @param rate_value [Integer, String]
24
+ #
25
+ # @return [void]
26
+ def rate(rate_value)
27
+ @template.rate = rate_value
28
+ end
29
+
30
+ # Set the number of channels on the template.
31
+ #
32
+ # @param channels_value [Integer, String]
33
+ #
34
+ # @return [void]
35
+ def channels(channels_value)
36
+ @template.channels = channels_value
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,78 @@
1
+ module AudioGlue
2
+ # Loads +.glue+ templates and caches them.
3
+ #
4
+ # @example
5
+ # loader = AudioGlue::TemplateLoader.new('/project/audio_templates/')
6
+ #
7
+ # # load and cache "/project/audio_templates/john/hi.glue"
8
+ # loader.get('john/hi') # => subclass of AudioGlue::Template
9
+ class TemplateLoader
10
+ # Extension of template files.
11
+ TEMPLATE_EXT = 'glue'
12
+
13
+ # @attr_reader base_path [String] path to a directory with templates
14
+ attr_reader :base_path
15
+
16
+ # @attr_reader cache [Hash<String, Class>] cached templates, key is a path
17
+ # to a template file, value is a subclass of {AudioGlue::Template}
18
+ attr_reader :cache
19
+
20
+ # @param base_path [String] path to a directory with templates
21
+ # @param opts [Hash] options
22
+ # @option opts :helper [Module] module which provides custom methods
23
+ # for templates.
24
+ def initialize(base_path, opts = {})
25
+ @base_path = base_path
26
+ @helper = opts.delete(:helper)
27
+ @cache = {}
28
+ end
29
+
30
+ # Load and cache the template from a +.glue+ template file.
31
+ #
32
+ # @param template_name [String] name of template in +base_path+ directory
33
+ #
34
+ # @return [Class] a subclass of {AudioGlue::Template}
35
+ def get(template_name)
36
+ path = absolute_path(template_name)
37
+ @cache[path] ||= load_template_from_file(path)
38
+ end
39
+
40
+ # Reset the cache.
41
+ #
42
+ # @return [Hash] empty cache
43
+ def reset_cache!
44
+ @cache.clear
45
+ end
46
+
47
+
48
+
49
+ # Calculate the absolute path to a file from a template name.
50
+ #
51
+ # @param template_name [String] name of template in +base_path+ directory
52
+ #
53
+ # @return [String] absolute path to a template file
54
+ def absolute_path(template_name)
55
+ File.join(@base_path, "#{template_name}.#{TEMPLATE_EXT}")
56
+ end
57
+ private :absolute_path
58
+
59
+ # Read a +.glue+ template file and create a template class from it.
60
+ #
61
+ # @param path [String] absolute path to .glue template file
62
+ #
63
+ # @return [Class] a subclass of {AudioGlue::Template}
64
+ def load_template_from_file(path)
65
+ Class.new(AudioGlue::Template).tap do |template|
66
+ content = File.read(path)
67
+ template.path = path
68
+ template.send(:include, @helper) if @helper
69
+ template.instance_eval(content, path)
70
+ end
71
+ rescue Errno::ENOENT => err
72
+ raise AudioGlue::LoadTemplateError, err.message
73
+ rescue SyntaxError, NameError => err
74
+ raise AudioGlue::LoadTemplateError, err.message, err.backtrace
75
+ end
76
+ private :load_template_from_file
77
+ end
78
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: audio_glue
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - TMX Credit
8
+ - Potapov Sergey
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-10-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '1.0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '1.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: jeweler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 1.8.7
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: 1.8.7
42
+ - !ruby/object:Gem::Dependency
43
+ name: yard
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: pry
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: metric_fu
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ description: Tool to assemble audio files from templates
85
+ email:
86
+ - rubygems@tmxcredit.com
87
+ - blake131313@gmail.com
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files:
91
+ - LICENSE.txt
92
+ - README.markdown
93
+ files:
94
+ - LICENSE.txt
95
+ - README.markdown
96
+ - lib/audio_glue.rb
97
+ - lib/audio_glue/base_adapter.rb
98
+ - lib/audio_glue/builder.rb
99
+ - lib/audio_glue/snippet.rb
100
+ - lib/audio_glue/snippet_packet.rb
101
+ - lib/audio_glue/template.rb
102
+ - lib/audio_glue/template/head_context.rb
103
+ - lib/audio_glue/template_loader.rb
104
+ homepage: http://github.com/TMXCredit/audio_glue
105
+ licenses:
106
+ - MIT
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 2.0.3
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: aka ERB for audio files
128
+ test_files: []
129
+ has_rdoc: