Nothig
This commit is contained in:
97
src/main.rs
97
src/main.rs
@@ -1,7 +1,7 @@
|
|||||||
use std::{fs::File, path::PathBuf};
|
use std::{fs::File, path::PathBuf};
|
||||||
|
|
||||||
use clap::{Parser, Subcommand, ValueEnum};
|
use clap::{Parser, Subcommand, ValueEnum};
|
||||||
use symphonia::core::{audio::SampleBuffer, codecs::DecoderOptions, formats::FormatOptions, io::MediaSourceStream, meta::MetadataOptions, probe::Hint};
|
use symphonia::core::{audio::{AudioBufferRef, SampleBuffer}, codecs::DecoderOptions, formats::FormatOptions, io::MediaSourceStream, meta::MetadataOptions, probe::Hint};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
|
||||||
enum Backend {
|
enum Backend {
|
||||||
@@ -9,6 +9,7 @@ enum Backend {
|
|||||||
Alsa,
|
Alsa,
|
||||||
Pulseaudio,
|
Pulseaudio,
|
||||||
Coreaudio,
|
Coreaudio,
|
||||||
|
Cpal,
|
||||||
}
|
}
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(version, about, long_about = None)]
|
#[command(version, about, long_about = None)]
|
||||||
@@ -25,94 +26,84 @@ fn main() {
|
|||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
// You can check the value provided by positional arguments, or option arguments
|
// You can check the value provided by positional arguments, or option arguments
|
||||||
// Read the track from the tracks into the buffer
|
// Read the track from the tracks into the buffer
|
||||||
|
let mut data: Vec<f32>;
|
||||||
if let Some(files) = cli.track {
|
if let Some(files) = cli.track {
|
||||||
for file in files {
|
for file in files {
|
||||||
read_audio_file(file);
|
data = read_audio_file(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(backend) = cli.backend {
|
if let Some(backend) = cli.backend {
|
||||||
match backend {
|
match backend {
|
||||||
Backend::Jack => println!("jack"),
|
Backend::Jack => play_with_jack(),
|
||||||
Backend::Alsa => println!("alsa"),
|
Backend::Alsa => println!("alsa"),
|
||||||
Backend::Pulseaudio => println!("pulse"),
|
Backend::Pulseaudio => println!("pulse"),
|
||||||
Backend::Coreaudio => println!("coreaudio"),
|
Backend::Coreaudio => println!("coreaudio"),
|
||||||
|
Backend::Cpal => println!("cpal"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_audio_file(file: String) {
|
#[cfg(feature = "jack")]
|
||||||
let file = Box::new(File::open(file).unwrap());
|
fn play_with_jack(data: Vec<f32>) {
|
||||||
let mss = MediaSourceStream::new(file, Default::default());
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "jack"))]
|
||||||
|
fn play_with_jack(_: Vec<f32>) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_audio_file(path: String) -> Vec<f32>{
|
||||||
|
// Open file
|
||||||
|
let file = File::open(path).expect("Failed to open file");
|
||||||
|
let mss = MediaSourceStream::new(Box::new(file), Default::default());
|
||||||
|
|
||||||
|
// Hint format by extension
|
||||||
let mut hint = Hint::new();
|
let mut hint = Hint::new();
|
||||||
hint.with_extension("mp3");
|
|
||||||
let format_opts: FormatOptions = Default::default();
|
|
||||||
let metadata_opts: MetadataOptions = Default::default();
|
|
||||||
let decoder_opts: DecoderOptions = Default::default();
|
|
||||||
let probed =
|
|
||||||
symphonia::default::get_probe().format(&hint, mss, &format_opts, &metadata_opts).unwrap();
|
|
||||||
|
|
||||||
// Get the format reader yielded by the probe operation.
|
// Probe the file
|
||||||
|
let probed = symphonia::default::get_probe()
|
||||||
|
.format(&hint, mss, &FormatOptions::default(), &MetadataOptions::default())
|
||||||
|
.expect("Unsupported format");
|
||||||
|
|
||||||
let mut format = probed.format;
|
let mut format = probed.format;
|
||||||
|
let track = format.default_track().expect("No default track");
|
||||||
|
|
||||||
// Get the default track.
|
let mut decoder = symphonia::default::get_codecs()
|
||||||
let track = format.default_track().unwrap();
|
.make(&track.codec_params, &DecoderOptions::default())
|
||||||
|
.expect("Failed to create decoder");
|
||||||
|
|
||||||
// Create a decoder for the track.
|
let mut samples = Vec::new();
|
||||||
let mut decoder =
|
|
||||||
symphonia::default::get_codecs().make(&track.codec_params, &decoder_opts).unwrap();
|
|
||||||
|
|
||||||
// Store the track identifier, we'll use it to filter packets.
|
// Temporary sample buffer for decoding
|
||||||
let track_id = track.id;
|
|
||||||
|
|
||||||
let mut sample_count = 0;
|
|
||||||
let mut sample_buf = None;
|
let mut sample_buf = None;
|
||||||
|
|
||||||
loop {
|
while let Ok(packet) = format.next_packet() {
|
||||||
// Get the next packet from the format reader.
|
if packet.track_id() != track.id {
|
||||||
let packet = format.next_packet().unwrap();
|
|
||||||
|
|
||||||
// If the packet does not belong to the selected track, skip it.
|
|
||||||
if packet.track_id() != track_id {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode the packet into audio samples, ignoring any decode errors.
|
// Decode packet
|
||||||
match decoder.decode(&packet) {
|
match decoder.decode(&packet) {
|
||||||
Ok(audio_buf) => {
|
Ok(audio_buf) => {
|
||||||
// The decoded audio samples may now be accessed via the audio buffer if per-channel
|
// Create a f32 sample buffer if not already
|
||||||
// slices of samples in their native decoded format is desired. Use-cases where
|
|
||||||
// the samples need to be accessed in an interleaved order or converted into
|
|
||||||
// another sample format, or a byte buffer is required, are covered by copying the
|
|
||||||
// audio buffer into a sample buffer or raw sample buffer, respectively. In the
|
|
||||||
// example below, we will copy the audio buffer into a sample buffer in an
|
|
||||||
// interleaved order while also converting to a f32 sample format.
|
|
||||||
|
|
||||||
// If this is the *first* decoded packet, create a sample buffer matching the
|
|
||||||
// decoded audio buffer format.
|
|
||||||
if sample_buf.is_none() {
|
if sample_buf.is_none() {
|
||||||
// Get the audio buffer specification.
|
|
||||||
let spec = *audio_buf.spec();
|
let spec = *audio_buf.spec();
|
||||||
|
let capacity = audio_buf.capacity() as u64;
|
||||||
// Get the capacity of the decoded buffer. Note: This is capacity, not length!
|
sample_buf = Some(SampleBuffer::<f32>::new(capacity, spec));
|
||||||
let duration = audio_buf.capacity() as u64;
|
|
||||||
|
|
||||||
// Create the f32 sample buffer.
|
|
||||||
sample_buf = Some(SampleBuffer::<f32>::new(duration, spec));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the decoded audio buffer into the sample buffer in an interleaved format.
|
// Copy decoded data to f32 buffer
|
||||||
if let Some(buf) = &mut sample_buf {
|
if let Some(buf) = &mut sample_buf {
|
||||||
buf.copy_interleaved_ref(audio_buf);
|
buf.copy_interleaved_ref(audio_buf);
|
||||||
|
samples.extend(buf.samples());
|
||||||
// The samples may now be access via the `samples()` function.
|
|
||||||
sample_count += buf.samples().len();
|
|
||||||
print!("\rDecoded {} samples", sample_count);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(symphonia::core::errors::Error::DecodeError(_)) => (),
|
Err(_) => continue,
|
||||||
Err(_) => break,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
samples
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DecodedAudio {
|
pub struct DecodedAudio {
|
||||||
|
|||||||
Reference in New Issue
Block a user