1 ############################################################################
2 # Copyright (C) 2008 by RafaĆ Rzepecki #
3 # divided.mind@gmail.com #
5 # This program is free software; you can redistribute it and#or modify #
6 # it under the terms of the GNU General Public License as published by #
7 # the Free Software Foundation; either version 2 of the License, or #
8 # (at your option) any later version. #
10 # This program 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 #
13 # GNU General Public License for more details. #
15 # You should have received a copy of the GNU General Public License #
16 # along with this program; if not, write to the #
17 # Free Software Foundation, Inc., #
18 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
19 ############################################################################
26 def self.get_dvid(mount_point)
27 File.open(File.join([mount_point, "mp3fm", "dvid.dat"])) {|f|
29 f.read(4).unpack("N")[0]
35 MPEG_VERSION = [:v2_5, :reserved, :v2, :v1]
36 LAYER = [:reserved, :layer3, :layer2, :layer1]
38 # v1l1 v1l2 v1l3 v2l1 v2l*
41 [ 64, 48, 40, 48, 16],
42 [ 96, 56, 48, 56, 24],
43 [ 128, 64, 56, 64, 32],
44 [ 160, 80, 64, 80, 40],
45 [ 192, 96, 80, 96, 48],
46 [ 224, 112, 96, 112, 56],
47 [ 256, 128, 112, 128, 64],
48 [ 288, 160, 128, 144, 80],
49 [ 320, 192, 160, 160, 96],
50 [ 352, 224, 192, 176, 112],
51 [ 384, 256, 224, 192, 128],
52 [ 416, 320, 256, 224, 144],
53 [ 448, 384, 320, 256, 160],
54 [ -1, -1, -1, -1, -1]].transpose
56 SAMPLING_RATE = { :v1 => [44100, 48000, 32000, -1],
57 :v2 => [22050, 24000, 16000, -1],
58 :v2_5 => [11025, 12000, 8000, -1] }
59 SAMPLE_PER_FRAME = { :v1 => [0, 1152, 1152, 384],
60 :v2 => [0, 576, 1152, 384],
61 :v2_5 => [0, 576, 1152, 384]}
72 elsif layer == :layer1
78 attr_reader :version, :layer, :tags, :bitrate, :length, :frames, :encoding
80 def initialize(filename)
81 @tags = ID3::AudioFile.new(filename)
82 @filename = File.basename(filename)
83 @file = File.new(filename)
84 @file.seek(@tags.audioStartX)
89 if @file.readchar == 0xFF
90 @tags.audioStartX = @file.pos
91 if (byte = @file.readchar) & 0xE0 == 0xE0
92 @version = MPEG_VERSION[(byte & 0x18) >> 3]
93 @layer = LAYER[(byte & 0x06) >> 1]
94 @has_crc = (byte & 1) == 0
95 @encoding = (byte & 0x1e) << 3
101 byte = @file.readchar
102 @bitrate = bitrates[(byte & 0xF0) >> 4]
106 @sampling_rate = SAMPLING_RATE[version][(byte & 0x0C) >> 2]
107 @is_padded = (byte & 2) == 2
108 @length = (tags.audioEndX - tags.audioStartX) * 8 / bitrate
109 @sample_per_frame = SAMPLE_PER_FRAME[version][LAYER.index(layer)]
110 @frames = @length * @sampling_rate / 1000 / @sample_per_frame
111 @framelen = bitrate * 1000 * @sample_per_frame / 8 / @sampling_rate
112 @encoding |= (byte & 0xF0) >> 4
114 @crc = @file.read(2).unpack("n")
116 if @sampling_rate > 0
120 @audioStartX, @audioEndX = tags.audioStartX, tags.audioEndX
121 mtags = tags.tagID3v2 || tags.tagID3v1
122 @tags = ID3::Tag2.new
123 mtags ||= ID3::Tag2.new
126 if v.class == ID3::Frame
134 @tags["ORIGFILENAME"] = "\3#{@filename}"
138 def putOnDevice(mount_point)
139 @dvid = NetworkWalkman.get_dvid(mount_point)
140 @slot = AudioFile.freeSlot(mount_point)
141 @filename = AudioFile.filename_for_slot(@slot, mount_point)
145 # def scramble(outfile)
146 # key = 0xFFFFFFFF & (( 0x2465 + @slot * 0x5296E435 ) ^ @dvid);
147 # @file.seek(@audioStartX)
148 # left = @audioEndX - @audioStartX
149 # while left > 0 and block = @file.read([8, left].min)
150 # if block.length != 8
153 # outfile << block.unpack("N2").map{|x|x^key}.pack("N2")
155 # left -= block.length