Implement merge and play, refactor

This commit is contained in:
Julius Koskela 2022-09-25 17:44:48 +03:00
parent 16a2c5c47c
commit e81028d751
12 changed files with 450 additions and 92 deletions

222
audio-logger/Cargo.lock generated
View File

@ -51,20 +51,21 @@ dependencies = [
]
[[package]]
name = "audio-logger"
name = "audio"
version = "0.1.0"
dependencies = [
"alsa",
"anyhow",
"chrono",
"clap",
"cpal",
"cpal 0.13.5",
"ctrlc",
"hound",
"jack 0.9.2",
"libc",
"nix 0.23.1",
"parking_lot 0.12.1",
"rodio",
]
[[package]]
@ -104,6 +105,12 @@ version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.2.1"
@ -205,6 +212,12 @@ dependencies = [
"os_str_bytes",
]
[[package]]
name = "claxon"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688"
[[package]]
name = "combine"
version = "4.6.6"
@ -255,7 +268,7 @@ dependencies = [
"lazy_static",
"libc",
"mach",
"ndk",
"ndk 0.6.0",
"ndk-glue",
"nix 0.23.1",
"oboe",
@ -266,6 +279,31 @@ dependencies = [
"winapi",
]
[[package]]
name = "cpal"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d466b47cf0ea4100186a7c12d7d0166813dda7cf648553554c9c39c6324841b"
dependencies = [
"alsa",
"core-foundation-sys",
"coreaudio-rs",
"jni",
"js-sys",
"libc",
"mach",
"ndk 0.7.0",
"ndk-context",
"nix 0.23.1",
"oboe",
"once_cell",
"parking_lot 0.12.1",
"stdweb",
"thiserror",
"web-sys",
"windows",
]
[[package]]
name = "ctrlc"
version = "3.2.3"
@ -276,6 +314,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "cty"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
[[package]]
name = "darling"
version = "0.13.4"
@ -523,6 +567,17 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "lewton"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030"
dependencies = [
"byteorder",
"ogg",
"tinyvec",
]
[[package]]
name = "libc"
version = "0.2.133"
@ -598,6 +653,26 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "minimp3"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372"
dependencies = [
"minimp3-sys",
"slice-deque",
"thiserror",
]
[[package]]
name = "minimp3-sys"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90"
dependencies = [
"cc",
]
[[package]]
name = "ndk"
version = "0.6.0"
@ -606,11 +681,25 @@ checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4"
dependencies = [
"bitflags",
"jni-sys",
"ndk-sys",
"ndk-sys 0.3.0",
"num_enum",
"thiserror",
]
[[package]]
name = "ndk"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0"
dependencies = [
"bitflags",
"jni-sys",
"ndk-sys 0.4.0",
"num_enum",
"raw-window-handle",
"thiserror",
]
[[package]]
name = "ndk-context"
version = "0.1.1"
@ -626,10 +715,10 @@ dependencies = [
"lazy_static",
"libc",
"log",
"ndk",
"ndk 0.6.0",
"ndk-context",
"ndk-macro",
"ndk-sys",
"ndk-sys 0.3.0",
]
[[package]]
@ -654,6 +743,15 @@ dependencies = [
"jni-sys",
]
[[package]]
name = "ndk-sys"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21d83ec9c63ec5bf950200a8e508bdad6659972187b625469f58ef8c08e29046"
dependencies = [
"jni-sys",
]
[[package]]
name = "nix"
version = "0.23.1"
@ -747,7 +845,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1"
dependencies = [
"jni",
"ndk",
"ndk 0.6.0",
"ndk-context",
"num-derive",
"num-traits",
@ -763,6 +861,15 @@ dependencies = [
"cc",
]
[[package]]
name = "ogg"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e"
dependencies = [
"byteorder",
]
[[package]]
name = "once_cell"
version = "1.15.0"
@ -906,6 +1013,15 @@ dependencies = [
"proc-macro2 1.0.43",
]
[[package]]
name = "raw-window-handle"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed7e3d950b66e19e0c372f3fa3fbbcf85b1746b571f74e0c2af6042a5c93420a"
dependencies = [
"cty",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -930,6 +1046,19 @@ version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "rodio"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb10b653d5ec0e9411a2e7d46e2c7f4046fd87d35b9955bd73ba4108d69072b5"
dependencies = [
"claxon",
"cpal 0.14.0",
"hound",
"lewton",
"minimp3",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
@ -963,6 +1092,17 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "slice-deque"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25"
dependencies = [
"libc",
"mach",
"winapi",
]
[[package]]
name = "smallvec"
version = "1.9.0"
@ -1049,6 +1189,21 @@ dependencies = [
"winapi",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "toml"
version = "0.5.9"
@ -1188,17 +1343,30 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647"
dependencies = [
"windows_aarch64_msvc 0.37.0",
"windows_i686_gnu 0.37.0",
"windows_i686_msvc 0.37.0",
"windows_x86_64_gnu 0.37.0",
"windows_x86_64_msvc 0.37.0",
]
[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
"windows_aarch64_msvc 0.36.1",
"windows_i686_gnu 0.36.1",
"windows_i686_msvc 0.36.1",
"windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc 0.36.1",
]
[[package]]
@ -1207,26 +1375,56 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "windows_x86_64_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d"

View File

@ -1,5 +1,5 @@
[package]
name = "audio-logger"
name = "audio"
version = "0.1.0"
edition = "2021"
@ -10,6 +10,7 @@ anyhow = "1.0.61"
hound = "3.4.0"
chrono = "0.4.22"
ctrlc = "3.2.3"
rodio = "0.16.0"
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"))'.dependencies]
alsa = "0.6"

View File

@ -1,9 +1,10 @@
test: all
bash run_test.sh
all:
cargo build --release
test:
cargo build --release
mkdir -p recordings
bash run_test.sh
clean:
cargo clean
@ -14,4 +15,4 @@ fclean: clean
re: fclean
cargo build --release
.PHONY: all clean re test
.PHONY: all clean fclean re test

View File

@ -1,4 +1,4 @@
use clap::{Parser, ValueEnum};
use clap::{Parser, ValueEnum, Subcommand};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
pub enum Hosts {
@ -6,9 +6,39 @@ pub enum Hosts {
Jack,
}
#[derive(Subcommand)]
#[clap(about = "A tool to record audio on Linux using the command line.")]
pub enum Commands {
/// Record audio either continously or in batches (in case a possible
/// interruption is an issue)
Rec(Rec),
/// Play audio from a .wav file
Play(Play),
/// Merge audio resulting from a batch recording into a single file
Merge(Merge),
/// Get reports of system's audio resources
Info(Info),
}
#[derive(Parser, Debug)]
#[clap(about = "A tool to record audio.")]
pub struct Args {
#[clap(about = "Merge audio resulting from a batch recording into a single
file.
")]
pub struct Merge {
/// The directory to look for files to merge.
#[clap(short, long, default_value = "./", required = true)]
pub input: std::path::PathBuf,
/// The directory to save the merged file to.
#[clap(short, long, default_value = "./")]
pub output: std::path::PathBuf,
}
#[derive(Parser, Debug)]
#[clap(about = "Record audio either continously or in batches (in case a
possible interruption is an issue).
")]
pub struct Rec {
/// Filename will be `[NAME]-yyyy-mm-dd-H:M:S.wav`
#[clap(required = true, short, long)]
@ -22,10 +52,6 @@ pub struct Args {
#[clap(short, long, value_name = "SECONDS")]
pub batch_recording: Option<u64>,
/// Output the available devices and their configurations
#[clap(long)]
pub print_configs: bool,
/// Host API to use
#[clap(value_enum)]
pub host: Hosts,
@ -42,3 +68,27 @@ pub struct Args {
#[clap(long, value_name = "FRAMES")]
pub buffer_size: Option<u32>,
}
#[derive(Parser, Debug)]
#[clap(about = "Play audio from a .wav file.
")]
pub struct Play {
/// Path to the file to play
#[clap(value_parser, value_name = "PATH", value_hint = clap::ValueHint::FilePath)]
pub input: std::path::PathBuf,
}
#[derive(Parser, Debug)]
#[clap(about = "Get reports of system's audio resources.")]
pub struct Info {
/// Output the available devices and their configurations
#[clap(long)]
pub print_configs: bool,
}
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
#[clap(propagate_version = true)]
pub struct Cli {
#[clap(subcommand)]
pub command: Commands,
}

View File

@ -0,0 +1,7 @@
pub const DEFAULT_SAMPLE_RATE: u32 = 44100;
pub const DEFAULT_CHANNEL_COUNT: u16 = 1;
pub const DEFAULT_BUFFER_SIZE: u32 = 1024;
pub const ALLOWED_SAMPLE_RATES: [u32; 6] = [44100, 48000, 88200, 96000, 176400, 192000];
pub const MAX_CHANNEL_COUNT: u16 = 2;
pub const MIN_BUFFER_SIZE: usize = 64;
pub const MAX_BUFFER_SIZE: usize = 8192;

View File

@ -1,10 +1,18 @@
use cpal::traits::{DeviceTrait, HostTrait};
use cpal::*;
use std::path::PathBuf;
use hound::WavSpec;
use chrono::prelude::*;
use anyhow::{Error, anyhow};
use super::*;
use cpal::{
StreamConfig,
SupportedStreamConfig,
Device,
HostId,
Host,
SampleRate,
BufferSize,
traits::{DeviceTrait, HostTrait},
};
use hound::WavSpec;
use std::path::PathBuf;
use chrono::*;
use anyhow::{Error, Result, anyhow};
/// # Get Host
///
@ -86,17 +94,20 @@ pub fn get_wav_spec(default_config: &SupportedStreamConfig, user_config: &Stream
})
}
pub fn get_date_time_string() -> String {
let now: DateTime<Local> = Local::now();
format!(
"{}-{}-{}_{}:{}:{}",
now.year(), now.month(), now.day(),
now.hour(), now.minute(), now.second(),
)
}
/// # Get Filename
///
/// Get the filename for the current recording according to the given format,
/// the current date and time, and the name prefix.
pub fn get_filename(name: &str, path: &PathBuf) -> String {
let now: DateTime<Local> = Local::now();
let filename = format!(
"{}-{}-{}-{}-{}:{}:{}.wav",
name,
now.year(), now.month(), now.day(),
now.hour(), now.minute(), now.second(),
);
path.join(filename).to_str().unwrap().to_string()
let mut filename = path.clone();
filename.push(format!("{}_{}.wav", get_date_time_string(), name));
filename.to_str().unwrap().to_string()
}

View File

@ -1,5 +1,10 @@
use std::sync::{Arc, Mutex};
use super::*;
use std::sync::{
Arc,
Mutex,
Condvar,
atomic::{AtomicBool, Ordering}
};
type StreamInterrupt = Arc<(Mutex<bool>, Condvar)>;
type BatchInterrupt= Arc<AtomicBool>;

View File

@ -1,59 +1,43 @@
//! Records a WAV file (roughly 3 seconds long) using the default input device and config.
//!
//! The input data is recorded to "$CARGO_MANIFEST_DIR/recorded.wav".
//! # Main
mod cli;
mod recorder;
mod print_configs;
mod getters;
mod input_handling;
mod merge;
mod constants;
mod play;
use clap::Parser;
use recorder::{batch_recording, contiguous_recording};
use cli::*;
use std::path::Path;
use print_configs::*;
use std::sync::{Condvar, atomic::{AtomicBool, Ordering}};
use cli::*;
use merge::*;
use recorder::*;
use constants::*;
use getters::*;
use input_handling::*;
use play::*;
const DEFAULT_SAMPLE_RATE: u32 = 44100;
const DEFAULT_CHANNEL_COUNT: u16 = 1;
const DEFAULT_BUFFER_SIZE: u32 = 1024;
const ALLOWED_SAMPLE_RATES: [u32; 6] = [44100, 48000, 88200, 96000, 176400, 192000];
const MAX_CHANNEL_COUNT: u16 = 2;
const MIN_BUFFER_SIZE: usize = 64;
const MAX_BUFFER_SIZE: usize = 8192;
use anyhow::{Result, Error};
use clap::Parser;
fn main() -> Result<(), anyhow::Error> {
let args = Args::parse();
fn main() -> Result<(), Error> {
let cli = Cli::parse();
if args.print_configs {
print_configs()?;
return Ok(());
}
let mut recorder = recorder::Recorder::init(
args.name.clone(),
match args.output.clone() {
Some(path) => path,
None => Path::new("./").to_path_buf(),
match &cli.command {
Commands::Rec(args) => {
record(&args)?;
},
match args.host {
Hosts::Alsa => cpal::HostId::Alsa,
Hosts::Jack => cpal::HostId::Jack,
Commands::Play(args) => {
play(&args.input)?;
},
args.sample_rate.unwrap_or(DEFAULT_SAMPLE_RATE),
args.channels.unwrap_or(DEFAULT_CHANNEL_COUNT),
args.buffer_size.unwrap_or(DEFAULT_BUFFER_SIZE),
)?;
match args.batch_recording {
Some(secs) => {
batch_recording(&mut recorder, secs)?;
Commands::Info(args) => {
if args.print_configs {
print_configs()?;
}
},
None => {
contiguous_recording(&mut recorder)?;
Commands::Merge(args) => {
merge_wavs(&args.input, &args.output)?;
}
}
Ok(())
}

43
audio-logger/src/merge.rs Normal file
View File

@ -0,0 +1,43 @@
use hound::{WavReader, WavWriter};
use anyhow::{Result, Error};
pub fn merge_wavs(input: &std::path::PathBuf, output: &std::path::PathBuf) -> Result<(), Error> {
// Read files from input directory
let mut files = std::fs::read_dir(input)?
.filter_map(|entry| entry.ok())
.filter(|entry| entry.file_type().ok().map(|t| t.is_file()).unwrap_or(false))
.filter(|entry| entry.path().extension().unwrap_or_default() == "wav")
.collect::<Vec<_>>();
// Sort files by name
files.sort_by(|a, b| a.file_name().cmp(&b.file_name()));
// Use the name of the first file as the name of the output file
let output_name = files.first().unwrap().file_name();
let output_name = output_name.to_str().unwrap();
// Get wav spec from file
let spec = WavReader::open(files.first().unwrap().path())?.spec();
let mut writer = WavWriter::create(output.join(output_name), spec)?;
match spec.sample_format {
hound::SampleFormat::Float => {
for file in files {
let mut reader = WavReader::open(file.path())?;
for sample in reader.samples::<f32>() {
writer.write_sample(sample?)?;
}
}
},
hound::SampleFormat::Int => {
for file in files {
let mut reader = WavReader::open(file.path())?;
for sample in reader.samples::<i32>() {
writer.write_sample(sample?)?;
}
}
},
}
writer.finalize()?;
Ok(())
}

14
audio-logger/src/play.rs Normal file
View File

@ -0,0 +1,14 @@
//! Play audio from a .wav file.
use anyhow::{Error, Result};
use rodio::{Decoder, OutputStream, Sink};
pub fn play(path: &std::path::PathBuf) -> Result<(), Error> {
let file = std::fs::File::open(path)?;
let source = Decoder::new(file).unwrap();
let (_stream, stream_handle) = OutputStream::try_default()?;
let sink = Sink::try_new(&stream_handle)?;
sink.append(source);
sink.sleep_until_end();
Ok(())
}

View File

@ -1,5 +1,19 @@
use cpal::traits::{DeviceTrait, HostTrait};
// pub fn print_available_hosts() -> Result<(), anyhow::Error> {
// let hosts = cpal::available_hosts();
// println!("Available hosts:");
// for host in hosts {
// println!(" {}", host.name());
// }
// Ok(())
// }
// pub fn print_supported_hosts() {
// println!("Supported hosts:");
// println!("{:?}", cpal::ALL_HOSTS);
// }
pub fn print_configs() -> Result<(), anyhow::Error> {
println!("Supported hosts:\n {:?}", cpal::ALL_HOSTS);
let available_hosts = cpal::available_hosts();

View File

@ -1,12 +1,20 @@
use cpal::traits::{DeviceTrait, StreamTrait};
use cpal::*;
use std::fs::File;
use std::io::BufWriter;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use crate::getters::*;
use crate::input_handling::*;
use super::*;
use cpal::{
StreamConfig,
SupportedStreamConfig,
Device,
HostId,
Stream,
traits::{DeviceTrait, StreamTrait},
};
use std::{
fs::File,
io::BufWriter,
path::{PathBuf, Path},
sync::{Arc, Mutex},
};
use anyhow::Error;
type WriteHandle = Arc<Mutex<Option<hound::WavWriter<BufWriter<File>>>>>;
pub struct Recorder {
@ -85,7 +93,7 @@ impl Recorder {
fn create_stream(&self) -> Result<Stream, Error> {
let writer = self.writer.clone();
let config = self.user_config.clone();
let err_fn = |err| { eprintln!("An error occurred on stream: {}", err); };
let err_fn = |err| { eprintln!("{}: An error occurred on stream: {}", get_date_time_string(), err); };
let stream = match self.default_config.sample_format() {
cpal::SampleFormat::F32 => self.device.build_input_stream(
@ -161,14 +169,36 @@ where
}
}
pub fn batch_recording(rec: &mut Recorder, secs: u64) -> Result<(), Error> {
fn batch_recording(rec: &mut Recorder, secs: u64) -> Result<(), Error> {
while rec.interrupt_handles.batch_is_running() {
rec.record_secs(secs)?;
}
Ok(())
}
pub fn contiguous_recording(rec: &mut Recorder) -> Result<(), Error> {
fn continuous_recording(rec: &mut Recorder) -> Result<(), Error> {
rec.record()?;
Ok(())
}
pub fn record(args: &Rec) -> Result<(), Error> {
let mut recorder = Recorder::init(
args.name.clone(),
match args.output.clone() {
Some(path) => path,
None => Path::new("./").to_path_buf(),
},
match args.host {
Hosts::Alsa => cpal::HostId::Alsa,
Hosts::Jack => cpal::HostId::Jack,
},
args.sample_rate.unwrap_or(DEFAULT_SAMPLE_RATE),
args.channels.unwrap_or(DEFAULT_CHANNEL_COUNT),
args.buffer_size.unwrap_or(DEFAULT_BUFFER_SIZE),
)?;
match args.batch_recording {
Some(seconds) => batch_recording(&mut recorder, seconds),
None => continuous_recording(&mut recorder),
}
}