27 Commits

Author SHA1 Message Date
Jamie Hardt
bebfa235e6 Added very basic file verification 2020-11-22 21:07:16 -08:00
Jamie Hardt
a5c55dbcf1 added json parsing 2020-11-22 18:48:08 -08:00
Jamie Hardt
02a91f2b1d More documentation, killed some code 2020-11-22 15:18:13 -08:00
Jamie Hardt
781e8769b0 Readability 2020-11-22 14:57:17 -08:00
Jamie Hardt
e637dc86d3 Re-ran this to fix filename fields 2020-11-22 14:54:57 -08:00
Jamie Hardt
d9f8855f84 Documentation 2020-11-22 14:36:39 -08:00
Jamie Hardt
0da6594081 Replaced the TOML file with an FFPROBE output 2020-11-22 14:36:35 -08:00
Jamie Hardt
a3920a922e Doc cleanup 2020-11-22 13:24:09 -08:00
Jamie Hardt
afbeb7d737 Documentation tweaks 2020-11-22 13:08:54 -08:00
Jamie Hardt
bfbe0f0b9d Made more items public 2020-11-22 13:07:26 -08:00
Jamie Hardt
d242e33de3 Update README.md
Removed resources
2020-11-22 12:57:39 -08:00
Jamie Hardt
da229c7396 Update README.md 2020-11-22 12:56:47 -08:00
Jamie Hardt
5b480c919b Update rust.yml 2020-11-20 23:11:36 -08:00
Jamie Hardt
5cd58c236b Update rust.yml
Added tarpaulin as an experiment
2020-11-20 23:05:15 -08:00
Jamie Hardt
048f58d856 Update Cargo.toml
Removed license-file key
2020-11-20 22:29:56 -08:00
Jamie Hardt
79f146a222 Update rust.yml 2020-11-20 22:27:34 -08:00
Jamie Hardt
5384ebfdc5 Merge branch 'master' of https://github.com/iluvcapra/bwavfile 2020-11-20 22:25:34 -08:00
Jamie Hardt
c6ffbc4559 ds 2020-11-20 22:25:20 -08:00
Jamie Hardt
46fe38e3d6 Added empirical test data 2020-11-20 22:25:09 -08:00
Jamie Hardt
6d2223d8c2 Update README.md 2020-11-20 20:22:47 -08:00
Jamie Hardt
84f5a955ab Update README.md
Added build badge
2020-11-20 20:21:50 -08:00
Jamie Hardt
013145d267 Update rust.yml 2020-11-20 20:17:55 -08:00
Jamie Hardt
63ee997eb3 Update rust.yml 2020-11-20 20:15:15 -08:00
Jamie Hardt
c5072c76b0 Update rust.yml
Added Create Test Media step
2020-11-20 20:11:19 -08:00
Jamie Hardt
acd0fe6793 Create rust.yml 2020-11-20 20:06:14 -08:00
Jamie Hardt
9178e48a5b Update README.md 2020-11-20 19:29:55 -08:00
Jamie Hardt
044d1327c0 Update README.md 2020-11-20 19:28:18 -08:00
15 changed files with 1061 additions and 114 deletions

28
.github/workflows/rust.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Rust
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# - name: Install ffmpeg
# run: sudo apt-get install ffmpeg
- name: Create Test Media
run: cd tests; sh create_test_media.sh
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
# - name: rust-tarpaulin
# uses: actions-rs/tarpaulin@v0.1.0

3
.gitignore vendored
View File

