Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions .github/workflows/mlsafir.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ on:
pull_request:
paths:
- src/vocoder/mlsa.rs
- src/mlpg_adjust/**

jobs:
collect:
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ mod tests {

assert_eq!(speech.len(), 74880);
approx::assert_abs_diff_eq!(speech[2000], 2.3158134981607754e-5, epsilon = 1.0e-10);
approx::assert_abs_diff_eq!(speech[30000], 6459.375032316974, epsilon = 1.0e-10);
approx::assert_abs_diff_eq!(speech[30000], 6459.375032318177, epsilon = 1.0e-10);
}

// これ,名詞,代名詞,一般,*,*,*,これ,コレ,コレ,0/2,C3,-1
Expand Down Expand Up @@ -127,7 +127,7 @@ mod tests {

assert_eq!(speech.len(), 100800);
approx::assert_abs_diff_eq!(speech[2000], 17.15977345625943, epsilon = 1.0e-10);
approx::assert_abs_diff_eq!(speech[30000], 2566.2058730889985, epsilon = 1.0e-10);
approx::assert_abs_diff_eq!(speech[30000], 2566.205873089126, epsilon = 1.0e-10);
approx::assert_abs_diff_eq!(speech[70000], -1898.2890228814217, epsilon = 1.0e-10);
approx::assert_abs_diff_eq!(speech[100799], -13.514971382534956, epsilon = 1.0e-10);
}
Expand Down
207 changes: 96 additions & 111 deletions src/mlpg_adjust/mask.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,55 @@
//!
//! The unvoiced frames are determined using multi-space probability distribution (MSD) parameter in stream.

use crate::model::StreamParameter;
use std::ops::Range;

use super::IterExt;
use crate::model::StreamParameter;

/// Mask for unvoiced frames
pub struct Mask(Vec<bool>);

impl FromIterator<bool> for Mask {
fn from_iter<I: IntoIterator<Item = bool>>(iter: I) -> Self {
Self(iter.into_iter().collect())
}
pub struct Mask {
// matches the length of `durations`
pub(super) ranged_durations: Vec<Range<usize>>,
// contiguous ranges joined together
pub(super) voiced_ranges: Vec<Range<usize>>,
}

impl Mask {
/// Create mask from `msd` field in stream with lengths of `durations`.
pub fn create(stream: &StreamParameter, threshold: f64, durations: &[usize]) -> Self {
Self(
stream
.iter()
.map(|(_, msd)| *msd > threshold)
.duration(durations)
.collect(),
)
let mut i = 0;
let mut ranged_durations = Vec::with_capacity(durations.len());
let mut voiced_ranges: Vec<Range<usize>> = Vec::new();
for ((_, msd), duration) in stream.iter().zip(durations) {
let range = i..(i + duration);
if *msd > threshold {
if let Some(last) = voiced_ranges.last_mut()
&& last.end == range.start
{
last.end = range.end;
} else {
voiced_ranges.push(range.clone());
}
}
ranged_durations.push(range);
i += duration;
}
Self {
ranged_durations,
voiced_ranges,
}
}
pub fn len(&self) -> usize {
self.ranged_durations.last().map_or(0, |r| r.end)
}
/// Get the internal mask.
pub fn mask(&self) -> &[bool] {
&self.0
pub fn voiced_len(&self) -> usize {
self.voiced_ranges.iter().map(|r| r.len()).sum()
}
fn mask(&self) -> Vec<bool> {
let mut out = vec![false; self.len()];
for range in &self.voiced_ranges {
out[range.clone()].fill(true);
}
out
}
/// Fill back the masked region with `default` and returns an iterator of full-length sequence.
pub fn fill<'a, T: 'a + Clone>(
Expand All @@ -37,124 +59,87 @@ impl Mask {
default: T,
) -> impl 'a + Iterator<Item = T> {
let mut iter = masked.into_iter();
self.0.iter().map(move |&mask| {
if mask {
iter.next().expect(
"Length of `masked` must be the same as the number of `true`'s in mask.",
)
self.mask().into_iter().map(move |is_voiced| {
if is_voiced {
iter.next().unwrap()
} else {
default.clone()
}
})
}
/// Get distances from left- and right-boundaries.
pub fn boundary_distances(&self) -> Vec<(usize, usize)> {
if self.0.is_empty() {
return vec![];
}
}

let mut result = vec![(0, 0); self.0.len()];
#[derive(Debug)]
pub struct IntoIter<'a> {
ranged_durations: std::slice::Iter<'a, Range<usize>>,
voiced_ranges: std::slice::Iter<'a, Range<usize>>,
next_voiced_range: Option<&'a Range<usize>>,
}

let mut left = 0;
for (frame, mask) in self.0.iter().enumerate() {
if *mask {
result[frame].0 = frame - left;
} else {
// current position will be cut off
left = frame + 1;
}
impl<'a> IntoIter<'a> {
pub fn new(mask: &'a Mask) -> Self {
let ranged_durations = mask.ranged_durations.iter();
let mut voiced_ranges = mask.voiced_ranges.iter();
let next_voiced_range = voiced_ranges.next();
Self {
ranged_durations,
voiced_ranges,
next_voiced_range,
}
}
}

let mut right = self.0.len() - 1;
for (frame, mask) in self.0.iter().enumerate().rev() {
if *mask {
result[frame].1 = right - frame;
} else {
// current position will be cut off
if frame == 0 {
break;
}
right = frame - 1;
}
impl Iterator for IntoIter<'_> {
type Item = (Range<usize>, Option<Range<usize>>);

fn next(&mut self) -> Option<Self::Item> {
let range = self.ranged_durations.next()?;
let voiced_range = self
.next_voiced_range
.filter(|r| r.start <= range.start && range.end <= r.end);
if voiced_range.is_some_and(|r| r.end == range.end) {
self.next_voiced_range = self.voiced_ranges.next();
}
Some((range.clone(), voiced_range.cloned()))
}
}

impl<'a> IntoIterator for &'a Mask {
type Item = <IntoIter<'a> as Iterator>::Item;
type IntoIter = IntoIter<'a>;

result
fn into_iter(self) -> Self::IntoIter {
IntoIter::new(self)
}
}

#[cfg(test)]
#[allow(
clippy::single_range_in_vec_init,
reason = "intended vec of single range"
)]
mod tests {
use super::Mask;

#[test]
fn fill() {
assert_eq!(
Mask(vec![false, false, true, true, false, true])
.fill([0, 1, 2], 5)
.collect::<Vec<_>>(),
Mask {
ranged_durations: vec![0..2, 2..4, 4..5, 5..6],
voiced_ranges: vec![2..4, 5..6]
}
.fill([0, 1, 2], 5)
.collect::<Vec<_>>(),
vec![5, 5, 0, 1, 5, 2]
);
assert_eq!(
Mask(vec![false, false]).fill([0, 1], 5).collect::<Vec<_>>(),
Mask {
ranged_durations: vec![0..2],
voiced_ranges: vec![]
}
.fill([0, 1], 5)
.collect::<Vec<_>>(),
vec![5, 5]
);
}
#[test]
fn boundary_distances() {
assert_eq!(
Mask(vec![
true, true, true, true, true, true, true, true, true, true
])
.boundary_distances(),
vec![
(0, 9),
(1, 8),
(2, 7),
(3, 6),
(4, 5),
(5, 4),
(6, 3),
(7, 2),
(8, 1),
(9, 0)
],
);
assert_eq!(
Mask(vec![
true, true, true, false, false, true, true, true, true, true
])
.boundary_distances(),
vec![
(0, 2),
(1, 1),
(2, 0),
(0, 0),
(0, 0),
(0, 4),
(1, 3),
(2, 2),
(3, 1),
(4, 0)
]
);
assert_eq!(
Mask(vec![
true, true, true, false, true, false, false, false, false, false
])
.boundary_distances(),
vec![
(0, 2),
(1, 1),
(2, 0),
(0, 0),
(0, 0),
(0, 0),
(0, 0),
(0, 0),
(0, 0),
(0, 0)
]
);
assert_eq!(Mask(vec![]).boundary_distances(), vec![]);
}
}
Loading
Loading