lib/scissor/sound_file.rb in scissor-0.4.0 vs lib/scissor/sound_file.rb in scissor-0.5.0
- old
+ new
@@ -1,6 +1,7 @@
require 'mp3info'
+require 'mp4info'
require 'pathname'
require 'riff/reader'
module Scissor
class SoundFile
@@ -42,13 +43,31 @@
def fmt
@fmt ||= riff.root_chunk['fmt ']
end
end
+ class M4a < SoundFile
+ def length
+ info.SECS_NOROUND
+ end
+
+ # FIXME
+ def mono?
+ false
+ end
+
+ private
+
+ def info
+ @info ||= MP4Info.open(@filename.to_s)
+ end
+ end
+
SUPPORTED_FORMATS = {
:mp3 => Mp3,
- :wav => Wav
+ :wav => Wav,
+ :m4a => M4a
}
class Error < StandardError; end
class UnknownFormat < Error; end
@@ -63,7 +82,40 @@
end
def initialize(filename)
@filename = Pathname.new(filename)
end
+ end
+end
+
+class MP4Info
+ private
+
+ def parse_mvhd(io_stream, level, size)
+ raise "Parse error" if size < 32
+ data = read_or_raise(io_stream, size, "Premature end of file")
+
+ version = data.unpack("C")[0] & 255
+ if (version == 0)
+ scale, duration = data[12..19].unpack("NN")
+ elsif (version == 1)
+ scale, hi, low = data[20..31].unpack("NNN")
+ duration = hi * (2**32) + low
+ else
+ return
+ end
+
+ printf " %sDur/Scl=#{duration}/#{scale}\n", ' ' * ( 2 * level ) if $DEBUG
+
+ secs = (duration * 1.0) / scale
+
+ # add
+ @info_atoms["SECS_NOROUND"] = secs
+
+ @info_atoms["SECS"] = (secs).round
+ @info_atoms["MM"] = (secs / 60).floor
+ @info_atoms["SS"] = (secs - @info_atoms["MM"] * 60).floor
+ @info_atoms["MS"] = (1000 * (secs - secs.floor)).round
+ @info_atoms["TIME"] = sprintf "%02d:%02d", @info_atoms["MM"],
+ @info_atoms["SECS"] - @info_atoms["MM"] * 60;
end
end