Skip to content

Commit

Permalink
sound_len
Browse files Browse the repository at this point in the history
  • Loading branch information
Kapu1178 committed Nov 9, 2024
1 parent 9a4c784 commit 22f775b
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 0 deletions.
149 changes: 149 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ ammonia = { version = "4.0.0", optional = true }
fast_poisson = { version = "0.5.2", optional = true, features = [
"single_precision",
] } # Higher versions have problems with x86 due to 'kiddo'.
symphonia = { version = "0.5.4", optional = true }

[features]
default = [
Expand All @@ -79,6 +80,7 @@ default = [
"noise",
"rustls_tls",
"sanitize",
"sound_len",
"sql",
"time",
"toml",
Expand All @@ -98,6 +100,7 @@ all = [
"noise",
"rustls_tls",
"sanitize",
"sound_len",
"sql",
"time",
"toml",
Expand All @@ -123,6 +126,7 @@ http = ["ureq", "serde", "serde_json", "once_cell", "jobs"]
json = ["serde", "serde_json"]
log = ["chrono"]
sanitize = ["ammonia", "serde_json"]
sound_len = ["symphonia"]
sql = ["mysql", "serde", "serde_json", "once_cell", "dashmap", "jobs"]
time = []
toml = ["serde", "serde_json", "toml-dep"]
Expand Down
27 changes: 27 additions & 0 deletions dmsrc/soundlen.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/proc/rustg_sound_length(file_path)
var/static/list/sound_cache
if(isnull(sound_cache))
sound_cache = list()

. = 0

if(!istext(file_path))
if(!isfile(file_path))
CRASH("rustg_sound_length error: Passed non-text object")

if(length("[file_path]"))
file_path = "[file_path]"
else
CRASH("rustg_sound_length does not support non-static file refs.")

if(!isnull((. = sound_cache[file_path])))
return .

var/ret = RUSTG_CALL(RUST_G, "sound_len")(file_path)
var/as_num = text2num(ret)
if(isnull(ret))
. = 0
CRASH("rustg_sound_length error: [ret]")

sound_cache[file_path] = as_num
return as_num
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ pub mod redis_pubsub;
pub mod redis_reliablequeue;
#[cfg(feature = "sanitize")]
pub mod sanitize;
#[cfg(feature = "sound_len")]
pub mod sound_len;
#[cfg(feature = "sql")]
pub mod sql;
#[cfg(feature = "time")]
Expand Down
94 changes: 94 additions & 0 deletions src/sound_len.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use crate::error::Result;
use symphonia::{
self,
core::{
codecs::DecoderOptions,
formats::FormatOptions,
io::MediaSourceStream,
meta::MetadataOptions,
probe::Hint
},
default::{get_codecs, get_probe},
};
use std::{
fs::File,
path::Path,
};

byond_fn!(fn sound_len(sound_path) {
match get_sound_length(sound_path) {
Ok(r) => return Some(r),
Err(e) => return Some(e.to_string())
}
});

fn get_sound_length (sound_path: &str) -> Result<String> {
let path = Path::new(sound_path);

// Gracefully exit if the filepath is invalid.
if !path.exists() {
return Ok(String::from("path doesnt exist!"));
}

// Try to open the file
let sound_src = match File::open(&path) {
Ok(r) => r,
Err(_e) => return Ok(String::from("Couldn't open file!")),
};


// Audio probe things
let mss = MediaSourceStream::new(Box::new(sound_src), Default::default());

let mut hint = Hint::new();
hint.with_extension("ogg");

let meta_opts: MetadataOptions = Default::default();
let mut fmt_opts: FormatOptions = Default::default();
fmt_opts.enable_gapless = true;

let probed = match get_probe().format(&hint, mss, &fmt_opts, &meta_opts) {
Ok(r) => r,
Err(_e) => return Ok(String::from("Failed to probe file!")),
};

let mut format = probed.format;

let track = match format.default_track() {
Some(r) => r,
None => return Ok(String::from("Failed to grab track from container!")),
};

// Grab the number of frames of the track
let samples_capacity: f64 = if let Some(n_frames) = track.codec_params.n_frames {
n_frames as f64
} else {
0.0
};

// Create a decoder using the provided codec parameters in the track.
let decoder_opts: DecoderOptions = Default::default();
let mut decoder = match get_codecs().make(&track.codec_params, &decoder_opts) {
Ok(r) => r,
Err(_e) => return Ok(String::from("Failed to generate decoder!")),
};

// Try to grab a data packet from the container
let encoded_packet = match format.next_packet() {
Ok(r) => r,
Err(_e) => return Ok(String::from("Failed to grab packet from container!")),
};

// Try to decode the data packet
let decoded_packet = match decoder.decode(&encoded_packet) {
Ok(r) => r,
Err(_e) => return Ok(String::from("Failed to decode packet!"))
};

// Grab the sample rate from the spec of the buffer.
let sample_rate: f64 = decoded_packet.spec().rate as f64;
// Math!
let duration_in_seconds: f32 = (samples_capacity / sample_rate) as f32;
return Ok(duration_in_seconds.to_string());

}

0 comments on commit 22f775b

Please sign in to comment.