Something stupid
Some checks failed
ci/woodpecker/push/pre_commit_test Pipeline was successful
ci/woodpecker/push/code_tests Pipeline failed

This commit is contained in:
2025-12-18 17:33:00 +01:00
parent 49e4f05b5e
commit 6bdb38bcee
3 changed files with 745 additions and 11 deletions

View File

@@ -1,14 +1,14 @@
use std::{fs::File, path::PathBuf};
use alsa::{Direction, PCM, ValueOr, device_name::Hint, pcm::{Access, Format, HwParams}};
use clap::{Parser, Subcommand, ValueEnum};
use symphonia::{core::{audio::{AudioBufferRef, Signal}, codecs::DecoderOptions, formats::FormatOptions, io::MediaSourceStream}, default::{get_codecs, get_probe}};
use symphonia::core::{audio::SampleBuffer, codecs::DecoderOptions, formats::FormatOptions, io::MediaSourceStream, meta::MetadataOptions, probe::Hint};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
enum Backend {
Jack,
Alsa,
Pulseaudio,
Coreaudio,
}
#[derive(Parser)]
#[command(version, about, long_about = None)]
@@ -17,18 +17,100 @@ struct Cli {
#[arg(short, long, value_enum)]
backend: Option<Backend>,
#[arg(short, long)]
path: String,
track: Option<Vec<String>>,
}
fn main() {
let cli = Cli::parse();
// You can check the value provided by positional arguments, or option arguments
// Read the track from the tracks into the buffer
if let Some(files) = cli.track {
for file in files {
read_audio_file(file);
}
}
if let Some(backend) = cli.backend {
match backend {
Backend::Jack => println!("jack"),
Backend::Alsa => println!("alsa"),
Backend::Pulseaudio => println!("pulse"),
Backend::Coreaudio => println!("coreaudio"),
}
}
}
fn read_audio_file(file: String) {
let file = Box::new(File::open(file).unwrap());
let mss = MediaSourceStream::new(file, Default::default());
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.
let mut format = probed.format;
// Get the default track.
let track = format.default_track().unwrap();
// Create a decoder for the track.
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.
let track_id = track.id;
let mut sample_count = 0;
let mut sample_buf = None;
loop {
// Get the next packet from the format reader.
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;
}
// Decode the packet into audio samples, ignoring any decode errors.
match decoder.decode(&packet) {
Ok(audio_buf) => {
// The decoded audio samples may now be accessed via the audio buffer if per-channel
// 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() {
// Get the audio buffer specification.
let spec = *audio_buf.spec();
// Get the capacity of the decoded buffer. Note: This is capacity, not length!
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.
if let Some(buf) = &mut sample_buf {
buf.copy_interleaved_ref(audio_buf);
// 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(_) => break,
}
}
}