flac & raw export
This commit is contained in:
parent
b0444e13d4
commit
bd9e239c77
4 changed files with 314 additions and 8 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -34,6 +34,7 @@ out/
|
|||
*.mp3
|
||||
*.raw
|
||||
*.wav
|
||||
*.flac
|
||||
|
||||
# VSCode
|
||||
.vscode/settings.json
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "bliplib"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
edition = "2024"
|
||||
authors = ["Breval Ferrari <breval.ferrari@fish.golf>"]
|
||||
description = "The Bizarre Language for Intermodulation Programming (BLIP)"
|
||||
|
@ -33,6 +33,7 @@ rodio = { version = "0.20", default-features = false, optional = true }
|
|||
dasp_sample = { version = "0", optional = true }
|
||||
log = "0"
|
||||
env_logger = { version = "0", optional = true }
|
||||
fon = "0.5"
|
||||
|
||||
[features]
|
||||
default = ["all-formats"]
|
||||
|
|
|
@ -385,9 +385,7 @@ fn audio_format_parser(input: &str) -> Result<AudioFormat, anyhow::Error> {
|
|||
tag::<&'a str, LocatedSpan<&'a str>, nom::error::Error<LocatedSpan<&'a str>>>(
|
||||
AudioFormatDiscriminants::Flac.into(),
|
||||
),
|
||||
usize
|
||||
.or(success(320000))
|
||||
.map(|bps| AudioFormat::Flac { bps }),
|
||||
usize.or(success(16)).map(|bps| AudioFormat::Flac { bps }),
|
||||
)
|
||||
}
|
||||
fn parser<'a>() -> impl P<
|
||||
|
@ -401,8 +399,11 @@ fn audio_format_parser(input: &str) -> Result<AudioFormat, anyhow::Error> {
|
|||
flac::<'a>(),
|
||||
rest.map_res(|r: LocatedSpan<&'a str>| {
|
||||
Ok::<AudioFormat, nom::error::Error<LocatedSpan<&'a str>>>(AudioFormat::Raw(
|
||||
RawAudioFormat::try_from(*r)
|
||||
.map_err(|_| nom::error::Error::new(r, ErrorKind::Verify))?,
|
||||
(*r == "raw")
|
||||
.then_some(Default::default())
|
||||
.ok_or(nom::error::Error::new(r, ErrorKind::Verify))
|
||||
.or(RawAudioFormat::try_from(*r)
|
||||
.map_err(|_| nom::error::Error::new(r, ErrorKind::Verify)))?,
|
||||
))
|
||||
}),
|
||||
))
|
||||
|
|
307
src/cli/main.rs
307
src/cli/main.rs
|
@ -1,5 +1,6 @@
|
|||
//! See [the lib docs](https://docs.rs/bliplib)
|
||||
|
||||
#[macro_use]
|
||||
mod cli;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
|
@ -16,7 +17,8 @@ use bliplib::{
|
|||
};
|
||||
use clap::Parser as _;
|
||||
use cli::Cli;
|
||||
use dasp_sample::Sample;
|
||||
use dasp_sample::{I24, Sample};
|
||||
use flacenc::{component::BitRepr, error::Verify};
|
||||
use hound::{SampleFormat, WavSpec, WavWriter};
|
||||
use log::{debug, error, info, warn};
|
||||
use mp3lame_encoder::{Builder as Mp3EncoderBuilder, FlushNoGap, MonoPcm};
|
||||
|
@ -134,6 +136,45 @@ fn main() -> anyhow::Result<()> {
|
|||
info!("writing samples to output");
|
||||
writer.write_all(buff.get_ref())?;
|
||||
}
|
||||
Flac { bps } => {
|
||||
let config = flacenc::config::Encoder::default()
|
||||
.into_verified()
|
||||
.expect("Config data error.");
|
||||
let source = flacenc::source::MemSource::from_samples(
|
||||
samples
|
||||
.into_iter()
|
||||
.map(|sample| match bps {
|
||||
8 => sample.to_sample::<i8>() as i32,
|
||||
16 => sample.to_sample::<i16>() as i32,
|
||||
24 => sample.to_sample::<I24>().inner(),
|
||||
_=> unimplemented!("sorry, the current implementation for the flac encoder doesn't support any other bitrate than 8, 16 or 24.")
|
||||
})
|
||||
.collect::<Vec<i32>>()
|
||||
.as_slice(),
|
||||
1,
|
||||
bps,
|
||||
SAMPLE_RATE.into(),
|
||||
);
|
||||
let flac_stream =
|
||||
flacenc::encode_with_fixed_block_size(&config, source, config.block_size)
|
||||
.expect("Encode failed.");
|
||||
|
||||
// `Stream` imlpements `BitRepr` so you can obtain the encoded stream via
|
||||
// `ByteSink` struct that implements `BitSink`.
|
||||
let mut sink = flacenc::bitsink::ByteSink::new();
|
||||
flac_stream
|
||||
.write(&mut sink)
|
||||
.context("Failed to write samples to FLAC byte sink")?;
|
||||
|
||||
let mut writer: Box<dyn Write> = output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout()));
|
||||
writer
|
||||
.write_all(sink.as_slice())
|
||||
.context("Failed to write samples to output")?;
|
||||
}
|
||||
Mp3 { bitrate, quality } => {
|
||||
let buff = {
|
||||
let mut encoder = Mp3EncoderBuilder::new()
|
||||
|
@ -181,7 +222,269 @@ fn main() -> anyhow::Result<()> {
|
|||
info!("writing samples to output");
|
||||
writer.write_all(&buff)?;
|
||||
}
|
||||
_ => todo!(),
|
||||
// I don't know how to easily solve this copy paste with macros because of the variant name usage
|
||||
Raw(format) => match format {
|
||||
RawAudioFormat::ALaw => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::ALaw,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::F32Be => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::F32Be,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::F32Le => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::F32Le,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::F64Be => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::F64Be,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::F64Le => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::F64Le,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::MuLaw => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::MuLaw,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::S8 => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::S8,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::S16Be => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::S16Be,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::S16Le => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::S16Le,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::S24Be => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::S24Be,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::S24Le => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::S24Le,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::S32Be => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::S32Be,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::S32Le => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::S32Le,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::U8 => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::U8,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::U16Be => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::U16Be,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::U16Le => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::U16Le,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::U24Be => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::U24Be,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::U24Le => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::U24Le,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::U32Be => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::U32Be,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
RawAudioFormat::U32Le => raw_audio::Encoder::new(
|
||||
output
|
||||
.map(File::from)
|
||||
.map(Box::new)
|
||||
.map(|b| b as Box<dyn Write>)
|
||||
.unwrap_or(Box::new(stdout())),
|
||||
raw_audio::pcm::U32Le,
|
||||
)
|
||||
.encode(
|
||||
fon::Audio::<fon::mono::Mono64>::with_f64_buffer(SAMPLE_RATE, samples)
|
||||
.drain(),
|
||||
)
|
||||
.context("Failed to encode to raw audio")?,
|
||||
},
|
||||
}
|
||||
}
|
||||
Memo(MemoKind::Syntax(s)) => println!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue