1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
module WaveFile
module ChunkReaders
# Internal
class SampleChunkReader < BaseChunkReader # :nodoc:
def initialize(io, chunk_size)
@io = io
@chunk_size = chunk_size
end
def read
if @chunk_size < CORE_BYTE_COUNT
raise_error InvalidFormatError, "The sample chunk is incomplete; it contains fewer than the required number of fields."
end
raw_bytes = read_entire_chunk_body(CHUNK_IDS[:sample])
fields = {}
fields[:manufacturer_id],
fields[:product_id],
fields[:sample_nanoseconds],
fields[:midi_note],
fields[:fine_tuning_cents],
fields[:smpte_format],
smpte_offset_frames,
smpte_offset_seconds,
smpte_offset_minutes,
smpte_offset_hours,
loop_count,
sampler_data_size = raw_bytes.slice!(0...CORE_BYTE_COUNT).unpack("VVVVVVCCCcVV")
fields[:fine_tuning_cents] = (fields[:fine_tuning_cents] / 4_294_967_296.0) * 100
fields[:smpte_offset] = SMPTETimecode.new(hours: smpte_offset_hours,
minutes: smpte_offset_minutes,
seconds: smpte_offset_seconds,
frames: smpte_offset_frames)
fields[:loops] = []
loop_count.times do
if raw_bytes.length < LOOP_BYTE_COUNT
raise_error InvalidFormatError, "`smpl` chunk loop count is #{loop_count}, but it does not contain that many loops"
end
loop_fields = {}
loop_fields[:id],
loop_fields[:type],
loop_fields[:start_sample_frame],
loop_fields[:end_sample_frame],
loop_fields[:fraction],
loop_fields[:play_count] = raw_bytes.slice!(0...LOOP_BYTE_COUNT).unpack("VVVVVV")
loop_fields[:type] = loop_fields[:type]
loop_fields[:fraction] /= 4_294_967_296.0
fields[:loops] << SamplerLoop.new(**loop_fields)
end
if sampler_data_size > 0
if raw_bytes.length < sampler_data_size
raise_error InvalidFormatError, "`smpl` chunk \"sampler specific data\" field is smaller than expected."
end
fields[:sampler_specific_data] = raw_bytes.slice!(0...sampler_data_size)
else
fields[:sampler_specific_data] = ""
end
SamplerInfo.new(**fields)
end
private
CORE_BYTE_COUNT = 36
LOOP_BYTE_COUNT = 24
end
end
end
|