Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: rustg_sound_length() #192

Merged
merged 8 commits into from
Nov 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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",
ZeWaka marked this conversation as resolved.
Show resolved Hide resolved
"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"]
Kapu1178 marked this conversation as resolved.
Show resolved Hide resolved
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)
Kapu1178 marked this conversation as resolved.
Show resolved Hide resolved
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 {
Kapu1178 marked this conversation as resolved.
Show resolved Hide resolved
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;
ZeWaka marked this conversation as resolved.
Show resolved Hide resolved
return Ok(duration_in_seconds.to_string());

}
Loading