claxon/
lib.rs

1// Claxon -- A FLAC decoding library in Rust
2// Copyright 2014 Ruud van Asseldonk
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// A copy of the License has been included in the root of the repository.
7
8//! Claxon, a FLAC decoding library.
9//!
10//! Examples
11//! ========
12//!
13//! The following example computes the root mean square (RMS) of a FLAC file.
14//!
15//! ```
16//! # use claxon;
17//! let mut reader = claxon::FlacReader::open("testsamples/pop.flac").unwrap();
18//! let mut sqr_sum = 0.0;
19//! let mut count = 0;
20//! for sample in reader.samples() {
21//!     let s = sample.unwrap() as f64;
22//!     sqr_sum += s * s;
23//!     count += 1;
24//! }
25//! println!("RMS is {}", (sqr_sum / count as f64).sqrt());
26//! ```
27//!
28//! A simple way to decode a file to wav with Claxon and
29//! [Hound](https://github.com/ruuda/hound):
30//!
31//! ```
32//! # extern crate hound;
33//! # extern crate claxon;
34//! # use std::path::Path;
35//! # fn decode_file(fname: &Path) {
36//! let mut reader = claxon::FlacReader::open(fname).expect("failed to open FLAC stream");
37//!
38//! let spec = hound::WavSpec {
39//!     channels: reader.streaminfo().channels as u16,
40//!     sample_rate: reader.streaminfo().sample_rate,
41//!     bits_per_sample: reader.streaminfo().bits_per_sample as u16,
42//!     sample_format: hound::SampleFormat::Int,
43//! };
44//!
45//! let fname_wav = fname.with_extension("wav");
46//! let opt_wav_writer = hound::WavWriter::create(fname_wav, spec);
47//! let mut wav_writer = opt_wav_writer.expect("failed to create wav file");
48//!
49//! for opt_sample in reader.samples() {
50//!     let sample = opt_sample.expect("failed to decode FLAC stream");
51//!     wav_writer.write_sample(sample).expect("failed to write wav file");
52//! }
53//! # }
54//! ```
55//!
56//! Retrieving the artist metadata:
57//!
58//! ```
59//! # use claxon;
60//! let reader = claxon::FlacReader::open("testsamples/pop.flac").unwrap();
61//! for artist in reader.get_tag("ARTIST") {
62//!     println!("{}", artist);
63//! }
64//! ```
65//!
66//! For more examples, see the [examples](https://github.com/ruuda/claxon/tree/master/examples)
67//! directory in the crate.
68
69#![warn(missing_docs)]
70
71use std::fs;
72use std::io;
73use std::mem;
74use std::path;
75use error::fmt_err;
76use frame::FrameReader;
77use input::{BufferedReader, ReadBytes};
78use metadata::{MetadataBlock, MetadataBlockReader, StreamInfo, VorbisComment};
79
80mod crc;
81mod error;
82pub mod frame;
83pub mod input;
84pub mod metadata;
85pub mod subframe;
86
87pub use error::{Error, Result};
88pub use frame::Block;
89
90/// A FLAC decoder that can decode the stream from the underlying reader.
91///
92/// TODO: Add an example.
93pub struct FlacReader<R: io::Read> {
94    streaminfo: StreamInfo,
95    vorbis_comment: Option<VorbisComment>,
96    input: FlacReaderState<BufferedReader<R>>,
97}
98
99enum FlacReaderState<T> {
100    /// When the reader is positioned at the beginning of a frame.
101    Full(T),
102    /// When the reader might not be positioned at the beginning of a frame.
103    MetadataOnly(T),
104}
105
106/// Controls what metadata `FlacReader` reads when constructed.
107///
108/// The FLAC format contains a number of metadata blocks before the start of
109/// audio data. Reading these is wasteful if the data is never used. The
110/// `FlacReaderOptions` indicate which blocks to look for. As soon as all
111/// desired blocks have been read, `FlacReader::new_ext()` returns without
112/// reading remaining metadata blocks.
113///
114/// A few use cases:
115///
116/// * To read only the streaminfo, as quickly as possible, set `metadata_only`
117///   to true and `read_vorbis_comment` to false. The resulting reader cannot be
118///   used to read audio data.
119/// * To read only the streaminfo and tags, set `metadata_only` and
120///   `read_vorbis_comment` both to true. The resulting reader cannot be used to
121///   read audio data.
122#[derive(Copy, Clone, Debug, Eq, PartialEq)]
123pub struct FlacReaderOptions {
124    /// When true, return a reader as soon as all desired metadata has been read.
125    ///
126    /// If this is set, the `FlacReader` will not be able to read audio samples.
127    /// When reading audio is not desired anyway, enabling `metadata_only` can
128    /// save a lot of expensive reads.
129    ///
130    /// Defaults to false.
131    pub metadata_only: bool,
132
133    /// When true, read metadata blocks at least until a Vorbis comment block is found.
134    ///
135    /// When false, the `FlacReader` will be constructed without reading a
136    /// Vorbis comment block, even if the stream contains one. Consequently,
137    /// `FlacReader::tags()` and other tag-related methods will not return tag
138    /// data.
139    ///
140    /// Defaults to true.
141    pub read_vorbis_comment: bool,
142}
143
144impl Default for FlacReaderOptions {
145    fn default() -> FlacReaderOptions {
146        FlacReaderOptions {
147            read_vorbis_comment: true,
148            metadata_only: false,
149        }
150    }
151}
152
153impl FlacReaderOptions {
154    /// Return whether any metadata blocks need to be read.
155    fn has_desired_blocks(&self) -> bool {
156        // If we do not want only metadata, we want everything. Hence there are
157        // desired blocks left.
158        if !self.metadata_only {
159            return true
160        }
161
162        // Should be the or of all read_* fields, of which vorbis_comment is the
163        // only one at the moment.
164        self.read_vorbis_comment
165    }
166}
167
168/// An iterator that yields samples read from a `FlacReader`.
169pub struct FlacSamples<R: ReadBytes> {
170    frame_reader: FrameReader<R>,
171    block: Block,
172    sample: u32,
173    channel: u32,
174
175    /// If reading ever failed, this flag is set, so that the iterator knows not
176    /// to return any new values.
177    has_failed: bool,
178}
179
180// TODO: Add a `FlacIntoSamples`.
181
182fn read_stream_header<R: ReadBytes>(input: &mut R) -> Result<()> {
183    // A FLAC stream starts with a 32-bit header 'fLaC' (big endian).
184    const FLAC_HEADER: u32 = 0x66_4c_61_43;
185
186    // Some files start with ID3 tag data. The reference decoder supports this
187    // for convenience. Claxon does not, but we can at least generate a helpful
188    // error message if a file starts like this.
189    const ID3_HEADER: u32 = 0x49_44_33_00;
190
191    let header = try!(input.read_be_u32());
192    if header != FLAC_HEADER {
193        if (header & 0xff_ff_ff_00) == ID3_HEADER {
194            fmt_err("stream starts with ID3 header rather than FLAC header")
195        } else {
196            fmt_err("invalid stream header")
197        }
198    } else {
199        Ok(())
200    }
201}
202
203impl<R: io::Read> FlacReader<R> {
204    /// Create a reader that reads the FLAC format.
205    ///
206    /// The header and metadata blocks are read immediately. Audio frames
207    /// will be read on demand.
208    ///
209    /// Claxon rejects files that claim to contain excessively large metadata
210    /// blocks, to protect against denial of service attacks where a
211    /// small damaged or malicous file could cause gigabytes of memory
212    /// to be allocated. `Error::Unsupported` is returned in that case.
213    pub fn new(reader: R) -> Result<FlacReader<R>> {
214        FlacReader::new_ext(reader, FlacReaderOptions::default())
215    }
216
217    /// Create a reader that reads the FLAC format, with reader options.
218    ///
219    /// The header and metadata blocks are read immediately, but only as much as
220    /// specified in the options. See `FlacReaderOptions` for more details.
221    ///
222    /// Claxon rejects files that claim to contain excessively large metadata
223    /// blocks, to protect against denial of service attacks where a
224    /// small damaged or malicous file could cause gigabytes of memory
225    /// to be allocated. `Error::Unsupported` is returned in that case.
226    pub fn new_ext(reader: R, options: FlacReaderOptions) -> Result<FlacReader<R>> {
227        let mut buf_reader = BufferedReader::new(reader);
228        let mut opts_current = options;
229
230        // A flac stream first of all starts with a stream header.
231        try!(read_stream_header(&mut buf_reader));
232
233        // Start a new scope, because the input reader must be available again
234        // for the frame reader next.
235        let (streaminfo, vorbis_comment) = {
236            // Next are one or more metadata blocks. The flac specification
237            // dictates that the streaminfo block is the first block. The metadata
238            // block reader will yield at least one element, so the unwrap is safe.
239            let mut metadata_iter = MetadataBlockReader::new(&mut buf_reader);
240            let streaminfo_block = try!(metadata_iter.next().unwrap());
241            let streaminfo = match streaminfo_block {
242                MetadataBlock::StreamInfo(info) => info,
243                _ => return fmt_err("streaminfo block missing"),
244            };
245
246            let mut vorbis_comment = None;
247
248            // There might be more metadata blocks, read and store them.
249            for block_result in metadata_iter {
250                match try!(block_result) {
251                    MetadataBlock::VorbisComment(vc) => {
252                        // The Vorbis comment block need not be present, but
253                        // when it is, it must be unique.
254                        if vorbis_comment.is_some() {
255                            return fmt_err("encountered second Vorbis comment block")
256                        } else {
257                            vorbis_comment = Some(vc);
258                        }
259
260                        // We have one, no new one is desired.
261                        opts_current.read_vorbis_comment = false;
262                    }
263                    MetadataBlock::StreamInfo(..) => {
264                        return fmt_err("encountered second streaminfo block")
265                    }
266                    // Other blocks are currently not handled.
267                    _block => {}
268                }
269
270                // Early-out reading metadata once all desired blocks have been
271                // collected.
272                if !opts_current.has_desired_blocks() {
273                    break
274                }
275            }
276
277            // TODO: Rather than discarding afterwards, never parse it in the
278            // first place; treat it like padding in the MetadataBlockReader.
279            if !options.read_vorbis_comment {
280                vorbis_comment = None;
281            }
282
283            (streaminfo, vorbis_comment)
284        };
285
286        // Even if we might have read all metadata blocks, only set the state to
287        // "full" if `metadata_only` was false: this results in more predictable
288        // behavior.
289        let state = if options.metadata_only {
290            FlacReaderState::MetadataOnly(buf_reader)
291        } else {
292            FlacReaderState::Full(buf_reader)
293        };
294
295        // The flac reader will contain the reader that will read frames.
296        let flac_reader = FlacReader {
297            streaminfo: streaminfo,
298            vorbis_comment: vorbis_comment,
299            input: state,
300        };
301
302        Ok(flac_reader)
303    }
304
305    /// Returns the streaminfo metadata.
306    ///
307    /// This contains information like the sample rate and number of channels.
308    pub fn streaminfo(&self) -> StreamInfo {
309        self.streaminfo
310    }
311
312    /// Returns the vendor string of the Vorbis comment block, if present.
313    ///
314    /// This string usually contains the name and version of the program that
315    /// encoded the FLAC stream, such as `reference libFLAC 1.3.2 20170101`
316    /// or `Lavf57.25.100`.
317    pub fn vendor(&self) -> Option<&str> {
318        self.vorbis_comment.as_ref().map(|vc| &vc.vendor[..])
319    }
320
321    /// Returns name-value pairs of Vorbis comments, such as `("ARTIST", "Queen")`.
322    ///
323    /// The name is supposed to be interpreted case-insensitively, and is
324    /// guaranteed to consist of ASCII characters. Claxon does not normalize
325    /// the casing of the name. Use `get_tag()` to do a case-insensitive lookup.
326    ///
327    /// Names need not be unique. For instance, multiple `ARTIST` comments might
328    /// be present on a collaboration track.
329    ///
330    /// See <https://www.xiph.org/vorbis/doc/v-comment.html> for more details.
331    pub fn tags<'a>(&'a self) -> metadata::Tags<'a> {
332        match self.vorbis_comment.as_ref() {
333            Some(vc) => metadata::Tags::new(&vc.comments[..]),
334            None => metadata::Tags::new(&[]),
335        }
336    }
337
338    /// Look up a Vorbis comment such as `ARTIST` in a case-insensitive way.
339    ///
340    /// Returns an iterator,  because tags may occur more than once. There could
341    /// be multiple `ARTIST` tags on a collaboration track, for instance.
342    ///
343    /// Note that tag names are ASCII and never contain `'='`; trying to look up
344    /// a non-ASCII tag will return no results. Furthermore, the Vorbis comment
345    /// spec dictates that tag names should be handled case-insensitively, so
346    /// this method performs a case-insensitive lookup.
347    ///
348    /// See also `tags()` for access to the raw tags.
349    /// See <https://www.xiph.org/vorbis/doc/v-comment.html> for more details.
350    pub fn get_tag<'a>(&'a self, tag_name: &'a str) -> metadata::GetTag<'a> {
351        match self.vorbis_comment.as_ref() {
352            Some(vc) => metadata::GetTag::new(&vc.comments[..], tag_name),
353            None => metadata::GetTag::new(&[], tag_name),
354        }
355    }
356
357    /// Returns an iterator that decodes a single frame on every iteration.
358    /// TODO: It is not an iterator.
359    ///
360    /// This is a low-level primitive that gives you control over when decoding
361    /// happens. The representation of the decoded audio is somewhat specific to
362    /// the FLAC format. For a higher-level interface, see `samples()`.
363    pub fn blocks<'r>(&'r mut self) -> FrameReader<&'r mut BufferedReader<R>> {
364        match self.input {
365            FlacReaderState::Full(ref mut inp) => FrameReader::new(inp),
366            FlacReaderState::MetadataOnly(..) =>
367                panic!("FlacReaderOptions::metadata_only must be false \
368                       to be able to use FlacReader::blocks()"),
369        }
370    }
371
372    /// Returns an iterator over all samples.
373    ///
374    /// The channel data is is interleaved. The iterator is streaming. That is,
375    /// if you call this method once, read a few samples, and call this method
376    /// again, the second iterator will not start again from the beginning of
377    /// the file. It will continue somewhere after where the first iterator
378    /// stopped, and it might skip some samples. (This is because FLAC divides
379    /// a stream into blocks, which have to be decoded entirely. If you drop the
380    /// iterator, you lose the unread samples in that block.)
381    ///
382    /// This is a user-friendly interface that trades performance for ease of
383    /// use. If performance is an issue, consider using `blocks()` instead.
384    ///
385    /// This is a high-level interface to the decoder. The cost of retrieving
386    /// the next sample can vary significantly, as sometimes a new block has to
387    /// be decoded. Additionally, there is a cost to every iteration returning a
388    /// `Result`. When a block has been decoded, iterating the samples in that
389    /// block can never fail, but a match on every sample is required
390    /// nonetheless. For more control over when decoding happens, and less error
391    /// handling overhead, use `blocks()`.
392    pub fn samples<'r>(&'r mut self) -> FlacSamples<&'r mut BufferedReader<R>> {
393        match self.input {
394            FlacReaderState::Full(ref mut inp) => {
395                FlacSamples {
396                    frame_reader: frame::FrameReader::new(inp),
397                    block: Block::empty(),
398                    sample: 0,
399                    channel: 0,
400                    has_failed: false,
401                }
402            }
403            FlacReaderState::MetadataOnly(..) => {
404                panic!("FlacReaderOptions::metadata_only must be false \
405                       to be able to use FlacReader::samples()")
406            }
407        }
408    }
409
410    /// Destroys the FLAC reader and returns the underlying reader.
411    ///
412    /// Because the reader employs buffering internally, anything in the buffer
413    /// will be lost.
414    pub fn into_inner(self) -> R {
415        match self.input {
416            FlacReaderState::Full(inp) => inp.into_inner(),
417            FlacReaderState::MetadataOnly(inp) => inp.into_inner(),
418        }
419    }
420}
421
422impl FlacReader<fs::File> {
423    /// Attempts to create a reader that reads from the specified file.
424    ///
425    /// This is a convenience constructor that opens a `File`, and constructs a
426    /// `FlacReader` from it. There is no need to wrap the file in a
427    /// `BufReader`, as the `FlacReader` employs buffering already.
428    pub fn open<P: AsRef<path::Path>>(filename: P) -> Result<FlacReader<fs::File>> {
429        let file = try!(fs::File::open(filename));
430        FlacReader::new(file)
431    }
432
433    /// Attemps to create a reader that reads from the specified file.
434    ///
435    /// This is a convenience constructor that opens a `File`, and constructs a
436    /// `FlacReader` from it. There is no need to wrap the file in a
437    /// `BufReader`, as the `FlacReader` employs buffering already.
438    pub fn open_ext<P: AsRef<path::Path>>(filename: P,
439                                          options: FlacReaderOptions)
440                                          -> Result<FlacReader<fs::File>> {
441        let file = try!(fs::File::open(filename));
442        FlacReader::new_ext(file, options)
443    }
444}
445
446impl<R: ReadBytes> Iterator for FlacSamples<R> {
447    type Item = Result<i32>;
448
449    fn next(&mut self) -> Option<Result<i32>> {
450        // If the previous read failed, end iteration.
451        if self.has_failed {
452            return None;
453        }
454
455        // Iterate the samples channel interleaved, so first increment the
456        // channel.
457        self.channel += 1;
458
459        // If that was the last channel, increment the sample number.
460        if self.channel >= self.block.channels() {
461            self.channel = 0;
462            self.sample += 1;
463
464            // If that was the last sample in the block, decode the next block.
465            if self.sample >= self.block.duration() {
466                self.sample = 0;
467
468                // Replace the current block with an empty one so that we may
469                // reuse the current buffer to decode again.
470                let current_block = mem::replace(&mut self.block, Block::empty());
471
472                match self.frame_reader.read_next_or_eof(current_block.into_buffer()) {
473                    Ok(Some(next_block)) => {
474                        self.block = next_block;
475                    }
476                    Ok(None) => {
477                        // The stream ended with EOF.
478                        // TODO: If a number of samples was specified in the
479                        // streaminfo metadata block, verify that we did not
480                        // read more or less samples.
481                        return None;
482                    }
483                    Err(error) => {
484                        self.has_failed = true;
485                        return Some(Err(error));
486                    }
487                }
488            }
489        }
490
491        Some(Ok(self.block.sample(self.channel, self.sample)))
492    }
493}