WavFile.rb

view WavFile.rb @ 40:a324224bc098

maximize volume
author shokai <hashimoto@shokai.org>
date Sat Feb 06 15:14:02 2010 +0900 (4 weeks ago)
parents a5fa629da0be
children
line source
1 # -*- coding: utf-8 -*-
2 module WavFile
4 class WavFormatError < StandardError
5 end
7 class Chunk
8 attr_accessor(:name, :size, :data)
10 def initialize(file)
11 @name = file.read(4)
12 @size = file.read(4).unpack("V")[0].to_i
13 @data = file.read(@size)
14 end
16 def to_bin
17 @name + [@data.size].pack('V') + @data
18 end
19 end
21 class Format
22 attr_accessor(:id, :channel, :hz, :bytePerSec, :blockSize, :bitPerSample)
24 def initialize(chunk)
25 return if chunk.class != Chunk
26 return if chunk.name != 'fmt '
27 @id = chunk.data.slice(0,2)[0].to_i
28 @channel = chunk.data.slice(2,2)[0].to_i
29 @hz = chunk.data.slice(4,4).unpack('V').join.to_i
30 @bytePerSec = chunk.data.slice(8,4).unpack('V').join.to_i
31 @blockSize = chunk.data.slice(12,2)[0].to_i
32 @bitPerSample = chunk.data.slice(14,2)[0].to_i
33 end
35 def to_s
36 <<EOS
37 フォーマットID: #{@id}
38 チャンネル数: #{@channel}
39 サンプリングレート: #{@hz} (Hz)
40 byte per sec: #{@bytePerSec}
41 bit per sample: #{@bitPerSample}
42 ブロックサイズ: #{blockSize}
43 EOS
44 end
46 def to_bin
47 [@id].pack('v')+
48 [@channel].pack('v') +
49 [@hz].pack('V') +
50 [@bytePerSec].pack('V') +
51 [@blockSize].pack('v') +
52 [@bitPerSample].pack('v')
53 end
55 def ==(target)
56 @id == target.id &&
57 @channel == target.channel &&
58 @hz == target.hz &&
59 @bytePerSec == target.bytePerSec &&
60 @bitPerSample == target.bitPerSample &&
61 @blockSize == target.blockSize
62 end
64 end
66 def WavFile.readFormat(f)
67 f.binmode
68 f.seek(0)
69 header = f.read(12)
70 riff = header.slice(0,4)
71 data_size = header.slice(4,4).unpack('V')[0].to_i
72 wave = header.slice(8,4)
73 raise(WavFormatError) if riff != 'RIFF' or wave != 'WAVE'
75 formatChunk = Chunk.new(f)
76 Format.new(formatChunk)
77 end
79 def WavFile.readAll(f)
80 format = readFormat(f)
81 chunks = Array.new
82 while !f.eof?
83 chunk = Chunk.new(f)
84 chunks << chunk
85 end
86 return format, chunks
87 end
89 def WavFile.readDataChunk(f)
90 format, chunks = readAll(f)
91 chunks.each{|c|
92 return c if c.name == 'data'
93 }
94 return nil
95 end
97 def WavFile.read(f)
98 return readFormat(f), readDataChunk(f)
99 end
101 def WavFile.write(f, format, dataChunks)
102 header_file_size = 4
103 dataChunks.each{|c|
104 header_file_size += c.data.size + 8
105 }
106 f.write('RIFF' + [header_file_size].pack('V') + 'WAVE')
107 f.write("fmt ")
108 f.write([format.to_bin.size].pack('V'))
109 f.write(format.to_bin)
110 dataChunks.each{|c|
111 f.write(c.to_bin)
112 }
113 end
115 end