Class: Riff::Builder
- Inherits:
-
Object
- Object
- Riff::Builder
- Defined in:
- lib/riff/writer.rb
Overview
A Builder allows you to create a ‘de novo’ RIFF file recursively, similar in style to the XML Builder class. The client uses Builder.create
to create an empty file at a given filesystem location, and yields a block, allowing the client to construct chunks and LISTs semantically with Ruby blocks.
In the following example, a new .wav file is created containing 1 second of 1 K tone and descriptive metadata.
require 'lib/riff/reader.rb'
require 'lib/riff/writer.rb'
include Riff
SAMPLES_PER_SECOND = 48000
FREQ = 1000
AMPLITUDE = 0x0fff
Builder.create(ARGV[0],"WAVE") do |w|
w.list("INFO") { |info|
info.chunk("ICOP") {|c| # "copyright"
c << "(c) 2007 Joe User.
}
info.chunk("INAM") {|c| # "name" or "title"
c << "1K tone with metadata"
}
info.chunk("ISFT") {|c| # "software"
c << "libRiff v" + "%i.%i" % [Riff::VERSION::MAJOR, Riff::VERSION::MINOR]
}
info.chunk("IART") {|c| # "artist" (maps to kMDItemAuthors in Spotlight)
c << "Joe User"
}
}
w.chunk("fmt ") { |c|
c.putc(1);c.putc(0) #format 1, PCM
c.putc(1);c.putc(0) #1 channel
# samples per second
Builder.int_to_four_little_endian_bytes(SAMPLES_PER_SECOND).each {|byte| c.putc(byte)}
# avg. bytes per second
Builder.int_to_four_little_endian_bytes(SAMPLES_PER_SECOND * 2).each {|byte| c.putc(byte)}
c.putc(2);c.putc(0) #block alignment 2
c.putc(16);c.putc(0) #16 bits per sample
}
w.chunk("data") { |c|
factor = Math::PI / (SAMPLES_PER_SECOND / (FREQ * 2))
1.upto(SAMPLES_PER_SECOND) do |i|
val = ( Math::sin( i * factor ) * AMPLITUDE ).floor
Builder::int_to_four_little_endian_bytes(val)[0,2].each {|byte| c.putc(byte)}
end
}
end
Defined Under Namespace
Classes: IOProxy
Class Method Summary collapse
-
.create(path, type) ⇒ Object
Create a new RIFF file at
path
, usingtype
for the top-level chunk’s type or signature.
Instance Method Summary collapse
-
#chunk(fourcc) {|IOProxy.new(@io)| ... } ⇒ Object
Add a data chunk to the Builder.
-
#container(fourcc, type) ⇒ Object
:nodoc:.
-
#initialize(stream) ⇒ Builder
constructor
:nodoc:.
-
#list(type) ⇒ Object
Add a RIFF “LIST” chunk.
Constructor Details
#initialize(stream) ⇒ Builder
:nodoc:
151 152 153 |
# File 'lib/riff/writer.rb', line 151 def initialize(stream) # :nodoc: @io = stream end |
Class Method Details
.create(path, type) ⇒ Object
Create a new RIFF file at path
, using type
for the top-level chunk’s type or signature.
At this time, you must provide a block to this method to add chunks.
114 115 116 117 118 119 120 121 122 |
# File 'lib/riff/writer.rb', line 114 def create(path,type) #:yields: builder raise RuntimeError unless block_given? file = File.open(path,"w") w = Builder.new(file) w.container('RIFF',type) do |body_io| yield Builder.new(body_io) end file.close end |
Instance Method Details
#chunk(fourcc) {|IOProxy.new(@io)| ... } ⇒ Object
Add a data chunk to the Builder. The method yields a write-only pseudo-IO object that you write the chunk data to. Only write the payload of the chunk here; the fourcc and size will be written for you. Do not pad the data you write to an even boundary, either.
130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/riff/writer.rb', line 130 def chunk(fourcc) #:yields: stream @io.write( Util::sanitize_fourcc(fourcc) ) 4.times { @io.putc(0) } oldPos = @io.pos yield IOProxy.new(@io) length = @io.pos - oldPos @io.putc(0) if (length % 2) == 1 @io.seek(oldPos-4,IO::SEEK_SET) bytes = Util::int_to_four_little_endian_bytes(length) bytes.each {|byte| @io.putc(byte)} @io.seek(0,IO::SEEK_END) end |