///|
/// A verified native frame location. Offsets refer to the original input.
pub(all) struct FrameLocation {
sample : Int64
offset : Int64
samples : Int32
bytes : Int32
}
///|
/// Build once, reuse against the same immutable native FLAC input.
pub(all) struct SeekIndex {
metadata : Metadata
frames : Array[FrameLocation]
total_samples : Int64
integrity : Integrity
}
///|
/// Validate a native stream and retain frame locations, not decoded PCM.
pub fn build_index(data : Bytes) -> SeekIndex raise FlacError {
if data.length() < 4 || data[:4] != b"fLaC" {
raise Invalid(0L, "frame byte index requires native FLAC input")
}
let decoder = Decoder::new()
let mut cursor = 0
let mut metadata = None
let frames = []
let mut total_samples = 0L
while true {
match decoder.next() {
MetadataReady(value) => metadata = Some(value)
AudioFrame(frame) => {
frames.push({
sample: frame.sample_number,
offset: frame.byte_offset,
samples: frame.block_size,
bytes: frame.byte_length,
})
total_samples += frame.block_size.to_int64()
}
LinkEnd(_) => raise Invalid(0L, "native index does not support Ogg links")
NeedInput =>
if cursor == data.length() {
decoder.finish()
} else {
let end = if data.length() - cursor > 16384 {
cursor + 16384
} else {
data.length()
}
cursor += decoder.push(data[cursor:end].to_owned())
}
Done(integrity) =>
match metadata {
Some(metadata) =>
return { metadata, frames, total_samples, integrity, }
None => raise Invalid(0L, "missing metadata")
}
}
} nobreak {
raise Invalid(0L, "index incomplete")
}
}
///|
/// Find the last indexed frame at or before sample, in logarithmic time.
pub fn SeekIndex::locate(self : SeekIndex, sample : Int64) -> FrameLocation? {
if sample < 0L || sample >= self.total_samples {
return None
}
let mut low = 0
let mut high = self.frames.length()
while low < high {
let mid = low + (high - low) / 2
if self.frames[mid].sample <= sample {
low = mid + 1
} else {
high = mid
}
}
if low == 0 {
None
} else {
Some(self.frames[low - 1])
}
}
///|
/// Crop a frame to the half-open absolute sample interval. Copies all planes.
pub fn crop_frame(frame : Frame, start : Int64, end : Int64) -> Frame? {
let first = if start > frame.sample_number {
start
} else {
frame.sample_number
}
let frame_end = frame.sample_number + frame.block_size.to_int64()
let last = if end < frame_end { end } else { frame_end }
if first >= last {
return None
}
let offset = (first - frame.sample_number).to_int()
let count = (last - first).to_int()
let channels = frame.channels.map(plane => {
Array::makei(count, i => plane[offset + i])
})
Some({ ..frame, sample_number: first, block_size: count, channels, })
}
///|
/// Seek through an existing index. The index must describe this exact input;
/// every selected frame CRC is checked again. Global MD5 comes from build_index.
pub fn decode_indexed_range(
data : Bytes,
index : SeekIndex,
start : Int64,
end : Int64,
) -> Audio raise FlacError {
if start < 0L || end < start || end > index.total_samples {
raise Invalid(0L, "sample interval is outside stream")
}
let frames = []
if start == end {
return { metadata: index.metadata, frames, integrity: index.integrity, }
}
let location = match index.locate(start) {
Some(location) => location
None => raise Invalid(0L, "sample location missing")
}
if location.offset < 0L || location.offset >= data.length().to_int64() {
raise Invalid(location.offset, "index offset is outside input")
}
let mut offset = location.offset.to_int()
let mut sample = location.sample
while sample < end {
let (frame, next) = parse_frame(
data,
offset,
index.metadata.info,
offset.to_int64(),
)
let frame = { ..frame, sample_number: sample, }
if crop_frame(frame, start, end) is Some(cropped) {
frames.push(cropped)
}
sample += frame.block_size.to_int64()
offset = next
}
{ metadata: index.metadata, frames, integrity: index.integrity, }
}
///|
/// Exact half-open interval, with whole-stream integrity verification.
/// Native FLAC uses a frame index; Ogg is demultiplexed sequentially.
pub fn decode_range(
data : Bytes,
start : Int64,
end : Int64,
) -> Audio raise FlacError {
if start < 0L || end < start {
raise Invalid(0L, "invalid sample interval")
}
if data.length() >= 4 && data[:4] == b"fLaC" {
return decode_indexed_range(data, build_index(data), start, end)
}
let links = decode_chained(data)
let mut total = 0L
let mut integrity = Md5Verified
let frames = []
for audio in links {
if audio.integrity != Md5Verified {
integrity = Md5Unavailable
}
for original in audio.frames {
let frame = { ..original, sample_number: total, }
total += frame.block_size.to_int64()
if crop_frame(frame, start, end) is Some(frame) {
frames.push(frame)
}
}
}
if end > total {
raise Invalid(0L, "sample interval is outside stream")
}
{ metadata: links[0].metadata, frames, integrity, }
}