@@ -1,4 +1,5 @@
/target
.DS_Store
target/*
tests/media/*
tests/media/*
tests/.DS_Store

32
Cargo.lock generated
View File

@@ -2,10 +2,11 @@
# It is not intended for manual editing.
[[package]]
name = "bwavfile"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"byteorder",
"encoding",
"serde_json",
]
[[package]]
@@ -77,3 +78,32 @@ name = "encoding_index_tests"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
[[package]]
name = "itoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "serde"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
[[package]]
name = "serde_json"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
dependencies = [
"itoa",
"ryu",
"serde",
]

View File

@@ -1,10 +1,9 @@
[package]
name = "bwavfile"
version = "0.1.1"
version = "0.1.2"
authors = ["Jamie Hardt <jamiehardt@me.com>"]
edition = "2018"
license = "MIT"
license-file = "LICENSE"
description = "Rust Wave File Reader/Writer with Broadcast-WAV, MBWF and RF64 Support"
homepage = "https://github.com/iluvcapra/bwavfile"
readme = "README.md"
@@ -17,3 +16,4 @@ keywords = ["audio", "broadcast", "multimedia","smpte"]
[dependencies]
byteorder = "1.3.4"
encoding = "0.2.33"
serde_json = "1.0.59"

View File

@@ -1,69 +1,38 @@
![Crates.io](https://img.shields.io/crates/l/bwavfile)
![Crates.io](https://img.shields.io/crates/v/bwavfile)
[![Crates.io](https://img.shields.io/crates/l/bwavfile)](LICENSE)
[![Crates.io](https://img.shields.io/crates/v/bwavfile)](https://crates.io/crates/bwavfile/)
![GitHub last commit](https://img.shields.io/github/last-commit/iluvcapra/bwavfile)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/iluvcapra/bwavfile/Rust)](https://github.com/iluvcapra/bwavfile/actions?query=workflow%3ARust)
# bwavfile
Rust Wave File Reader/Writer with Broadcast-WAV, MBWF and RF64 Support
This is currently a work-in-progress!
## Use
## Use Examples
### Reading a File
```rust
let path = "tests/media/ff_silence.wav";
let mut w = WaveReader::open(path)?;
let length = w.frame_length()?;
let format = w.format()?;
let bext = w.broadcast_extension()?;
println!("Description field: {}", &bext.description);
println!("Originator field: {}", &bext.originator);
let frame_reader = w.audio_frame_reader()?;
let mut buffer: Vec<i32> = w.create_frame_buffer();
while( frame_reader.read_integer_frame(&mut buffer) > 0) {
println!("Read frames {:?}", &buffer);
}
use bwavfile::WaveReader;
let mut r = WaveReader::open("tests/media/ff_silence.wav").unwrap();
let format = r.format().unwrap();
assert_eq!(format.sample_rate, 44100);
assert_eq!(format.channel_count, 1);
let mut frame_reader = r.audio_frame_reader().unwrap();
let mut buffer = frame_reader.create_frame_buffer();
let read = frame_reader.read_integer_frame(&mut buffer).unwrap();
assert_eq!(buffer, [0i32]);
assert_eq!(read, 1);
```
## Note on Testing
All of the media for the integration tests is committed to the respository
in either zipped form or is created by ffmpeg. Before you can run tests, you
will need to have ffmpeg installed, and you need to `cd` into the `tests`
directory and run the `create_test_media.sh` script.
## Resources
### Implementation of Broadcast Wave Files
- [EBU Tech 3285][ebu3285] (May 2011), "Specification of the Broadcast Wave Format (BWF)"
### Implementation of 64-bit Wave Files
- [ITU-R 2088][itu2088] (October 2019), "Long-form file format for the international exchange of audio programme materials with metadata"
- Presently in force, adopted by the EBU in [EBU Tech 3306v2][ebu3306v2] (June 2018).
- [EBU Tech 3306v1][ebu3306v1] (July 2009), "MBWF / RF64: An extended File Format for Audio"
- No longer in force, however long-established.
### Implementation of Wave format `fmt` chunk
- [MSDN WAVEFORMATEX](https://docs.microsoft.com/en-us/windows/win32/api/mmeapi/ns-mmeapi-waveformatex)
- [MSDN WAVEFORMATEXTENSIBLE](https://docs.microsoft.com/en-us/windows/win32/api/mmreg/ns-mmreg-waveformatextensible)
### Other resources
- [RFC 3261][rfc3261] (June 1998) "WAVE and AVI Codec Registries"
- [Peter Kabal, McGill University](http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html)
- [Multimedia Programming Interface and Data Specifications 1.0](http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf)
IBM Corporation and Microsoft Corporation, (August 1991)
[ebu3285]: https://tech.ebu.ch/docs/tech/tech3285.pdf
[ebu3306v1]: https://tech.ebu.ch/docs/tech/tech3306v1_1.pdf
[ebu3306v2]: https://tech.ebu.ch/docs/tech/tech3306.pdf
[itu2088]: https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.2088-1-201910-I!!PDF-E.pdf
[rfc3261]: https://tools.ietf.org/html/rfc2361
in zipped form. Before you can run tests, you need to `cd` into the `tests`
directory and run the `create_test_media.sh` script. Note that one of the
test files (the RF64 test case) is over four gigs in size.

View File

@@ -38,7 +38,7 @@ These are from http://dream.cs.bath.ac.uk/researchdev/wave-ex/mulchaud.rtf
*/
#[derive(Debug)]
enum WaveFmtExtendedChannelMask {
pub enum WaveFmtExtendedChannelMask {
FrontLeft = 0x1,
FrontRight = 0x2,
FrontCenter = 0x4,
@@ -67,9 +67,19 @@ enum WaveFmtExtendedChannelMask {
*/
#[derive(Debug)]
pub struct WaveFmtExtended {
valid_bits_per_sample : u16,
channel_mask : WaveFmtExtendedChannelMask,
type_guid : [u8; 16],
/// Valid bits per sample
pub valid_bits_per_sample : u16,
/// Channel mask
///
/// Identifies the speaker assignment for each channel in the file
pub channel_mask : WaveFmtExtendedChannelMask,
/// Codec GUID
///
/// Identifies the codec of the audio stream
pub type_guid : [u8; 16],
}
/**
@@ -82,18 +92,43 @@ pub struct WaveFmtExtended {
*/
#[derive(Debug)]
pub struct WaveFmt {
/// A tag identifying the codec in use.
///
/// If this is 0xFFFE, the codec will be identified by a GUID
/// in `extended_format`
pub tag: u16,
/// Count of audio channels in each frame
pub channel_count: u16,
/// Sample rate of the audio data
pub sample_rate: u32,
/// Count of bytes per second
///
/// By rule, this is `block_alignment * sample_rate`
pub bytes_per_second: u32,
/// Count of bytes per audio frame
///
/// By rule, this is `channel_count * bits_per_sample / 8`
pub block_alignment: u16,
/// Count of bits stored in the file per sample
pub bits_per_sample: u16,
/// Extended format description
///
/// Additional format metadata if `channel_count` is greater than 2,
/// or if certain codecs are used.
pub extended_format: Option<WaveFmtExtended>
}
impl WaveFmt {
/// Create a new integer PCM format `WaveFmt`
pub fn new_pcm(sample_rate: u32, bits_per_sample: u16, channel_count: u16) -> Self {
let container_bits_per_sample = bits_per_sample + (bits_per_sample % 8);
let container_bytes_per_sample= container_bits_per_sample / 8;
@@ -114,17 +149,6 @@ impl WaveFmt {
extended_format: None
}
}
pub fn bytes_per_frame(&self) -> u16 {
let bits_per_byte = 8;
let bits_per_sample_with_pad = self.bits_per_sample + (self.bits_per_sample % 8);
bits_per_sample_with_pad * self.channel_count / bits_per_byte
}
pub fn valid_broadcast_wave_format(&self) -> bool {
let real_alignment = self.block_alignment;
self.bytes_per_frame() == real_alignment
}
}
/**

View File

@@ -1,16 +1,39 @@
use std::io;
use super::fourcc::FourCC;
/// Errors returned by methods in this crate.
#[derive(Debug)]
pub enum Error {
/// An `io::Error` occurred
IOError(io::Error),
/// The file does not begin with a recognized WAVE header
HeaderNotRecognized,
/// A wave file with a 64-bit header does not contain
/// the required `ds64` metadata element
MissingRequiredDS64,
/// A data chunk required to complete the operation
/// is not present in the file
ChunkMissing { signature : FourCC },
/// The file is formatted improperly
FmtChunkAfterData,
/// The file did not validate as a minimal WAV file
NotMinimalWaveFile,
/// The `data` chunk is not aligned to the desired page
/// boundary
DataChunkNotAligned,
/// The file cannot be converted into an RF64 file due
/// to its internal structure
InsufficientDS64Reservation {expected: u64, actual: u64},
/// The file is not optimized for writing new data
DataChunkNotPreparedForAppend
}

View File

@@ -1,17 +1,54 @@
//
/*!
# bwavfile
Rust Wave File Reader/Writer with Broadcast-WAV, MBWF and RF64 Support
(Note: This crate is still in an alpha or pre-alpha stage of development. Reading of
files works however the interfaces may change significantly. Stay up-to-date on the
status of this project at [Github][github].)
## Resources
### Implementation of Broadcast Wave Files
- [EBU Tech 3285][ebu3285] (May 2011), "Specification of the Broadcast Wave Format (BWF)"
### Implementation of 64-bit Wave Files
- [ITU-R 2088][itu2088] (October 2019), "Long-form file format for the international exchange of audio programme materials with metadata"
- Presently in force, adopted by the EBU in [EBU Tech 3306v2][ebu3306v2] (June 2018).
- [EBU Tech 3306v1][ebu3306v1] (July 2009), "MBWF / RF64: An extended File Format for Audio"
- No longer in force, however long-established.
### Implementation of Wave format `fmt` chunk
- [MSDN WAVEFORMATEX](https://docs.microsoft.com/en-us/windows/win32/api/mmeapi/ns-mmeapi-waveformatex)
- [MSDN WAVEFORMATEXTENSIBLE](https://docs.microsoft.com/en-us/windows/win32/api/mmreg/ns-mmreg-waveformatextensible)
### Other resources
- [RFC 3261][rfc3261] (June 1998) "WAVE and AVI Codec Registries"
- [Peter Kabal, McGill University](http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html)
- [Multimedia Programming Interface and Data Specifications 1.0](http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf)
IBM Corporation and Microsoft Corporation, (August 1991)
[ebu3285]: https://tech.ebu.ch/docs/tech/tech3285.pdf
[ebu3306v1]: https://tech.ebu.ch/docs/tech/tech3306v1_1.pdf
[ebu3306v2]: https://tech.ebu.ch/docs/tech/tech3306.pdf
[itu2088]: https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.2088-1-201910-I!!PDF-E.pdf
[rfc3261]: https://tools.ietf.org/html/rfc2361
[github]: https://github.com/iluvcapra/bwavfile
*/
// #![feature(external_doc)]
// #[doc(include="../README.md")]
// #[cfg(doctest)]
// pub struct ReadmeDoctests;
extern crate encoding;
extern crate byteorder;
/**!
* bwavfile
*
* Rust Wave File Reader/Writer with Broadcast-WAV, MBWF and RF64 Support
*
* This crate is currently a work-in-progress (I'm using it to teach myself
* rust) so the interface may change dramatically and not all features work.
*
!*/
mod parser;
mod fourcc;
mod errors;

View File

@@ -103,7 +103,7 @@ impl<R: Read + Seek> Iterator for Parser<R> {
fn next(&mut self) -> Option<Event> {
let (event, next_state) = self.advance();
println!("{:?}", event);
//println!("{:?}", event);
self.state = next_state;
return event;
}

BIN
tests/.DS_Store vendored

Binary file not shown.

Binary file not shown.

BIN
tests/arch_ff_media.zip Normal file

Binary file not shown.

View File

@@ -3,46 +3,48 @@
mkdir -p media
cd media
touch error.wav
unzip ../arch_pt_media.zip
unzip ../arch_audacity_media.zip
unzip ../arch_ff_media.zip
rm -rf __MACOSX
# create a silent bext wave file with fixture metadata and a time refernce starting at
# one minute
#
# Keywords for bext metadata are here...
# https://github.com/FFmpeg/FFmpeg/blob/17a0dfebf55f67653c29a607545a799f12bc0c01/libavformat/wavenc.c#L110
#
ffmpeg -y -f lavfi -i "aevalsrc=0|0:c=stereo" -to 0.1 -ar 48000 -c:a pcm_s24le -write_bext 1 \
-metadata "description=FFMPEG-generated stereo WAV file with bext metadata" \
-metadata "originator=ffmpeg" \
-metadata "originator_reference=STEREO_WAVE_TEST" \
-metadata "time_reference=2880000" \
-metadata "origination_date=2020-11-18" \
-metadata "origination_time=12:00:00" \
-metadata "umid=0xFF00FF00FF00FF00FF00FF00FF00FF00" \
-metadata "coding_history=A:PCM,48K" ff_bwav_stereo.wav
# ffmpeg -y -f lavfi -i "aevalsrc=0|0:c=stereo" -to 0.1 -ar 48000 -c:a pcm_s24le -write_bext 1 \
# -metadata "description=FFMPEG-generated stereo WAV file with bext metadata" \
# -metadata "originator=ffmpeg" \
# -metadata "originator_reference=STEREO_WAVE_TEST" \
# -metadata "time_reference=2880000" \
# -metadata "origination_date=2020-11-18" \
# -metadata "origination_time=12:00:00" \
# -metadata "umid=0xFF00FF00FF00FF00FF00FF00FF00FF00" \
# -metadata "coding_history=A:PCM,48K" ff_bwav_stereo.wav
ffmpeg -y -f lavfi -i "aevalsrc=0|0|0|0|0|0:c=5.1" -to 0.1 -ar 48000 -c:a pcm_s24le -write_bext 1 \
-metadata "description=FFMPEG-generated 5.1 WAV file with bext metadata" \
-metadata "originator=ffmpeg" \
-metadata "originator_reference=5_1_WAVE_TEST" \
-metadata "time_reference=0" \
-metadata "origination_date=2020-11-18" \
-metadata "origination_time=13:00:00" \
-metadata "umid=0xFF00FF00FF00FF00FF00FF00FF00FF01" \
-metadata "coding_history=A:PCM,48K" ff_bwav_51.wav
# ffmpeg -y -f lavfi -i "aevalsrc=0|0|0|0|0|0:c=5.1" -to 0.1 -ar 48000 -c:a pcm_s24le -write_bext 1 \
# -metadata "description=FFMPEG-generated 5.1 WAV file with bext metadata" \
# -metadata "originator=ffmpeg" \
# -metadata "originator_reference=5_1_WAVE_TEST" \
# -metadata "time_reference=0" \
# -metadata "origination_date=2020-11-18" \
# -metadata "origination_time=13:00:00" \
# -metadata "umid=0xFF00FF00FF00FF00FF00FF00FF00FF01" \
# -metadata "coding_history=A:PCM,48K" ff_bwav_51.wav
ffmpeg -y -f lavfi -i "aevalsrc=0" -to 1 -ar 44100 ff_silence.wav
# ffmpeg -y -f lavfi -i "aevalsrc=0" -to 1 -ar 44100 ff_silence.wav
ffmpeg -y -f lavfi -i "aevalsrc=0" -to 1 -ar 44100 -fflags bitexact ff_minimal.wav
# ffmpeg -y -f lavfi -i "aevalsrc=0" -to 1 -ar 44100 -fflags bitexact ff_minimal.wav
# ffmpeg -y -f lavfi -i "aevalsrc=0|0|0|0|0|0:c=5.1" -to 0:45:00 -ar 96000 -c:a pcm_s24le -rf64 1 \
# -write_bext 1 \
# -metadata "description=rf64 test file" ff_longfile.wav
ffmpeg -y -f lavfi -i "anoisesrc=r=48000:a=0.5:c=pink:s=41879" -to 0.1 -ar 48000 -c:a pcm_f32le \
-write_bext 1 \
-metadata "description=float test file" ff_float.wav
touch error.wav
unzip ../arch_pt_media.zip
unzip ../arch_audacity_media.zip
rm -rf __MACOSX
# ffmpeg -y -f lavfi -i "anoisesrc=r=48000:a=0.5:c=pink:s=41879" -to 0.1 -ar 48000 -c:a pcm_f32le \
# -write_bext 1 \
# -metadata "description=float test file" ff_float.wav

View File

@@ -0,0 +1,50 @@
extern crate serde_json;
use core::fmt::Debug;
use serde_json::{Value, from_str};
use std::fs::File;
use std::io::Read;
use bwavfile::WaveReader;
// This seems rickety but we're going with it
fn assert_match_stream<T>(stream_key: &str,
other: impl Fn(&mut WaveReader<File>) -> T)
where T: PartialEq + Debug,
T: Into<Value>
{
let mut json_file = File::open("tests/media_ffprobe_result.json").unwrap();
let mut s = String::new();
json_file.read_to_string(&mut s).unwrap();
if let Value::Array(v) = from_str(&mut s).unwrap() { /* */
v.iter()
.filter(|value| {
!value["format"]["filename"].is_null()
})
.for_each(|value| {
let filen : &str = value["format"]["filename"].as_str().unwrap();
let json_value : &Value = &value["streams"][0][stream_key];
let mut wavfile = WaveReader::open(filen).unwrap();
let wavfile_value: T = other(&mut wavfile);
println!("asserting {} for {}",stream_key, filen);
assert_eq!(Into::<Value>::into(wavfile_value), *json_value);
})
}
}
#[test]
fn test_frame_count() {
assert_match_stream("duration_ts", |w| w.frame_length().unwrap() );
}
#[test]
fn test_sample_rate() {
assert_match_stream("sample_rate", |w| format!("{}", w.format().unwrap().sample_rate) );
}
#[test]
fn test_channel_count() {
assert_match_stream("channels", |w| w.format().unwrap().channel_count );
}

View File

@@ -0,0 +1,783 @@
[
{
"streams": [
{
"index": 0,
"codec_name": "pcm_f32le",
"codec_long_name": "PCM 32-bit floating point little-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[3][0][0][0]",
"codec_tag": "0x0003",
"sample_fmt": "flt",
"sample_rate": "48000",
"channels": 1,
"bits_per_sample": 32,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"duration_ts": 24000,
"duration": "0.500000",
"bit_rate": "1536000",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/pt_float.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.500000",
"size": "113344",
"bit_rate": "1813504",
"probe_score": 99,
"tags": {
"encoded_by": "Pro Tools",
"originator_reference": "aaijNFpjYOIk",
"date": "2020-11-18",
"creation_time": "19:57:21",
"time_reference": "1036416000",
"umid": "0x060A2B340101010501010F10130000002A3224F7E7248000F0B04F71BFE13E00"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s16le",
"codec_long_name": "PCM signed 16-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/44100",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s16",
"sample_rate": "44100",
"channels": 1,
"bits_per_sample": 16,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/44100",
"duration_ts": 4418,
"duration": "0.100181",
"bit_rate": "705600",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/audacity_16bit.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.100181",
"size": "9046",
"bit_rate": "722372",
"probe_score": 99,
"tags": {
"title": "Pink Noise 16bit",
"album": "Test Media",
"artist": "Jamie Hardt"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s24le",
"codec_long_name": "PCM signed 24-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s32",
"sample_rate": "48000",
"channels": 6,
"channel_layout": "5.1",
"bits_per_sample": 24,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"duration_ts": 24000,
"duration": "0.500000",
"bit_rate": "6912000",
"bits_per_raw_sample": "24",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/pt_24bit_51.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.500000",
"size": "452910",
"bit_rate": "7246560",
"probe_score": 99,
"tags": {
"encoded_by": "Pro Tools",
"originator_reference": "aaijNdlHDPIk",
"date": "2020-11-18",
"creation_time": "19:58:18",
"time_reference": "1036416000",
"umid": "0x060A2B340101010501010F10130000002A5D84B0E724800060654F71BFE13E00"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_f32le",
"codec_long_name": "PCM 32-bit floating point little-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[3][0][0][0]",
"codec_tag": "0x0003",
"sample_fmt": "flt",
"sample_rate": "48000",
"channels": 2,
"bits_per_sample": 32,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"duration_ts": 24000,
"duration": "0.500000",
"bit_rate": "3072000",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/pt_float_stereo.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.500000",
"size": "210058",
"bit_rate": "3360928",
"probe_score": 99,
"tags": {
"encoded_by": "Pro Tools",
"originator_reference": "aaijN!1TjQIk",
"date": "2020-11-18",
"creation_time": "19:59:16",
"time_reference": "1036416000",
"umid": "0x060A2B340101010501010F10130000002A89B75FE724800012164F71BFE13E00"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s24le",
"codec_long_name": "PCM signed 24-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s32",
"sample_rate": "48000",
"channels": 2,
"bits_per_sample": 24,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"duration_ts": 24000,
"duration": "0.500000",
"bit_rate": "2304000",
"bits_per_raw_sample": "24",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/pt_24bit_stereo.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.500000",
"size": "162058",
"bit_rate": "2592928",
"probe_score": 99,
"tags": {
"encoded_by": "Pro Tools",
"originator_reference": "aaijNF9aoPIk",
"date": "2020-11-18",
"creation_time": "19:57:57",
"time_reference": "1036416000",
"umid": "0x060A2B340101010501010F10130000002A4E03D7E724800059E44F71BFE13E00"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_f32le",
"codec_long_name": "PCM 32-bit floating point little-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[3][0][0][0]",
"codec_tag": "0x0003",
"sample_fmt": "flt",
"sample_rate": "48000",
"channels": 1,
"channel_layout": "mono",
"bits_per_sample": 32,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"duration_ts": 4800,
"duration": "0.100000",
"bit_rate": "1536000",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/ff_float.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.100000",
"size": "19924",
"bit_rate": "1593920",
"probe_score": 99,
"tags": {
"comment": "float test file",
"time_reference": "0",
"encoder": "Lavf58.29.100"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s24le",
"codec_long_name": "PCM signed 24-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s32",
"sample_rate": "48000",
"channels": 2,
"channel_layout": "stereo",
"bits_per_sample": 24,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"duration_ts": 4800,
"duration": "0.100000",
"bit_rate": "2304000",
"bits_per_raw_sample": "24",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/ff_bwav_stereo.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.100000",
"size": "29522",
"bit_rate": "2361760",
"probe_score": 99,
"tags": {
"comment": "FFMPEG-generated stereo WAV file with bext metadata",
"encoded_by": "ffmpeg",
"originator_reference": "STEREO_WAVE_TEST",
"date": "2020-11-18",
"creation_time": "12:00:00",
"time_reference": "2880000",
"umid": "0x7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF00000000000000000000000000000000",
"coding_history": "A:PCM,48K",
"encoder": "Lavf58.29.100"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s24le",
"codec_long_name": "PCM signed 24-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s32",
"sample_rate": "48000",
"channels": 1,
"bits_per_sample": 24,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"duration_ts": 24000,
"duration": "0.500000",
"bit_rate": "1152000",
"bits_per_raw_sample": "24",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/pt_24bit.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.500000",
"size": "89344",
"bit_rate": "1429504",
"probe_score": 99,
"tags": {
"encoded_by": "Pro Tools",
"originator_reference": "aaijNtnVOOIk",
"date": "2020-11-18",
"creation_time": "19:57:08",
"time_reference": "1036416000",
"umid": "0x060A2B340101010501010F10130000002A28BCD4E72480004F4A4F71BFE13E00"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s24le",
"codec_long_name": "PCM signed 24-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s32",
"sample_rate": "48000",
"channels": 6,
"channel_layout": "5.1",
"bits_per_sample": 24,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"duration_ts": 4800,
"duration": "0.100000",
"bit_rate": "6912000",
"bits_per_raw_sample": "24",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/ff_bwav_51.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.100000",
"size": "87122",
"bit_rate": "6969760",
"probe_score": 99,
"tags": {
"comment": "FFMPEG-generated 5.1 WAV file with bext metadata",
"encoded_by": "ffmpeg",
"originator_reference": "5_1_WAVE_TEST",
"date": "2020-11-18",
"creation_time": "13:00:00",
"time_reference": "0",
"umid": "0x7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF00000000000000000000000000000000",
"coding_history": "A:PCM,48K",
"encoder": "Lavf58.29.100"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s24le",
"codec_long_name": "PCM signed 24-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/96000",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s32",
"sample_rate": "96000",
"channels": 6,
"channel_layout": "5.1",
"bits_per_sample": 24,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/96000",
"duration_ts": 259200000,
"duration": "2700.000000",
"bit_rate": "13824000",
"bits_per_raw_sample": "24",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/ff_longfile.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "2700.000000",
"size": "4665600748",
"bit_rate": "13824002",
"probe_score": 100,
"tags": {
"comment": "rf64 test file",
"time_reference": "0",
"encoder": "Lavf58.29.100"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_f32le",
"codec_long_name": "PCM 32-bit floating point little-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[3][0][0][0]",
"codec_tag": "0x0003",
"sample_fmt": "flt",
"sample_rate": "48000",
"channels": 6,
"channel_layout": "5.1",
"bits_per_sample": 32,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"duration_ts": 24000,
"duration": "0.500000",
"bit_rate": "9216000",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/pt_float_51.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.500000",
"size": "596910",
"bit_rate": "9550560",
"probe_score": 99,
"tags": {
"encoded_by": "Pro Tools",
"originator_reference": "aaijNViK8PIk",
"date": "2020-11-18",
"creation_time": "19:58:59",
"time_reference": "1036416000",
"umid": "0x060A2B340101010501010F10130000002A7C908BE724800047E94F71BFE13E00"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s16le",
"codec_long_name": "PCM signed 16-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/44100",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s16",
"sample_rate": "44100",
"channels": 1,
"bits_per_sample": 16,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/44100",
"duration_ts": 44100,
"duration": "1.000000",
"bit_rate": "705600",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/ff_minimal.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "1.000000",
"size": "88244",
"bit_rate": "705952",
"probe_score": 99
}
},
{},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s16le",
"codec_long_name": "PCM signed 16-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/44100",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s16",
"sample_rate": "44100",
"channels": 1,
"bits_per_sample": 16,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/44100",
"duration_ts": 44100,
"duration": "1.000000",
"bit_rate": "705600",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/ff_silence.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "1.000000",
"size": "88278",
"bit_rate": "706224",
"probe_score": 99,
"tags": {
"encoder": "Lavf58.29.100"
}
}
},
{
"streams": [
{
"index": 0,
"codec_name": "pcm_s16le",
"codec_long_name": "PCM signed 16-bit little-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[1][0][0][0]",
"codec_tag": "0x0001",
"sample_fmt": "s16",
"sample_rate": "48000",
"channels": 1,
"bits_per_sample": 16,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"duration_ts": 24000,
"duration": "0.500000",
"bit_rate": "768000",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
],
"format": {
"filename": "tests/media/pt_16bit.wav",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "wav",
"format_long_name": "WAV / WAVE (Waveform Audio)",
"duration": "0.500000",
"size": "65344",
"bit_rate": "1045504",
"probe_score": 99,
"tags": {
"encoded_by": "Pro Tools",
"originator_reference": "aaijNZdiDOIk",
"date": "2020-11-18",
"creation_time": "19:56:53",
"time_reference": "1036416000",
"umid": "0x060A2B340101010501010F10130000002A1D203CE7248000711E4F71BFE13E00"
}
}
}
]