diff --git a/Cargo.lock b/Cargo.lock index ad05d28..388d4f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,98 +1,100 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + [[package]] name = "alsa-sys" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9013f855a808ab924a4c08b5c1ec9bd6b04fdb2295b4d570fb723e0ed2802a4f" dependencies = [ - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "pkg-config", ] [[package]] name = "bitflags" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" [[package]] name = "coreaudio-rs" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f97dd1cb4381fc1d3a80f2c63ce965c4c936befe7051fd33289a2dc45914bda" dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "coreaudio-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "coreaudio-sys", + "libc", ] [[package]] name = "coreaudio-sys" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31231897622a4cd14cb211af6f26d6fcf0c78078fa60c586ce9db8f0b581cd44" dependencies = [ - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "cpal" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989df64d59c65f18776046436c3e50964699ec789e76b1af04f6fc32b6a2b713" dependencies = [ - "alsa-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "coreaudio-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "alsa-sys", + "coreaudio-rs", + "lazy_static", + "libc", + "ole32-sys", + "winapi", ] [[package]] name = "hound" version = "3.4.0" dependencies = [ - "cpal 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cpal", ] [[package]] name = "lazy_static" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9e1e434b35b61b6422b19998d5c219f6b4a90aae841583444b44077adb953b" [[package]] name = "libc" version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e" [[package]] name = "ole32-sys" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", + "winapi-build", ] [[package]] name = "pkg-config" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum alsa-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9013f855a808ab924a4c08b5c1ec9bd6b04fdb2295b4d570fb723e0ed2802a4f" -"checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" -"checksum coreaudio-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f97dd1cb4381fc1d3a80f2c63ce965c4c936befe7051fd33289a2dc45914bda" -"checksum coreaudio-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31231897622a4cd14cb211af6f26d6fcf0c78078fa60c586ce9db8f0b581cd44" -"checksum cpal 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "989df64d59c65f18776046436c3e50964699ec789e76b1af04f6fc32b6a2b713" -"checksum lazy_static 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f9e1e434b35b61b6422b19998d5c219f6b4a90aae841583444b44077adb953b" -"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e" -"checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/src/lib.rs b/src/lib.rs index 899a67d..01ef699 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,7 +88,7 @@ pub trait Sample: Sized { fn write_padded(self, writer: &mut W, bits: u16, byte_width: u16) -> Result<()>; /// Reads the audio sample from the WAVE data chunk. - fn read(reader: &mut R, SampleFormat, bytes: u16, bits: u16) -> Result; + fn read(reader: &mut R, format: SampleFormat, bytes: u16, bits: u16) -> Result; /// Cast the sample to a 16-bit sample. /// @@ -187,11 +187,11 @@ impl Sample for i8 { fn write_padded(self, writer: &mut W, bits: u16, byte_width: u16) -> Result<()> { match (bits, byte_width) { - (8, 1) => Ok(try!(writer.write_u8(u8_from_signed(self)))), - (16, 2) => Ok(try!(writer.write_le_i16(self as i16))), - (24, 3) => Ok(try!(writer.write_le_i24(self as i32))), - (24, 4) => Ok(try!(writer.write_le_i24_4(self as i32))), - (32, 4) => Ok(try!(writer.write_le_i32(self as i32))), + (8, 1) => Ok(writer.write_u8(u8_from_signed(self))?), + (16, 2) => Ok(writer.write_le_i16(self as i16)?), + (24, 3) => Ok(writer.write_le_i24(self as i32)?), + (24, 4) => Ok(writer.write_le_i24_4(self as i32)?), + (32, 4) => Ok(writer.write_le_i32(self as i32)?), _ => Err(Error::Unsupported), } } @@ -206,7 +206,7 @@ impl Sample for i8 { return Err(Error::InvalidSampleFormat); } match (bytes, bits) { - (1, 8) => Ok(try!(reader.read_u8().map(signed_from_u8))), + (1, 8) => Ok(reader.read_u8().map(signed_from_u8)?), (n, _) if n > 1 => Err(Error::TooWide), // TODO: add a genric decoder for any bit depth. _ => Err(Error::Unsupported), @@ -221,13 +221,11 @@ impl Sample for i16 { fn write_padded(self, writer: &mut W, bits: u16, byte_width: u16) -> Result<()> { match (bits, byte_width) { - (8, 1) => Ok(try!( - writer.write_u8(u8_from_signed(try!(narrow_to_i8(self as i32)))) - )), - (16, 2) => Ok(try!(writer.write_le_i16(self))), - (24, 3) => Ok(try!(writer.write_le_i24(self as i32))), - (24, 4) => Ok(try!(writer.write_le_i24_4(self as i32))), - (32, 4) => Ok(try!(writer.write_le_i32(self as i32))), + (8, 1) => Ok(writer.write_u8(u8_from_signed(narrow_to_i8(self as i32)?))?), + (16, 2) => Ok(writer.write_le_i16(self)?), + (24, 3) => Ok(writer.write_le_i24(self as i32)?), + (24, 4) => Ok(writer.write_le_i24_4(self as i32)?), + (32, 4) => Ok(writer.write_le_i32(self as i32)?), _ => Err(Error::Unsupported), } } @@ -242,8 +240,8 @@ impl Sample for i16 { return Err(Error::InvalidSampleFormat); } match (bytes, bits) { - (1, 8) => Ok(try!(reader.read_u8().map(signed_from_u8).map(|x| x as i16))), - (2, 16) => Ok(try!(reader.read_le_i16())), + (1, 8) => Ok(reader.read_u8().map(signed_from_u8).map(|x| x as i16)?), + (2, 16) => Ok(reader.read_le_i16()?), (n, _) if n > 2 => Err(Error::TooWide), // TODO: add a generic decoder for any bit depth. _ => Err(Error::Unsupported), @@ -258,13 +256,11 @@ impl Sample for i32 { fn write_padded(self, writer: &mut W, bits: u16, byte_width: u16) -> Result<()> { match (bits, byte_width) { - (8, 1) => Ok(try!( - writer.write_u8(u8_from_signed(try!(narrow_to_i8(self)))) - )), - (16, 2) => Ok(try!(writer.write_le_i16(try!(narrow_to_i16(self))))), - (24, 3) => Ok(try!(writer.write_le_i24(try!(narrow_to_i24(self))))), - (24, 4) => Ok(try!(writer.write_le_i24_4(try!(narrow_to_i24(self))))), - (32, 4) => Ok(try!(writer.write_le_i32(self))), + (8, 1) => Ok(writer.write_u8(u8_from_signed(narrow_to_i8(self)?))?), + (16, 2) => Ok(writer.write_le_i16(narrow_to_i16(self)?)?), + (24, 3) => Ok(writer.write_le_i24(narrow_to_i24(self)?)?), + (24, 4) => Ok(writer.write_le_i24_4(narrow_to_i24(self)?)?), + (32, 4) => Ok(writer.write_le_i32(self)?), _ => Err(Error::Unsupported), } } @@ -279,11 +275,11 @@ impl Sample for i32 { return Err(Error::InvalidSampleFormat); } match (bytes, bits) { - (1, 8) => Ok(try!(reader.read_u8().map(signed_from_u8).map(|x| x as i32))), - (2, 16) => Ok(try!(reader.read_le_i16().map(|x| x as i32))), - (3, 24) => Ok(try!(reader.read_le_i24())), - (4, 24) => Ok(try!(reader.read_le_i24_4())), - (4, 32) => Ok(try!(reader.read_le_i32())), + (1, 8) => Ok(reader.read_u8().map(signed_from_u8).map(|x| x as i32)?), + (2, 16) => Ok(reader.read_le_i16().map(|x| x as i32)?), + (3, 24) => Ok(reader.read_le_i24()?), + (4, 24) => Ok(reader.read_le_i24_4()?), + (4, 32) => Ok(reader.read_le_i32()?), (n, _) if n > 4 => Err(Error::TooWide), // TODO: add a generic decoder for any bit depth. _ => Err(Error::Unsupported), @@ -298,7 +294,7 @@ impl Sample for f32 { fn write_padded(self, writer: &mut W, bits: u16, byte_width: u16) -> Result<()> { match (bits, byte_width) { - (32, 4) => Ok(try!(writer.write_le_f32(self))), + (32, 4) => Ok(writer.write_le_f32(self)?), _ => Err(Error::Unsupported), } } @@ -311,7 +307,7 @@ impl Sample for f32 { match fmt { SampleFormat::Float => match (bytes, bits) { - (4, 32) => Ok(try!(reader.read_le_f32())), + (4, 32) => Ok(reader.read_le_f32()?), (n, _) if n > 4 => Err(Error::TooWide), _ => Err(Error::Unsupported), }, @@ -319,9 +315,9 @@ impl Sample for f32 { // 32-bit IEEE floats can represent signed integers up to 24 bits wide exactly // (actually: 25 bits). match (bytes, bits) { - (1, 8) => Ok(try!(reader.read_u8().map(signed_from_u8).map(|x| x as f32))), - (2, 16) => Ok(try!(reader.read_le_i16().map(|x| x as f32))), - (3, 24) => Ok(try!(reader.read_le_i24()) as f32), + (1, 8) => Ok(reader.read_u8().map(signed_from_u8).map(|x| x as f32)?), + (2, 16) => Ok(reader.read_le_i16().map(|x| x as f32)?), + (3, 24) => Ok(reader.read_le_i24()? as f32), (n, _) if n > 3 => Err(Error::TooWide), // TODO: add a generic decoder for any bit depth. _ => Err(Error::Unsupported), @@ -362,6 +358,79 @@ pub struct WavSpec { pub sample_format: SampleFormat, } +/// Ill-formed WAVE data was encountered. +#[derive(Debug)] +pub struct FormatError(pub &'static str); + +impl fmt::Display for FormatError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Ill-formed WAVE file: {}", self.0) + } +} + +impl error::Error for FormatError{} + +/// The sample has more bits than the destination type. +/// +/// When iterating using the `samples` iterator, this means that the +/// destination type (produced by the iterator) is not wide enough to hold +/// the sample. When writing, this means that the sample cannot be written, +/// because it requires more bits than the bits per sample specified. +#[derive(Debug)] +pub struct TooWideError; + +impl fmt::Display for TooWideError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "The sample has more bits than the destination type") + } +} + +impl error::Error for TooWideError {} + +/// The number of samples written is not a multiple of the number of channels. +#[derive(Debug)] +pub struct UnfinishedSampleError; + +impl fmt::Display for UnfinishedSampleError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "The number of samples written is not a multiple of the number of channels") + } +} + +impl error::Error for UnfinishedSampleError {} + +/// The format is not supported. +#[derive(Debug)] +pub struct UnsupportedError; + +impl fmt::Display for UnsupportedError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "The wave format of the file is not supported") + } +} + +impl error::Error for UnsupportedError {} + +/// The sample format is different than the destination format. +/// +/// When iterating using the `samples` iterator, this means the destination +/// type (produced by the iterator) has a different sample format than the +/// samples in the wav file. +/// +/// For example, this will occur if the user attempts to produce `i32` +/// samples (which have a `SampleFormat::Int`) from a wav file that +/// contains floating point data (`SampleFormat::Float`). +#[derive(Debug)] +pub struct InvalidSampleFormatError; + +impl fmt::Display for InvalidSampleFormatError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "The sample format differs from the destination format") + } +} + +impl error::Error for InvalidSampleFormatError {} + /// The error type for operations on `WavReader` and `WavWriter`. #[derive(Debug)] pub enum Error { @@ -393,50 +462,40 @@ pub enum Error { } impl fmt::Display for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { + fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { match *self { - Error::IoError(ref err) => err.fmt(formatter), - Error::FormatError(reason) => { - try!(formatter.write_str("Ill-formed WAVE file: ")); - formatter.write_str(reason) - } + Error::IoError(ref err) => err.fmt(f), + Error::FormatError(reason) => write!(f, "Ill-formed WAVE file: {}", reason), Error::TooWide => { - formatter.write_str("The sample has more bits than the destination type.") + f.write_str("The sample has more bits than the destination type.") } Error::UnfinishedSample => { - formatter.write_str( + f.write_str( "The number of samples written is not a multiple of the number of channels.") } Error::Unsupported => { - formatter.write_str("The wave format of the file is not supported.") + f.write_str("The wave format of the file is not supported.") } Error::InvalidSampleFormat => { - formatter.write_str("The sample format differs from the destination format.") + f.write_str("The sample format differs from the destination format.") } } } } impl error::Error for Error { - fn description(&self) -> &str { - match *self { - Error::IoError(ref err) => err.description(), - Error::FormatError(reason) => reason, - Error::TooWide => "the sample has more bits than the destination type", - Error::UnfinishedSample => "the number of samples written is not a multiple of the number of channels", - Error::Unsupported => "the wave format of the file is not supported", - Error::InvalidSampleFormat => "the sample format differs from the destination format", - } - } - - fn cause(&self) -> Option<&error::Error> { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { Error::IoError(ref err) => Some(err), Error::FormatError(_) => None, - Error::TooWide => None, - Error::UnfinishedSample => None, - Error::Unsupported => None, - Error::InvalidSampleFormat => None, + Error::TooWide => Some(&TooWideError), + Error::UnfinishedSample => Some(&UnfinishedSampleError), + Error::Unsupported => Some(&UnsupportedError), + Error::InvalidSampleFormat => Some(&InvalidSampleFormatError), + //Error::TooWide => "the sample has more bits than the destination type", + //Error::UnfinishedSample => "the number of samples written is not a multiple of the number of channels", + //Error::Unsupported => "the wave format of the file is not supported", + //Error::InvalidSampleFormat => "the sample format differs from the destination format", } } } @@ -447,6 +506,36 @@ impl From for Error { } } +impl From for Error { + fn from(err: FormatError) -> Error { + Error::FormatError(err.0) + } +} + +impl From for Error { + fn from(_: TooWideError) -> Error { + Error::TooWide + } +} + +impl From for Error { + fn from(_: UnfinishedSampleError) -> Error { + Error::UnfinishedSample + } +} + +impl From for Error { + fn from(_: UnsupportedError) -> Error { + Error::Unsupported + } +} + +impl From for Error { + fn from(_: InvalidSampleFormatError) -> Error { + Error::InvalidSampleFormat + } +} + /// A type for results generated by Hound where the error type is hard-wired. pub type Result = result::Result; diff --git a/src/read.rs b/src/read.rs index c19361d..282201e 100644 --- a/src/read.rs +++ b/src/read.rs @@ -14,7 +14,6 @@ use std::cmp; use std::fs; use std::io; use std::marker; -use std::mem; use std::path; use super::{Error, Result, Sample, SampleFormat, WavSpec}; @@ -79,7 +78,7 @@ impl ReadExt for R fn read_into(&mut self, buf: &mut [u8]) -> io::Result<()> { let mut n = 0; while n < buf.len() { - let progress = try!(self.read(&mut buf[n..])); + let progress = self.read(&mut buf[n..])?; if progress > 0 { n += progress; } else { @@ -99,7 +98,7 @@ impl ReadExt for R let mut buf = [0u8; 1024]; while n_read < n { let end = cmp::min(n - n_read, 1024); - let progress = try!(self.read(&mut buf[0..end])); + let progress = self.read(&mut buf[0..end])?; if progress > 0 { n_read += progress; } else { @@ -112,7 +111,7 @@ impl ReadExt for R #[inline(always)] fn read_4_bytes(&mut self) -> io::Result<[u8; 4]> { let mut buf = [0_u8; 4]; - try!(self.read_into(&mut buf[..])); + self.read_into(&mut buf[..])?; Ok(buf) } @@ -124,7 +123,7 @@ impl ReadExt for R #[inline(always)] fn read_u8(&mut self) -> io::Result { let mut buf = [0u8; 1]; - try!(self.read_into(&mut buf)); + self.read_into(&mut buf)?; Ok(buf[0]) } @@ -136,7 +135,7 @@ impl ReadExt for R #[inline(always)] fn read_le_u16(&mut self) -> io::Result { let mut buf = [0u8; 2]; - try!(self.read_into(&mut buf)); + self.read_into(&mut buf)?; Ok((buf[1] as u16) << 8 | (buf[0] as u16)) } @@ -169,7 +168,7 @@ impl ReadExt for R #[inline(always)] fn read_le_u24(&mut self) -> io::Result { let mut buf = [0u8; 3]; - try!(self.read_into(&mut buf)); + self.read_into(&mut buf)?; Ok((buf[2] as u32) << 16 | (buf[1] as u32) << 8 | (buf[0] as u32)) } @@ -181,7 +180,7 @@ impl ReadExt for R #[inline(always)] fn read_le_u32(&mut self) -> io::Result { let mut buf = [0u8; 4]; - try!(self.read_into(&mut buf)); + self.read_into(&mut buf)?; Ok((buf[3] as u32) << 24 | (buf[2] as u32) << 16 | (buf[1] as u32) << 8 | (buf[0] as u32) << 0) } @@ -189,7 +188,7 @@ impl ReadExt for R #[inline(always)] fn read_le_f32(&mut self) -> io::Result { let mut buf = [0u8; 4]; - try!(self.read_into(&mut buf)); + self.read_into(&mut buf)?; Ok(f32::from_le_bytes(buf)) } } @@ -205,7 +204,7 @@ pub struct ChunkReadingState { impl ChunkReadingState { fn read(&mut self, reader: &mut R, buffer: &mut[u8]) -> io::Result { let max = cmp::min(buffer.len(), self.remaining as usize); - let read = try!(reader.read(&mut buffer[0..max])); + let read = reader.read(&mut buffer[0..max])?; self.remaining -= read as u64; Ok(read) } @@ -308,7 +307,7 @@ impl ChunksReader { /// This function will only read the Riff header from the file /// in order to position the stream to the first chunk. pub fn new(mut reader: R) -> Result> { - try!(read_wave_header(&mut reader)); + read_wave_header(&mut reader)?; Ok(ChunksReader { reader: reader, spec_ex: None, @@ -367,7 +366,7 @@ impl ChunksReader { /// keep track of the audio samples parsing. pub fn next(&mut self) -> Result>> { if let Some(ref mut data) = self.data_state { - try!(data.chunk.skip_remaining(&mut self.reader)) + data.chunk.skip_remaining(&mut self.reader)? } self.data_state = None; let mut kind_str = [0; 4]; @@ -375,10 +374,10 @@ impl ChunksReader { // FIXME EOF is indistinguishable from actual errors in read_into return Ok(None); } - let len = try!(self.reader.read_le_u32()); + let len = self.reader.read_le_u32()?; match &kind_str { b"fmt " => { - let spec_ex = try!(self.read_fmt_chunk(len)); + let spec_ex = self.read_fmt_chunk(len)?; self.spec_ex = Some(spec_ex); Ok(Some(Chunk::Fmt(spec_ex))) } @@ -424,7 +423,7 @@ impl ChunksReader { /// Returns true if a data chunk has been found. Afterwards, the reader /// will be positioned at the first content byte of the data chunk. pub fn read_until_data(&mut self) -> Result { - while let Some(chunk) = try!(self.next()) { + while let Some(chunk) = self.next()? { if let Chunk::Data = chunk { return Ok(true) } @@ -479,12 +478,12 @@ impl ChunksReader { // is misleading though, because it is the number of bits used to store // a sample, not all of the bits need to be valid for all versions of // the WAVE format.) - let format_tag = try!(self.reader.read_le_u16()); - let n_channels = try!(self.reader.read_le_u16()); - let n_samples_per_sec = try!(self.reader.read_le_u32()); - let n_bytes_per_sec = try!(self.reader.read_le_u32()); - let block_align = try!(self.reader.read_le_u16()); - let bits_per_sample = try!(self.reader.read_le_u16()); + let format_tag = self.reader.read_le_u16()?; + let n_channels = self.reader.read_le_u16()?; + let n_samples_per_sec = self.reader.read_le_u32()?; + let n_bytes_per_sec = self.reader.read_le_u32()?; + let block_align = self.reader.read_le_u16()?; + let bits_per_sample = self.reader.read_le_u16()?; if n_channels == 0 { return Err(Error::FormatError("file contains zero channels")); @@ -530,10 +529,10 @@ impl ChunksReader { const EXTENSIBLE: u16 = 0xfffe; // We may update our WavSpec based on more data we read from the header. match format_tag { - PCM => try!(self.read_wave_format_pcm(chunk_len, &spec)), + PCM => self.read_wave_format_pcm(chunk_len, &spec)?, ADPCM => return Err(Error::Unsupported), - IEEE_FLOAT => try!(self.read_wave_format_ieee_float(chunk_len, &mut spec)), - EXTENSIBLE => try!(self.read_wave_format_extensible(chunk_len, &mut spec)), + IEEE_FLOAT => self.read_wave_format_ieee_float(chunk_len, &mut spec)?, + EXTENSIBLE => self.read_wave_format_extensible(chunk_len, &mut spec)?, _ => return Err(Error::Unsupported), }; @@ -560,7 +559,7 @@ impl ChunksReader { // additional data. However, for WAVE_FORMAT_PCM, the member should // be ignored, see https://msdn.microsoft.com/en-us/library/ms713497.aspx. // Nonzero values do in fact occur in practice. - let _cb_size = try!(self.reader.read_le_u16()); + let _cb_size = self.reader.read_le_u16()?; // For WAVE_FORMAT_PCM in WAVEFORMATEX, only 8 or 16 bits per // sample are valid according to @@ -578,7 +577,7 @@ impl ChunksReader { // If the chunk len was longer than expected, ignore the additional bytes. if chunk_len == 40 { - try!(self.reader.skip_bytes(22)); + self.reader.skip_bytes(22)?; } Ok(()) } @@ -595,7 +594,7 @@ impl ChunksReader { if is_wave_format_ex { // For WAVE_FORMAT_IEEE_FLOAT which we are reading, there should // be no extra data, so `cbSize` should be 0. - let cb_size = try!(self.reader.read_le_u16()); + let cb_size = self.reader.read_le_u16()?; if cb_size != 0 { return Err(Error::FormatError("unexpected WAVEFORMATEX size")); } @@ -624,7 +623,7 @@ impl ChunksReader { } // `cbSize` is the last field of the WAVEFORMATEX struct. - let cb_size = try!(self.reader.read_le_u16()); + let cb_size = self.reader.read_le_u16()?; // `cbSize` must be at least 22, but in this case we assume that it is // 22, because we would not know how to handle extra data anyway. @@ -646,10 +645,10 @@ impl ChunksReader { // GUID SubFormat; // } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE; // ``` - let valid_bits_per_sample = try!(self.reader.read_le_u16()); - let _channel_mask = try!(self.reader.read_le_u32()); // Not used for now. + let valid_bits_per_sample = self.reader.read_le_u16()?; + let _channel_mask = self.reader.read_le_u32()?; // Not used for now. let mut subformat = [0u8; 16]; - try!(self.reader.read_into(&mut subformat)); + self.reader.read_into(&mut subformat)?; // Several GUIDS are defined. At the moment, only the following are supported: // @@ -691,7 +690,7 @@ impl ChunksReader { let data = self.data_state.as_mut().expect("Not in the data chunk."); let wanted_sample = time as i64 * data.spec_ex.spec.channels as i64; let wanted_byte = wanted_sample * data.spec_ex.bytes_per_sample as i64; - try!(data.chunk.seek(&mut self.reader, io::SeekFrom::Start(wanted_byte as u64))); + data.chunk.seek(&mut self.reader, io::SeekFrom::Start(wanted_byte as u64))?; Ok(()) } } @@ -764,14 +763,14 @@ pub fn read_wave_header(reader: &mut R) -> Result { // into it is more cumbersome, but also avoids a heap allocation. Is // the compiler smart enough to avoid the heap allocation anyway? I // would not expect it to be. - if b"RIFF" != &try!(reader.read_4_bytes())[..] { + if b"RIFF" != &reader.read_4_bytes()?[..] { return Err(Error::FormatError("no RIFF tag found")); } - let file_len = try!(reader.read_le_u32()); + let file_len = reader.read_le_u32()?; // Next four bytes indicate the file type, which should be WAVE. - if b"WAVE" != &try!(reader.read_4_bytes())[..] { + if b"WAVE" != &reader.read_4_bytes()?[..] { return Err(Error::FormatError("no WAVE tag found")); } @@ -788,8 +787,8 @@ impl WavReader /// The header is read immediately. Reading the data will be done on /// demand. pub fn new(reader: R) -> Result> { - let mut reader = try!(ChunksReader::new(reader)); - try!(reader.read_until_data()); + let mut reader = ChunksReader::new(reader)?; + reader.read_until_data()?; if reader.spec_ex.is_none() { return Err(Error::FormatError("Wave file with no fmt header")) } @@ -881,7 +880,7 @@ impl WavReader> { /// This is a convenience constructor that opens a `File`, wraps it in a /// `BufReader` and then constructs a `WavReader` from it. pub fn open>(filename: P) -> Result>> { - let file = try!(fs::File::open(filename)); + let file = fs::File::open(filename)?; let buf_reader = io::BufReader::new(file); WavReader::new(buf_reader) } diff --git a/src/write.rs b/src/write.rs index db04287..3100b72 100644 --- a/src/write.rs +++ b/src/write.rs @@ -190,7 +190,7 @@ impl<'w, W: 'w + io::Write + io::Seek> Write for EmbeddedWriter<'w, W> { /// Flushes the writer, updating the chunk header in the process. fn flush(&mut self) -> io::Result<()> { let &mut EmbeddedWriter { ref mut writer, ref mut state, .. } = self; - try!(state.update_header(writer)); + state.update_header(writer)?; writer.flush() } @@ -211,22 +211,22 @@ pub struct ChunkWritingState { impl ChunkWritingState { pub fn write(&mut self, writer: &mut W, buf:&[u8]) -> io::Result { - let written = try!(writer.write(buf)); + let written = writer.write(buf)?; self.len += written as u32; Ok(written) } pub fn update_header(&mut self, writer: &mut W) -> io::Result<()> { - try!(writer.seek(io::SeekFrom::Current(-(self.len as i64 + 4)))); - try!(writer.write_le_u32(self.len)); - try!(writer.seek(io::SeekFrom::Current(self.len as i64))); + writer.seek(io::SeekFrom::Current(-(self.len as i64 + 4)))?; + writer.write_le_u32(self.len)?; + writer.seek(io::SeekFrom::Current(self.len as i64))?; Ok(()) } pub fn finalize_chunk(&mut self, writer: &mut W) -> io::Result<()> { - try!(self.update_header(writer)); + self.update_header(writer)?; if self.len % 2 == 1 { - try!(writer.write_u8(0)); + writer.write_u8(0)?; } Ok(()) } @@ -252,7 +252,7 @@ impl ChunksWriter { /// Write the RIFF header (including a len placeholder). The writer /// is then ready to start writing the first chunk. pub fn new(mut writer: W) -> Result> { - try!(writer.write_all(b"RIFF\0\0\0\0WAVE")); + writer.write_all(b"RIFF\0\0\0\0WAVE")?; Ok(ChunksWriter { writer: writer, spec_ex: None, @@ -266,10 +266,10 @@ impl ChunksWriter { /// /// The writer is then repositioned at end of file. fn update_riff_header(&mut self) -> io::Result<()> { - let full_len = try!(self.writer.seek(io::SeekFrom::Current(0))); - try!(self.writer.seek(io::SeekFrom::Start(4))); - try!(self.writer.write_le_u32(full_len as u32 - 8)); - try!(self.writer.seek(io::SeekFrom::Current(full_len as i64 - 8))); + let full_len = self.writer.seek(io::SeekFrom::Current(0))?; + self.writer.seek(io::SeekFrom::Start(4))?; + self.writer.write_le_u32(full_len as u32 - 8)?; + self.writer.seek(io::SeekFrom::Current(full_len as i64 - 8))?; Ok(()) } @@ -286,9 +286,9 @@ impl ChunksWriter { fn update_data_chunk_header(&mut self) -> Result<()> { let data_state = self.data_state.expect("Should only be called in data chunk"); let spec_ex = self.spec_ex.expect("Data chunk implies known format"); - try!(self.writer.seek(io::SeekFrom::End(-(data_state.len as i64 + 4)))); - try!(self.writer.write_le_u32(data_state.len)); - try!(self.writer.seek(io::SeekFrom::End(0))); + self.writer.seek(io::SeekFrom::End(-(data_state.len as i64 + 4)))?; + self.writer.write_le_u32(data_state.len)?; + self.writer.seek(io::SeekFrom::End(0))?; // Signal error if the last sample was not finished, but do so after // everything has been written, so that no data is lost, even though @@ -309,8 +309,8 @@ impl ChunksWriter { pub fn start_chunk(&mut self, fourcc:[u8;4]) -> Result> { self.data_state = None; self.dirty = true; - try!(self.writer.write_all(&fourcc)); - try!(self.writer.write_le_u32(0)); + self.writer.write_all(&fourcc)?; + self.writer.write_le_u32(0)?; Ok(EmbeddedWriter { writer: &mut self.writer, state: ChunkWritingState { len: 0 }, @@ -323,8 +323,8 @@ impl ChunksWriter { if self.spec_ex.is_none() { panic!("Format must be written before data"); } - try!(self.writer.write_all(b"data")); - try!(self.writer.write_le_u32(0)); + self.writer.write_all(b"data")?; + self.writer.write_le_u32(0)?; self.data_state = Some(ChunkWritingState { len: 0 }); self.dirty = true; Ok(()) @@ -333,10 +333,10 @@ impl ChunksWriter { /// Update RIFF and data chunk header pub fn update_headers(&mut self) -> Result<()> { if self.data_state.is_some() { - try!(self.update_data_chunk_header()) + self.update_data_chunk_header()? } if self.dirty { - try!(self.update_riff_header()); + self.update_riff_header()?; self.dirty = false; } Ok(()) @@ -347,8 +347,8 @@ impl ChunksWriter { /// Before actually flushing the function will update the overall RIFF /// header and the data chunk header if required. pub fn flush(&mut self) -> Result<()> { - try!(self.update_headers()); - try!(self.writer.flush()); + self.update_headers()?; + self.writer.flush()?; Ok(()) } @@ -362,7 +362,7 @@ impl ChunksWriter { // the writer is dropped: for a buffered writer, the write to the buffer // may succeed, but the write to the underlying writer may fail. So // flush explicitly. - try!(self.flush()); + self.flush()?; Ok(()) } @@ -396,20 +396,20 @@ impl ChunksWriter { } let mut header = [0u8; 48]; - try!(self.writer.write(b"fmt ")); + self.writer.write(b"fmt ")?; let written = { let mut buffer = io::Cursor::new(&mut header[..]); match fmt_kind { FmtKind::PcmWaveFormat => { - try!(Self::write_pcmwaveformat(spec_ex, &mut buffer)); + Self::write_pcmwaveformat(spec_ex, &mut buffer)?; } FmtKind::WaveFormatExtensible => { - try!(Self::write_waveformatextensible(spec_ex, &mut buffer)); + Self::write_waveformatextensible(spec_ex, &mut buffer)?; } } buffer.position() }; - try!(self.writer.write_all(&header[..written as usize])); + self.writer.write_all(&header[..written as usize])?; self.spec_ex = Some(spec_ex); @@ -419,7 +419,7 @@ impl ChunksWriter { /// Writes the content of the fmt chunk as PCMWAVEFORMAT struct. fn write_pcmwaveformat(spec: WavSpecEx, buffer: &mut io::Cursor<&mut [u8]>) -> io::Result<()> { // Write the size of the WAVE header chunk. - try!(buffer.write_le_u32(16)); + buffer.write_le_u32(16)?; // The following is based on the PCMWAVEFORMAT struct as documented at // https://msdn.microsoft.com/en-us/library/ms712832.aspx. See also @@ -429,12 +429,12 @@ impl ChunksWriter { match spec.spec.sample_format { // WAVE_FORMAT_PCM SampleFormat::Int => { - try!(buffer.write_le_u16(1)); + buffer.write_le_u16(1)?; }, // WAVE_FORMAT_IEEE_FLOAT SampleFormat::Float => { if spec.spec.bits_per_sample == 32 { - try!(buffer.write_le_u16(3)); + buffer.write_le_u16(3)?; } else { panic!("Invalid number of bits per sample. \ When writing SampleFormat::Float, \ @@ -443,10 +443,10 @@ impl ChunksWriter { }, }; - try!(Self::write_waveformat(spec, buffer)); + Self::write_waveformat(spec, buffer)?; // The field wBitsPerSample, the real number of bits per sample. - try!(buffer.write_le_u16(spec.spec.bits_per_sample)); + buffer.write_le_u16(spec.spec.bits_per_sample)?; // Note: for WAVEFORMATEX, there would be another 16-byte field `cbSize` // here that should be set to zero. And the header size would be 18 @@ -458,7 +458,7 @@ impl ChunksWriter { /// Writes the contents of the fmt chunk as WAVEFORMATEXTENSIBLE struct. fn write_waveformatextensible(spec:WavSpecEx, buffer: &mut io::Cursor<&mut [u8]>) -> io::Result<()> { // Write the size of the WAVE header chunk. - try!(buffer.write_le_u32(40)); + buffer.write_le_u32(40)?; // The following is based on the WAVEFORMATEXTENSIBLE struct, documented // at https://msdn.microsoft.com/en-us/library/ms713496.aspx and @@ -466,21 +466,21 @@ impl ChunksWriter { // The field wFormatTag, value 1 means WAVE_FORMAT_PCM, but we use // the slightly more sophisticated WAVE_FORMAT_EXTENSIBLE. - try!(buffer.write_le_u16(0xfffe)); + buffer.write_le_u16(0xfffe)?; - try!(Self::write_waveformat(spec, buffer)); + Self::write_waveformat(spec, buffer)?; // The field wBitsPerSample. This is actually the size of the // container, so this is a multiple of 8. - try!(buffer.write_le_u16(spec.bytes_per_sample as u16 * 8)); + buffer.write_le_u16(spec.bytes_per_sample as u16 * 8)?; // The field cbSize, the number of remaining bytes in the struct. - try!(buffer.write_le_u16(22)); + buffer.write_le_u16(22)?; // The field wValidBitsPerSample, the real number of bits per sample. - try!(buffer.write_le_u16(spec.spec.bits_per_sample)); + buffer.write_le_u16(spec.spec.bits_per_sample)?; // The field dwChannelMask. // TODO: add the option to specify the channel mask. For now, use // the default assignment. - try!(buffer.write_le_u32(channel_mask(spec.spec.channels))); + buffer.write_le_u32(channel_mask(spec.spec.channels))?; // The field SubFormat. let subformat_guid = match spec.spec.sample_format { @@ -497,7 +497,7 @@ impl ChunksWriter { } } }; - try!(buffer.write_all(&subformat_guid)); + buffer.write_all(&subformat_guid)?; Ok(()) } @@ -508,19 +508,19 @@ impl ChunksWriter { /// `WAVEFORMATEXTENSIBLE`. This does not write the `wFormatTag` member. fn write_waveformat(spec: WavSpecEx, buffer: &mut io::Cursor<&mut [u8]>) -> io::Result<()> { // The field nChannels. - try!(buffer.write_le_u16(spec.spec.channels)); + buffer.write_le_u16(spec.spec.channels)?; // The field nSamplesPerSec. - try!(buffer.write_le_u32(spec.spec.sample_rate)); + buffer.write_le_u32(spec.spec.sample_rate)?; let bytes_per_sec = spec.spec.sample_rate * spec.bytes_per_sample as u32 * spec.spec.channels as u32; // The field nAvgBytesPerSec; - try!(buffer.write_le_u32(bytes_per_sec)); + buffer.write_le_u32(bytes_per_sec)?; // The field nBlockAlign. Block align * sample rate = bytes per sec. - try!(buffer.write_le_u16((bytes_per_sec / spec.spec.sample_rate) as u16)); + buffer.write_le_u16((bytes_per_sec / spec.spec.sample_rate) as u16)?; Ok(()) } @@ -533,11 +533,11 @@ impl ChunksWriter { #[inline] pub fn write_sample(&mut self, sample: S) -> Result<()> { let spec_ex = self.spec_ex.expect("Format should have written before this call"); - try!(sample.write_padded( + sample.write_padded( &mut self.writer, spec_ex.spec.bits_per_sample, spec_ex.bytes_per_sample - )); + )?; let written = spec_ex.bytes_per_sample as u32; self.data_state.as_mut().expect("Can only be called positioned in data chunk").len += written; Ok(()) @@ -645,9 +645,9 @@ impl WavWriter /// This writes parts of the header immediately, hence a `Result` is /// returned. pub fn new_with_spec_ex(writer: W, spec: WavSpecEx) -> Result> { - let mut chunks_writer = try!(ChunksWriter::new(writer)); - try!(chunks_writer.write_fmt(spec)); - try!(chunks_writer.start_data_chunk()); + let mut chunks_writer = ChunksWriter::new(writer)?; + chunks_writer.write_fmt(spec)?; + chunks_writer.start_data_chunk()?; Ok(WavWriter { writer: chunks_writer }) } @@ -753,11 +753,11 @@ impl WavWriter /// /// Returns (spec_ex, data_len, data_start). fn read_append(reader: &mut W) -> Result<(WavSpecEx, u32, u32)> { - let mut chunk_reader = try!(read::ChunksReader::new(reader)); - try!(chunk_reader.read_until_data()); - let spec_ex = try!(chunk_reader.spec_ex.ok_or(Error::FormatError("DATA found before fmt"))); + let mut chunk_reader = read::ChunksReader::new(reader)?; + chunk_reader.read_until_data()?; + let spec_ex = chunk_reader.spec_ex.ok_or(Error::FormatError("DATA found before fmt"))?; let data_len = chunk_reader.data_state.expect("Invalid state, should be in DATA").chunk.len; - let data_start = try!(chunk_reader.into_inner().seek(io::SeekFrom::Current(0))); + let data_start = chunk_reader.into_inner().seek(io::SeekFrom::Current(0))?; let num_samples = data_len / spec_ex.bytes_per_sample as u64; @@ -801,7 +801,7 @@ impl WavWriter> { pub fn create>(filename: P, spec: WavSpec) -> Result>> { - let file = try!(fs::File::create(filename)); + let file = fs::File::create(filename)?; let buf_writer = io::BufWriter::new(file); WavWriter::new(buf_writer, spec) } @@ -815,17 +815,17 @@ impl WavWriter> { /// See `WavWriter::new_append()` for more details about append behavior. pub fn append>(filename: P) -> Result>> { // Open the file in append mode, start reading from the start. - let file = try!(fs::OpenOptions::new().read(true).write(true).open(filename)); + let file = fs::OpenOptions::new().read(true).write(true).open(filename)?; // Read the header using a buffered reader. let mut buf_reader = io::BufReader::new(file); - let (spec_ex, data_len, data_start) = try!(read_append(&mut buf_reader)); + let (spec_ex, data_len, data_start) = read_append(&mut buf_reader)?; let mut file = buf_reader.into_inner(); // Seek to the data position, and from now on, write using a buffered // writer. - let full_len = try!(file.seek(io::SeekFrom::End(0))); + let full_len = file.seek(io::SeekFrom::End(0))?; if full_len as u32 != data_start + data_len { return Err(Error::FormatError("Can not append to a wave file with trailing chunks")) @@ -860,8 +860,8 @@ impl WavWriter where W: io::Read + io::Write + io::Seek { /// is not an issue, because Hound never writes a fact chunk. For all the /// formats that Hound can write, the fact chunk is redundant. pub fn new_append(mut writer: W) -> Result> { - let (spec_ex, data_len, _data_start) = try!(read_append(&mut writer)); - try!(writer.seek(io::SeekFrom::Current(data_len as i64))); + let (spec_ex, data_len, _data_start) = read_append(&mut writer)?; + writer.seek(io::SeekFrom::Current(data_len as i64))?; let writer = WavWriter { writer: ChunksWriter { spec_ex: Some(spec_ex), @@ -972,7 +972,7 @@ impl<'parent, W: io::Write + io::Seek> SampleWriter16<'parent, W> { // This is copied from the nightly implementation for slice_assume_init_ref. let slice = unsafe { &*(self.buffer as *const [MaybeUninit] as *const [u8]) }; - try!(self.writer.write_all(slice)); + self.writer.write_all(slice)?; *self.data_bytes_written += self.buffer.len() as u32; Ok(())