audio_glue 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: