mirror of
https://github.com/iluvcapra/bwavfile.git
synced 2026-05-17 04:33:26 +00:00
Compare commits
6 Commits
8e341990fa
...
3315f00a89
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3315f00a89 | ||
|
|
6819f63c74 | ||
| 1c83094888 | |||
| 977c8263d2 | |||
| da4bad0e87 | |||
| c89a98f7e4 |
64
CONTRIBUTING.md
Normal file
64
CONTRIBUTING.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Contributing
|
||||
|
||||
Contributions to `bwavfile` are welcome!
|
||||
|
||||
This project is currently in a maintenance phase, new features are entertained if we
|
||||
believe there is some demand for them but for the most part our current priorities
|
||||
are:
|
||||
|
||||
* Addressing bugs.
|
||||
* Keeping the codebase modern as the Rust language evolves.
|
||||
|
||||
This being said, there are some features that we've been wanting for some time and
|
||||
new contributors are welcome to take a swing at these:
|
||||
|
||||
* Reading `levl` metadata for the generation of waveform overviews.
|
||||
* Reading `smpl` metadata for reading sampler data, note assignments, loops etc.
|
||||
|
||||
## Adding New Features
|
||||
|
||||
If you are adding a large amount of new functionality, please weigh the amount of
|
||||
work you're doing against the potential benefit, the burden on the maintainers to
|
||||
review the work, and the technical debt incurred.
|
||||
|
||||
In general,
|
||||
|
||||
* new features should address new technologies; do not expend large amounts of
|
||||
effort to implement features that are primarily of historical interest.
|
||||
* new features should address the needs of professional users in a music or media
|
||||
production environment.
|
||||
|
||||
Features that implement new reading functionality must, when submitted, include
|
||||
test WAV files created empirically by third-party software.
|
||||
|
||||
## Regarding use of Agents
|
||||
|
||||
`bwavfile` is an open-source project that is offered free for no commerical gain, and
|
||||
is developed and maintained for educational and creative reasons.
|
||||
|
||||
If you use an agent or LLM to produce code for it you are missing out on the benefits
|
||||
of contributing to an open-source project, particularly community, collaboration with
|
||||
other developers and designers, and being able to learn and experiment without the
|
||||
burden of deadlines or worrying about business cases or profits.
|
||||
|
||||
This project is supposed to be fun, do not let machines have fun for you.
|
||||
|
||||
We can't prevent you from using LLMs to contribute to this project but we ask you
|
||||
abide by the following eitiquette when doing so:
|
||||
|
||||
* All communication with the maintainers must be written by a human in their own
|
||||
voice. Never use an LLM to craft thread comments, discussion posts, issues, emails
|
||||
or other correspondence with other developers or the maintainers.
|
||||
* PRs must be submitted by a person. Do not allow an agent to submit its own PRs to
|
||||
this project.
|
||||
* Especially if you are a new contributor to this project, please submit only one PR
|
||||
at a time and please restrict the subject matter of the PR to a specific unit,
|
||||
module or tool. All submissions have to be reviewed and understood by the
|
||||
maintainers before they can be merged.
|
||||
|
||||
Obviously we can't verify if you follow all of these rules but certain telltale
|
||||
traits of LLM-predicted text or code will raise a flag: lack of brevity in
|
||||
descriptions or code comments, large amounts of text describing your process or
|
||||
steps that add little to understanding the changes you've made, use of an
|
||||
obsequious tone or being excessively accomodating, immediately doing requests
|
||||
without further discussion or clarifications.
|
||||
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
@@ -30,7 +30,7 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bwavfile"
|
||||
version = "2.0.0"
|
||||
version = "2.0.2"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"clap",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bwavfile"
|
||||
version = "2.0.1"
|
||||
version = "2.0.2"
|
||||
authors = ["Jamie Hardt <jamiehardt@me.com>", "Ian Hobson <ian.r.hobson@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
|
||||
@@ -37,7 +37,7 @@ where
|
||||
self.write_u16::<LittleEndian>(format.block_alignment)?;
|
||||
self.write_u16::<LittleEndian>(format.bits_per_sample)?;
|
||||
if let Some(ext) = format.extended_format {
|
||||
let cb_size = 24u16;
|
||||
let cb_size = 22u16;
|
||||
self.write_u16::<LittleEndian>(cb_size)?;
|
||||
self.write_u16::<LittleEndian>(ext.valid_bits_per_sample)?;
|
||||
self.write_u32::<LittleEndian>(ext.channel_mask)?;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::common_format::{CommonFormat, WAVE_UUID_BFORMAT_PCM, WAVE_UUID_PCM};
|
||||
use crate::Sample;
|
||||
|
||||
@@ -8,7 +10,6 @@ use byteorder::LittleEndian;
|
||||
use byteorder::ReadBytesExt;
|
||||
|
||||
// Need more test cases for ADMAudioID
|
||||
#[allow(dead_code)]
|
||||
|
||||
/// ADM Audio ID record.
|
||||
///
|
||||
@@ -154,7 +155,7 @@ pub struct WaveFmtExtended {
|
||||
/// - [Sampler Metadata](http://www.piclist.com/techref/io/serial/midi/wave.html)
|
||||
/// - [Audio File Format Specifications](http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html) (September 2022) Prof. Peter Kabal, MMSP Lab, ECE, McGill University
|
||||
/// - [Multimedia Programming Interface and Data Specifications 1.0](http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf)
|
||||
/// (August 1991), IBM Corporation and Microsoft Corporation
|
||||
/// (August 1991), IBM Corporation and Microsoft Corporation
|
||||
///
|
||||
/// [rfc3261]: https://tools.ietf.org/html/rfc2361
|
||||
|
||||
@@ -404,7 +405,7 @@ where
|
||||
format: WaveFmt,
|
||||
into: &mut [i32],
|
||||
) -> Result<usize, std::io::Error> {
|
||||
assert!(into.len() % format.channel_count as usize == 0);
|
||||
assert!(into.len().is_multiple_of(format.channel_count as usize));
|
||||
|
||||
for frame in into {
|
||||
*frame = match (format.valid_bits_per_sample(), format.bits_per_sample) {
|
||||
@@ -424,7 +425,7 @@ where
|
||||
format: WaveFmt,
|
||||
into: &mut [f32],
|
||||
) -> Result<usize, std::io::Error> {
|
||||
assert!(into.len() % format.channel_count as usize == 0);
|
||||
assert!(into.len().is_multiple_of(format.channel_count as usize));
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use super::fourcc::{BW64_SIG, DATA_SIG, DS64_SIG, RF64_SIG, RIFF_SIG, WAVE_SIG};
|
||||
const RF64_SIZE_MARKER: u32 = 0xFF_FF_FF_FF;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum Event {
|
||||
StartParse,
|
||||
ReadHeader {
|
||||
@@ -258,7 +259,7 @@ impl<R: Read + Seek> Parser<R> {
|
||||
|
||||
state = State::ReadyForChunk {
|
||||
at: at + 8 + this_displacement,
|
||||
remaining: remaining - 8 - this_displacement,
|
||||
remaining: remaining.saturating_sub(8 + this_displacement),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,3 +293,35 @@ impl<R: Read + Seek> Parser<R> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[test]
|
||||
fn parser_handles_missing_trailing_pad_on_final_odd_chunk() {
|
||||
let mut buf = Vec::new();
|
||||
buf.extend_from_slice(b"RIFF");
|
||||
buf.extend_from_slice(&39u32.to_le_bytes());
|
||||
buf.extend_from_slice(b"WAVE");
|
||||
buf.extend_from_slice(b"fmt ");
|
||||
buf.extend_from_slice(&16u32.to_le_bytes());
|
||||
buf.extend_from_slice(&[0u8; 16]);
|
||||
buf.extend_from_slice(b"data");
|
||||
buf.extend_from_slice(&3u32.to_le_bytes());
|
||||
buf.extend_from_slice(&[0xAA, 0xBB, 0xCC]);
|
||||
assert_eq!(buf.len(), 47);
|
||||
|
||||
let chunks = Parser::make(Cursor::new(&buf))
|
||||
.unwrap()
|
||||
.into_chunk_list()
|
||||
.expect("parser should accept a missing trailing pad on the final odd-length chunk");
|
||||
|
||||
assert_eq!(chunks.len(), 2);
|
||||
assert_eq!(chunks[0].signature, FourCC::from(*b"fmt "));
|
||||
assert_eq!(chunks[0].length, 16);
|
||||
assert_eq!(chunks[1].signature, DATA_SIG);
|
||||
assert_eq!(chunks[1].length, 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ impl<R: Read + Seek> AudioFrameReader<R> {
|
||||
let common_format = self.format.common_format();
|
||||
let bits_per_sample = self.format.bits_per_sample;
|
||||
|
||||
if buffer.len() % channel_count != 0 {
|
||||
if !buffer.len().is_multiple_of(channel_count) {
|
||||
return Err(Error::InvalidBufferSize {
|
||||
buffer_size: buffer.len(),
|
||||
channel_count: self.format.channel_count,
|
||||
@@ -245,7 +245,7 @@ impl<R: Read + Seek> WaveReader<R> {
|
||||
/// will return an `Err(errors::Error)` immediately if there is a structural
|
||||
/// inconsistency that makes the stream unreadable or if it's missing
|
||||
/// essential components that make interpreting the audio data impossible.
|
||||
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::fs::File;
|
||||
/// use std::io::{Error,ErrorKind};
|
||||
|
||||
@@ -51,7 +51,7 @@ where
|
||||
let format = &self.inner.inner.format;
|
||||
let channel_count = format.channel_count as usize;
|
||||
|
||||
if buffer.len() % channel_count != 0 {
|
||||
if !buffer.len().is_multiple_of(channel_count) {
|
||||
return Err(Error::InvalidBufferSize {
|
||||
buffer_size: buffer.len(),
|
||||
channel_count: format.channel_count,
|
||||
@@ -339,7 +339,7 @@ where
|
||||
assert!(data.len() < u32::MAX as usize);
|
||||
self.inner.write_u32::<LittleEndian>(data.len() as u32)?;
|
||||
self.inner.write_all(data)?;
|
||||
if data.len() % 2 == 0 {
|
||||
if data.len().is_multiple_of(2) {
|
||||
self.increment_form_length(8 + data.len() as u64)?;
|
||||
} else {
|
||||
self.inner.write_u8(0)?;
|
||||
|
||||
Reference in New Issue
Block a user