riff 0.3 → 0.3.1
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.
- data/Rakefile +5 -1
- data/examples/readchunks.rb +32 -3
- data/lib/riff/info.rb +52 -10
- data/lib/riff/reader.rb +36 -55
- data/lib/riff/util.rb +46 -0
- data/lib/riff/writer.rb +83 -18
- data/test/builder_test.rb +67 -0
- data/test/riff_test.rb +19 -11
- data/test/riff_test_suite.rb +3 -0
- data/test/wav_test.rb +24 -24
- metadata +45 -34
data/Rakefile
CHANGED
data/examples/readchunks.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'lib/riff/reader.rb'
|
2
|
+
require 'optparse'
|
2
3
|
|
3
4
|
def print_chunk(ck,margin = "")
|
4
5
|
if ck.is_list? then
|
@@ -11,6 +12,34 @@ def print_chunk(ck,margin = "")
|
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
@chunk = nil
|
16
|
+
cl_options = OptionParser.new do |ops|
|
17
|
+
ops.on('-c CHUNK','--chunk CHUNK','Output the first first-tier chunk with fourcc',
|
18
|
+
'CHUNK to stdout') do |chk|
|
19
|
+
@chunk = chk
|
20
|
+
end
|
21
|
+
ops.on('-h','-?','--help','Print this Message') do
|
22
|
+
puts ops
|
23
|
+
exit 0
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
rest = cl_options.parse!
|
28
|
+
|
29
|
+
rest.each do |path|
|
30
|
+
if @chunk
|
31
|
+
Riff::Reader.open(path,"r") do |wav|
|
32
|
+
wav.root_chunk.each do |a_chunk|
|
33
|
+
if a_chunk.fourcc == @chunk
|
34
|
+
$stdout.print a_chunk.body
|
35
|
+
exit 0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
else
|
41
|
+
Riff::Reader.open(path,"r") do |wav|
|
42
|
+
print_chunk( wav.root_chunk )
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end # rest.each
|
data/lib/riff/info.rb
CHANGED
@@ -1,5 +1,24 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
#--
|
2
|
+
#riff.rb -- Library for reading generic Microsoft RIFF Files
|
3
|
+
#Copyright (C) 2009 Jamie Hardt
|
4
|
+
|
5
|
+
#This library is free software; you can redistribute it and/or
|
6
|
+
#modify it under the terms of the GNU Lesser General Public
|
7
|
+
#License as published by the Free Software Foundation; either
|
8
|
+
#version 2.1 of the License, or (at your option) any later version.
|
9
|
+
|
10
|
+
#This library is distributed in the hope that it will be useful,
|
11
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
#Lesser General Public License for more details.
|
14
|
+
|
15
|
+
#You should have received a copy of the GNU Lesser General Public
|
16
|
+
#License along with this library; if not, write to the Free Software
|
17
|
+
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'riff/reader.rb'
|
21
|
+
require 'riff/writer.rb'
|
3
22
|
|
4
23
|
module Riff
|
5
24
|
|
@@ -15,6 +34,10 @@ module Riff
|
|
15
34
|
# editor['IART'] = "Me Myself"
|
16
35
|
#
|
17
36
|
# Note that some names map to the same fourcc.
|
37
|
+
#
|
38
|
+
# Also note that RIFF INFO datums are generally encoded using ISO-8859-1 WinANSI.
|
39
|
+
# We expect to be able to support this more fully with Ruby 1.9 and its integrated
|
40
|
+
# text encoding facilities.
|
18
41
|
class MetaEditor
|
19
42
|
|
20
43
|
# the path to the file being edited
|
@@ -62,6 +85,7 @@ module Riff
|
|
62
85
|
ATTRIBUTE_FOURCCs.each do |key|
|
63
86
|
class_eval <<-TXT
|
64
87
|
def #{key.downcase}=(val)
|
88
|
+
@dirty = true
|
65
89
|
@metadata['#{key}'] = val
|
66
90
|
end
|
67
91
|
def #{key.downcase}
|
@@ -73,6 +97,7 @@ module Riff
|
|
73
97
|
ATTRIBUTE_NAMES.each_pair do |key,value|
|
74
98
|
class_eval <<-TXT
|
75
99
|
def #{key.downcase.gsub(/ /,'_').gsub(/[^a-z_]/,'')}=(val)
|
100
|
+
@dirty = true
|
76
101
|
@metadata['#{value}'] = val
|
77
102
|
end
|
78
103
|
|
@@ -98,30 +123,43 @@ module Riff
|
|
98
123
|
end
|
99
124
|
|
100
125
|
# Creates a MetaEditor object for the file locates at +path+
|
101
|
-
|
126
|
+
#
|
127
|
+
# If you provide a block, the MetaEditor itself will be yielded, and
|
128
|
+
# a +save!+ will be called upon the block closing.
|
129
|
+
def initialize(path) #:yields: self
|
102
130
|
reader = Reader.open(path,'r')
|
103
131
|
@pad_out = 1024
|
104
132
|
@path = path
|
105
133
|
@metadata = {}
|
134
|
+
@dirty = false
|
106
135
|
infoChunk = reader.root_chunk.find {|c| c.signature == 'INFO'}
|
107
136
|
if infoChunk && infoChunk.is_list?
|
108
137
|
infoChunk.each do |subChunk|
|
109
138
|
@metadata[subChunk.fourcc] = subChunk.body
|
110
139
|
end
|
111
140
|
end
|
141
|
+
if block_given?
|
142
|
+
yield self
|
143
|
+
save!
|
144
|
+
end
|
145
|
+
self
|
112
146
|
end
|
113
147
|
|
114
|
-
|
115
|
-
|
148
|
+
# Get a metadatum by +fourcc+
|
149
|
+
def [](fourcc)
|
150
|
+
return @metadata[fourcc]
|
116
151
|
end
|
117
152
|
|
118
|
-
|
119
|
-
|
153
|
+
# Set a metadatum by +fourcc+
|
154
|
+
def []=(fourcc,value)
|
155
|
+
@dirty = true
|
156
|
+
@metadata[fourcc] = value
|
120
157
|
end
|
121
158
|
|
159
|
+
# Yields each metadatum
|
122
160
|
def each_metadatum
|
123
|
-
@metadata.each_pair do |
|
124
|
-
yield
|
161
|
+
@metadata.each_pair do |fourcc,value|
|
162
|
+
yield fourcc,value
|
125
163
|
end
|
126
164
|
end
|
127
165
|
|
@@ -130,8 +168,12 @@ module Riff
|
|
130
168
|
#
|
131
169
|
# If a pad_out number is specified, a "JUNK" chunk with a payload of pad_out
|
132
170
|
# bytes will be added after the INFO chunk.
|
171
|
+
#
|
172
|
+
# If you have not modified any metadatums of the file, this method will have no
|
173
|
+
# effect on the system.
|
133
174
|
def save!
|
134
|
-
|
175
|
+
return unless @dirty
|
176
|
+
tempPath = File.dirname(path) + "/" + (([?a] *16).map {|i| (i + rand(26)).chr}).join + ".tmp"
|
135
177
|
Reader.open(path,'r') do |reader|
|
136
178
|
begin
|
137
179
|
Builder.create(tempPath,reader.root_chunk.signature) do |riffwriter|
|
data/lib/riff/reader.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#--
|
2
|
-
#riff.rb --
|
3
|
-
#Copyright (C)
|
2
|
+
#riff.rb -- Library for reading generic Microsoft RIFF Files
|
3
|
+
#Copyright (C) 2009 Jamie Hardt
|
4
4
|
|
5
5
|
#This library is free software; you can redistribute it and/or
|
6
6
|
#modify it under the terms of the GNU Lesser General Public
|
@@ -32,7 +32,7 @@
|
|
32
32
|
# = Examples
|
33
33
|
# === Getting iXML metadata from a broadcast-WAV file
|
34
34
|
#
|
35
|
-
# require 'riff/
|
35
|
+
# require 'riff/reader'
|
36
36
|
# Riff::Reader.open(ARGV[0],"r") do |wav|
|
37
37
|
# xml = wav.root_chunk['ixml'].body
|
38
38
|
# end
|
@@ -56,60 +56,55 @@
|
|
56
56
|
# print_chunk( wav.root_chunk )
|
57
57
|
# end
|
58
58
|
#
|
59
|
+
|
60
|
+
require 'libc/riff/riff.bundle'
|
61
|
+
#require 'riff/util'
|
62
|
+
|
59
63
|
module Riff
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end #module version
|
65
|
-
|
64
|
+
|
65
|
+
# The Reader class provides a front-end to the other objects of the library.
|
66
|
+
# It's the only object that you interact with directly, and calling its methods
|
67
|
+
# will return the other objects of the class.
|
66
68
|
class Reader
|
67
|
-
# The Reader class provides a front-end to the other objects of the library.
|
68
|
-
# It's the only object that you interact with directly, and calling its methods
|
69
|
-
# will return the other objects of the class.
|
70
69
|
|
71
70
|
# Returns the File object for this reader.
|
72
|
-
|
71
|
+
# attr_reader :file
|
73
72
|
|
74
73
|
# Opens a RIFF file for reading. Pass a string path and string mode, as you would
|
75
74
|
# for File::open. A Riff object will be returned.
|
76
|
-
# * At this time, only the "r" and "rb" modes are supported, others will raise
|
77
|
-
# and ArgumentError
|
78
75
|
# * If you provide a block, the Riff object will be yielded to the block as the
|
79
76
|
# sole parameter, and will be automatically closed at the end of the block.
|
80
77
|
# * If you pass a file which does not start with the RIFF fourcc, the file
|
81
78
|
# is invalid and a FileTypeError will be thrown.
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
riff_obj
|
87
|
-
|
88
|
-
|
89
|
-
|
79
|
+
# * _mode_ is ignored and will be removed in a future version
|
80
|
+
# def Reader.open(path,mode = nil) # :yields: riff_object
|
81
|
+
# riff_obj = Riff::Reader.new(path)
|
82
|
+
# if block_given? && riff_obj then
|
83
|
+
# yield riff_obj
|
84
|
+
# riff_obj.close
|
85
|
+
# end
|
86
|
+
# riff_obj
|
87
|
+
# end
|
90
88
|
|
91
89
|
# Returns the Root Chunk of the RIFF file as a ListChunk
|
92
|
-
def root_chunk
|
93
|
-
@file.rewind
|
94
|
-
the_chunk = Chunk.read_chunk(@file)
|
95
|
-
end
|
90
|
+
# def root_chunk
|
91
|
+
# @file.rewind
|
92
|
+
# the_chunk = Chunk.read_chunk(@file)
|
93
|
+
# end
|
96
94
|
|
97
95
|
# Closes the Riff object. Subsequent calls to the Riff object or any of its
|
98
96
|
# chunk objects will fail.
|
99
|
-
def close
|
100
|
-
@file.close
|
101
|
-
end
|
97
|
+
# def close
|
98
|
+
# @file.close
|
99
|
+
# end
|
102
100
|
|
103
|
-
|
101
|
+
# class FileTypeError < StandardError ; end #:nodoc:
|
104
102
|
|
105
|
-
private
|
106
|
-
|
107
|
-
def initialize(path
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
@file = File.open(path,mode)
|
112
|
-
end #def initialize
|
103
|
+
# private
|
104
|
+
#
|
105
|
+
# def initialize(path) #:nodoc:
|
106
|
+
# @file = File.open(path)
|
107
|
+
# end #def initialize
|
113
108
|
|
114
109
|
end
|
115
110
|
|
@@ -169,25 +164,11 @@ module Riff
|
|
169
164
|
|
170
165
|
protected
|
171
166
|
|
172
|
-
def Chunk.read_bytes_to_int(file,bytes) # :nodoc:
|
173
|
-
|
174
|
-
ary = [ ]
|
175
|
-
bytes.times { ary << file.getc }
|
176
|
-
|
177
|
-
result = 0
|
178
|
-
ary.each_with_index do |n, i|
|
179
|
-
7.downto(0) do |bit|
|
180
|
-
result += 2 ** ((bit) + i * 8) if n[bit] == 1
|
181
|
-
end
|
182
|
-
end
|
183
|
-
return result
|
184
|
-
end
|
185
|
-
|
186
167
|
def initialize(fp) #:nodoc:
|
187
168
|
@file = fp
|
188
169
|
@offset = @file.pos
|
189
170
|
@fourcc = @file.read(4)
|
190
|
-
@length =
|
171
|
+
@length = Util.read_bytes_to_int(@file,4)
|
191
172
|
end
|
192
173
|
|
193
174
|
end #class Chunk
|
@@ -195,7 +176,7 @@ module Riff
|
|
195
176
|
# ListChunk is a subclass of Chunk, and so you can access its fourcc and size
|
196
177
|
#
|
197
178
|
# <em>Note:</em> The +body+ method is not permitted on ListChunk
|
198
|
-
class ListChunk
|
179
|
+
class ListChunk #< Chunk
|
199
180
|
|
200
181
|
include Enumerable
|
201
182
|
|
data/lib/riff/util.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'libc/riff/riff.bundle'
|
2
|
+
|
3
|
+
module Riff
|
4
|
+
|
5
|
+
# module VERSION
|
6
|
+
# MAJOR = 0
|
7
|
+
# MINOR = 4
|
8
|
+
# end #module version
|
9
|
+
|
10
|
+
# The Util module contains various methods
|
11
|
+
module Util
|
12
|
+
|
13
|
+
# Reads +bytes+ bytes from file and converts the bytes into an unsigned int, assuming that
|
14
|
+
# the bytes are little-endian
|
15
|
+
# def self.read_bytes_to_int(file,bytes)
|
16
|
+
# ary = [ ]
|
17
|
+
# bytes.times { ary << file.getc }
|
18
|
+
#
|
19
|
+
# result = 0
|
20
|
+
# ary.each_with_index do |n, i|
|
21
|
+
# 7.downto(0) do |bit|
|
22
|
+
# result += 2 ** ((bit) + i * 8) if n[bit] == 1
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# return result
|
26
|
+
# end
|
27
|
+
|
28
|
+
# def self.int_to_four_little_endian_bytes(i)
|
29
|
+
# n = [ i.abs , 2 ** 32 ].min
|
30
|
+
# [(n.to_i & 0xff) , (n.to_i & 0xff00)>>8,
|
31
|
+
# (n.to_i & 0xff0000)>>16,(n.to_i & 0xff000000)>>24 ]
|
32
|
+
# end
|
33
|
+
|
34
|
+
# def self.int_to_four_big_endian_bytes(i)
|
35
|
+
# return int_to_four_little_endian_bytes(i).reverse
|
36
|
+
# end
|
37
|
+
|
38
|
+
|
39
|
+
# def self.sanitize_fourcc(fourcc)
|
40
|
+
# fourcc[0,4].ljust(4,"\0")
|
41
|
+
# end
|
42
|
+
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/lib/riff/writer.rb
CHANGED
@@ -1,9 +1,80 @@
|
|
1
|
+
#--
|
2
|
+
#riff.rb -- Library for reading generic Microsoft RIFF Files
|
3
|
+
#Copyright (C) 2009 Jamie Hardt
|
4
|
+
|
5
|
+
#This library is free software; you can redistribute it and/or
|
6
|
+
#modify it under the terms of the GNU Lesser General Public
|
7
|
+
#License as published by the Free Software Foundation; either
|
8
|
+
#version 2.1 of the License, or (at your option) any later version.
|
9
|
+
|
10
|
+
#This library is distributed in the hope that it will be useful,
|
11
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
#Lesser General Public License for more details.
|
14
|
+
|
15
|
+
#You should have received a copy of the GNU Lesser General Public
|
16
|
+
#License along with this library; if not, write to the Free Software
|
17
|
+
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
#++
|
19
|
+
|
1
20
|
require 'stringio'
|
21
|
+
require 'riff/util.rb'
|
2
22
|
|
3
23
|
module Riff
|
4
24
|
|
5
25
|
# A Builder allows you to create a 'de novo' RIFF file recursively, similar
|
6
|
-
# in style to the XML Builder class.
|
26
|
+
# in style to the XML Builder class. The client uses +Builder.create+
|
27
|
+
# to create an empty file at a given filesystem location, and yields a block,
|
28
|
+
# allowing the client to construct chunks and LISTs semantically with Ruby
|
29
|
+
# blocks.
|
30
|
+
#
|
31
|
+
# In the following example, a new .wav file is created containing 1 second
|
32
|
+
# of 1 K tone and descriptive metadata.
|
33
|
+
#
|
34
|
+
## require 'lib/riff/reader.rb'
|
35
|
+
## require 'lib/riff/writer.rb'
|
36
|
+
##
|
37
|
+
## include Riff
|
38
|
+
## SAMPLES_PER_SECOND = 48000
|
39
|
+
## FREQ = 1000
|
40
|
+
## AMPLITUDE = 0x0fff
|
41
|
+
##
|
42
|
+
## Builder.create(ARGV[0],"WAVE") do |w|
|
43
|
+
## w.list("INFO") { |info|
|
44
|
+
## info.chunk("ICOP") {|c| # "copyright"
|
45
|
+
## c << "(c) 2007 Joe User.
|
46
|
+
## }
|
47
|
+
## info.chunk("INAM") {|c| # "name" or "title"
|
48
|
+
## c << "1K tone with metadata"
|
49
|
+
## }
|
50
|
+
## info.chunk("ISFT") {|c| # "software"
|
51
|
+
## c << "libRiff v" + "%i.%i" % [Riff::VERSION::MAJOR, Riff::VERSION::MINOR]
|
52
|
+
## }
|
53
|
+
## info.chunk("IART") {|c| # "artist" (maps to kMDItemAuthors in Spotlight)
|
54
|
+
## c << "Joe User"
|
55
|
+
## }
|
56
|
+
## }
|
57
|
+
## w.chunk("fmt ") { |c|
|
58
|
+
## c.putc(1);c.putc(0) #format 1, PCM
|
59
|
+
## c.putc(1);c.putc(0) #1 channel
|
60
|
+
##
|
61
|
+
## # samples per second
|
62
|
+
## Builder.int_to_four_little_endian_bytes(SAMPLES_PER_SECOND).each {|byte| c.putc(byte)}
|
63
|
+
##
|
64
|
+
## # avg. bytes per second
|
65
|
+
## Builder.int_to_four_little_endian_bytes(SAMPLES_PER_SECOND * 2).each {|byte| c.putc(byte)}
|
66
|
+
## c.putc(2);c.putc(0) #block alignment 2
|
67
|
+
## c.putc(16);c.putc(0) #16 bits per sample
|
68
|
+
## }
|
69
|
+
## w.chunk("data") { |c|
|
70
|
+
## factor = Math::PI / (SAMPLES_PER_SECOND / (FREQ * 2))
|
71
|
+
## 1.upto(SAMPLES_PER_SECOND) do |i|
|
72
|
+
## val = ( Math::sin( i * factor ) * AMPLITUDE ).floor
|
73
|
+
## Builder::int_to_four_little_endian_bytes(val)[0,2].each {|byte| c.putc(byte)}
|
74
|
+
## end
|
75
|
+
## }
|
76
|
+
## end
|
77
|
+
|
7
78
|
class Builder
|
8
79
|
|
9
80
|
class IOProxy #:nodoc:
|
@@ -36,8 +107,12 @@ module Riff
|
|
36
107
|
end #class IOProxy
|
37
108
|
|
38
109
|
class << self
|
39
|
-
# Create a new RIFF file at +path+, using +type+ for the top-level
|
40
|
-
|
110
|
+
# Create a new RIFF file at +path+, using +type+ for the top-level
|
111
|
+
# chunk's type or signature.
|
112
|
+
#
|
113
|
+
# At this time, you must provide a block to this method to add chunks.
|
114
|
+
def create(path,type) #:yields: builder
|
115
|
+
raise RuntimeError unless block_given?
|
41
116
|
file = File.open(path,"w")
|
42
117
|
w = Builder.new(file)
|
43
118
|
w.container('RIFF',type) do |body_io|
|
@@ -46,16 +121,6 @@ module Riff
|
|
46
121
|
file.close
|
47
122
|
end
|
48
123
|
|
49
|
-
def int_to_four_little_endian_bytes(i) #:nodoc:
|
50
|
-
n =i # [ i.abs , 2^32 ].min
|
51
|
-
[(n.to_i & 0xff) , (n.to_i & 0xff00)>>8,
|
52
|
-
(n.to_i & 0xff0000)>>16,(n.to_i & 0xff000000)>>24 ]
|
53
|
-
end
|
54
|
-
|
55
|
-
def sanitize_fourcc(fourcc) #:nodoc:
|
56
|
-
fourcc[0,4].ljust(4,"\0")
|
57
|
-
end
|
58
|
-
|
59
124
|
end #class << self
|
60
125
|
|
61
126
|
# Add a data chunk to the Builder. The method yields a write-only pseudo-IO
|
@@ -63,14 +128,14 @@ module Riff
|
|
63
128
|
# here; the fourcc and size will be written for you. Do not pad the data you write to
|
64
129
|
# an even boundary, either.
|
65
130
|
def chunk(fourcc) #:yields: stream
|
66
|
-
@io.write(
|
67
|
-
4.times {@io.putc(0)}
|
131
|
+
@io.write( Util::sanitize_fourcc(fourcc) )
|
132
|
+
4.times { @io.putc(0) }
|
68
133
|
oldPos = @io.pos
|
69
134
|
yield IOProxy.new(@io)
|
70
135
|
length = @io.pos - oldPos
|
71
136
|
@io.putc(0) if (length % 2) == 1
|
72
137
|
@io.seek(oldPos-4,IO::SEEK_SET)
|
73
|
-
bytes =
|
138
|
+
bytes = Util::int_to_four_little_endian_bytes(length)
|
74
139
|
bytes.each {|byte| @io.putc(byte)}
|
75
140
|
@io.seek(0,IO::SEEK_END)
|
76
141
|
end
|
@@ -88,8 +153,8 @@ module Riff
|
|
88
153
|
end
|
89
154
|
|
90
155
|
def container(fourcc,type) # :nodoc:
|
91
|
-
chunk(
|
92
|
-
io.write(
|
156
|
+
chunk(Util::sanitize_fourcc(fourcc)) do |io|
|
157
|
+
io.write(Util::sanitize_fourcc(type))
|
93
158
|
yield io
|
94
159
|
end
|
95
160
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'riff/writer'
|
4
|
+
|
5
|
+
class RiffBuilder_Test < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
Riff::Builder.create("testfile.wav","WAVE") do |w|
|
9
|
+
w.list("INFO") { |info|
|
10
|
+
info.chunk("ICOP") {|c| # "copyright"
|
11
|
+
c << "00000000."
|
12
|
+
}
|
13
|
+
}
|
14
|
+
w.chunk("JUNK") { |c|
|
15
|
+
c << "00000000"
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
%x{rm testfile.wav}
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_file_made
|
26
|
+
assert(File.exist?("testfile.wav"))
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_length
|
30
|
+
assert_equal(58, File.stat("testfile.wav").size)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_file_fourcc
|
34
|
+
sig = IO.read("testfile.wav",4,0)
|
35
|
+
assert_equal("RIFF",sig)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_riff_chunk_size
|
39
|
+
File.open("testfile.wav",'r') do |f|
|
40
|
+
f.read(4);
|
41
|
+
assert_equal(50, Riff::Util::read_bytes_to_int(f,4) )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_icop_chunk
|
46
|
+
File.open("testfile.wav",'r') do |f|
|
47
|
+
f.read(24);
|
48
|
+
assert_equal('ICOP',f.read(4))
|
49
|
+
assert_equal(9, Riff::Util::read_bytes_to_int(f,4) )
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_info_chunk
|
54
|
+
File.open("testfile.wav",'r') do |f|
|
55
|
+
f.read(12);
|
56
|
+
assert_equal('LIST',f.read(4))
|
57
|
+
assert_equal(22, Riff::Util::read_bytes_to_int(f,4) )
|
58
|
+
assert_equal('INFO',f.read(4))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_file_sig
|
63
|
+
sig = IO.read("testfile.wav",4,8)
|
64
|
+
assert_equal("WAVE",sig)
|
65
|
+
end
|
66
|
+
|
67
|
+
end #class
|
data/test/riff_test.rb
CHANGED
@@ -18,7 +18,8 @@
|
|
18
18
|
#++
|
19
19
|
|
20
20
|
require 'test/unit'
|
21
|
-
|
21
|
+
|
22
|
+
require 'riff/reader'
|
22
23
|
|
23
24
|
class Riff_Test < Test::Unit::TestCase
|
24
25
|
|
@@ -37,7 +38,7 @@ class Riff_Test < Test::Unit::TestCase
|
|
37
38
|
def test_open_close
|
38
39
|
|
39
40
|
@test_media.each do |file|
|
40
|
-
@riff_obj_array << Riff::
|
41
|
+
@riff_obj_array << Riff::Reader.open(@test_media_basepath + file ,"r")
|
41
42
|
end
|
42
43
|
|
43
44
|
@riff_obj_array.each do |r|
|
@@ -46,23 +47,30 @@ class Riff_Test < Test::Unit::TestCase
|
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
50
|
+
def test_file_accessor
|
51
|
+
@test_media.each do |file|
|
52
|
+
r = Riff::Reader.open(@test_media_basepath + file , "r")
|
53
|
+
assert(r.file,"file accessor failed")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
49
57
|
def test_root
|
50
58
|
|
51
59
|
@test_media.each do |file|
|
52
|
-
Riff::
|
60
|
+
Riff::Reader.open(@test_media_basepath + file,"r") do |riff|
|
53
61
|
root_chunk = riff.root_chunk
|
54
62
|
|
55
63
|
assert_equal root_chunk.fourcc , "RIFF"
|
56
64
|
assert_equal root_chunk.signature , "WAVE"
|
57
|
-
assert_instance_of Riff::
|
65
|
+
assert_instance_of Riff::Reader::ListChunk , root_chunk
|
58
66
|
end
|
59
67
|
end
|
60
68
|
end
|
61
69
|
|
62
70
|
def test_hashing
|
63
|
-
Riff::
|
64
|
-
assert_instance_of Riff::
|
65
|
-
assert_instance_of Riff::
|
71
|
+
Riff::Reader.open(@test_media_basepath + @enumerable_file,"r") do |riff|
|
72
|
+
assert_instance_of Riff::Reader::Chunk , riff.root_chunk['bext']
|
73
|
+
assert_instance_of Riff::Reader::Chunk , riff.root_chunk['fmt ']
|
66
74
|
assert_equal riff.root_chunk[0].fourcc , 'bext'
|
67
75
|
assert_equal riff.root_chunk[0..1].collect {|c|c.fourcc} , ['bext','fmt ']
|
68
76
|
end
|
@@ -74,13 +82,13 @@ class Riff_Test < Test::Unit::TestCase
|
|
74
82
|
end
|
75
83
|
|
76
84
|
def test_simple_read
|
77
|
-
Riff::
|
85
|
+
Riff::Reader.open(@test_media_basepath + @enumerable_file,"r") do |riff|
|
78
86
|
assert_equal riff.root_chunk.length , 8272
|
79
87
|
end
|
80
88
|
end
|
81
89
|
|
82
90
|
def test_each_byte
|
83
|
-
Riff::
|
91
|
+
Riff::Reader.open(@test_media_basepath + @enumerable_file,"r") do |riff|
|
84
92
|
riff.root_chunk['fmt '].each_byte do |b|
|
85
93
|
assert b >= 0 and b <= 255
|
86
94
|
end
|
@@ -88,14 +96,14 @@ class Riff_Test < Test::Unit::TestCase
|
|
88
96
|
end
|
89
97
|
|
90
98
|
def test_is_list
|
91
|
-
Riff::
|
99
|
+
Riff::Reader.open(@test_media_basepath + @enumerable_file, 'r') do |r|
|
92
100
|
assert r.root_chunk.is_list?
|
93
101
|
assert_equal r.root_chunk['bext'].is_list? , false
|
94
102
|
end
|
95
103
|
end
|
96
104
|
|
97
105
|
def test_riff_enumerable
|
98
|
-
Riff::
|
106
|
+
Riff::Reader.open(@test_media_basepath + @enumerable_file, 'r') do |r|
|
99
107
|
|
100
108
|
count = 0
|
101
109
|
r.root_chunk.each_with_index do |chunk, i|
|
data/test/riff_test_suite.rb
CHANGED
data/test/wav_test.rb
CHANGED
@@ -18,27 +18,27 @@
|
|
18
18
|
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
19
19
|
#++
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
require 'test/unit'
|
24
|
-
require 'lib/riff/wav.rb'
|
25
|
-
|
26
|
-
class Wav_Test < Test::Unit::TestCase
|
27
|
-
|
28
|
-
def setup
|
29
|
-
@test_wav = "Pop.wav"
|
30
|
-
@test_path = "test_media/"
|
31
|
-
@bad_wav = "bad.riff"
|
32
|
-
end
|
33
|
-
|
34
|
-
def teardown
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_validation
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
end
|
21
|
+
#$: << 'lib/'
|
22
|
+
#
|
23
|
+
#require 'test/unit'
|
24
|
+
#require 'lib/riff/wav.rb'
|
25
|
+
#
|
26
|
+
#class Wav_Test < Test::Unit::TestCase
|
27
|
+
#
|
28
|
+
# def setup
|
29
|
+
# @test_wav = "Pop.wav"
|
30
|
+
# @test_path = "test_media/"
|
31
|
+
# @bad_wav = "bad.riff"
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# def teardown
|
35
|
+
#
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# def test_validation
|
39
|
+
#
|
40
|
+
#
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
#
|
44
|
+
#end
|
metadata
CHANGED
@@ -1,38 +1,33 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.1
|
3
|
-
specification_version: 1
|
4
2
|
name: riff
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version:
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
- lib
|
11
|
-
email:
|
12
|
-
homepage: http://riff.rubyforge.org
|
13
|
-
rubyforge_project: riff
|
14
|
-
description:
|
4
|
+
version: 0.3.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jamie Hardt
|
15
8
|
autorequire:
|
16
|
-
default_executable:
|
17
9
|
bindir: bin
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-22 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: jhardt@soundepartment.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
30
23
|
|
31
24
|
files:
|
32
25
|
- lib/riff/info.rb
|
33
26
|
- lib/riff/reader.rb
|
27
|
+
- lib/riff/util.rb
|
34
28
|
- lib/riff/writer.rb
|
35
29
|
- Rakefile
|
30
|
+
- test/builder_test.rb
|
36
31
|
- test/riff_test.rb
|
37
32
|
- test/riff_test_suite.rb
|
38
33
|
- test/wav_test.rb
|
@@ -41,17 +36,33 @@ files:
|
|
41
36
|
- examples/maketone.rb
|
42
37
|
- examples/metariff.rb
|
43
38
|
- examples/readchunks.rb
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
extra_rdoc_files: []
|
49
|
-
|
50
|
-
executables: []
|
39
|
+
has_rdoc: true
|
40
|
+
homepage: http://riff.rubyforge.org
|
41
|
+
licenses: []
|
51
42
|
|
52
|
-
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
53
45
|
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.8.2
|
53
|
+
version:
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
54
60
|
requirements: []
|
55
61
|
|
56
|
-
|
57
|
-
|
62
|
+
rubyforge_project: riff
|
63
|
+
rubygems_version: 1.3.5
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: Library for reading and writing RIFF (Resource Interchange File Format) files. RIFF is a meta-format which is a common wrapper for multimedia files, such as .wav and .avi files. Classes for reading and writing generic RIFF files are provided, as well as convenient INFO tag editing.
|
67
|
+
test_files:
|
68
|
+
- test/riff_test_suite.rb
|