| 232 | } |
| 233 | |
| 234 | std::vector<float> build_soft_mask( |
| 235 | const std::vector<int32_t> & mask, |
| 236 | int64_t crossfade_frames) { |
| 237 | std::vector<float> soft_mask(mask.size(), 0.0F); |
| 238 | for (size_t i = 0; i < mask.size(); ++i) { |
| 239 | soft_mask[i] = mask[i] != 0 ? 1.0F : 0.0F; |
| 240 | } |
| 241 | if (crossfade_frames <= 0 || mask.empty()) { |
| 242 | return soft_mask; |
| 243 | } |
| 244 | const auto first = std::find(mask.begin(), mask.end(), 1); |
| 245 | if (first == mask.end()) { |
| 246 | return soft_mask; |
| 247 | } |
| 248 | const auto last = std::find(mask.rbegin(), mask.rend(), 1); |
| 249 | const int64_t left = static_cast<int64_t>(std::distance(mask.begin(), first)); |
| 250 | const int64_t right = static_cast<int64_t>(mask.size() - std::distance(mask.rbegin(), last)); |
| 251 | const int64_t fade_start = std::max<int64_t>(left - crossfade_frames, 0); |
| 252 | const int64_t left_ramp_len = left - fade_start; |
| 253 | for (int64_t i = 0; i < left_ramp_len; ++i) { |
| 254 | soft_mask[static_cast<size_t>(fade_start + i)] = |
| 255 | static_cast<float>(i + 1) / static_cast<float>(left_ramp_len + 1); |
| 256 | } |
| 257 | const int64_t fade_end = std::min<int64_t>(right + crossfade_frames, static_cast<int64_t>(mask.size())); |
| 258 | const int64_t right_ramp_len = fade_end - right; |
| 259 | for (int64_t i = 0; i < right_ramp_len; ++i) { |
| 260 | soft_mask[static_cast<size_t>(right + i)] = |
| 261 | static_cast<float>(right_ramp_len - i) / static_cast<float>(right_ramp_len + 1); |
| 262 | } |
| 263 | return soft_mask; |
| 264 | } |
| 265 | |
| 266 | std::vector<float> blend_by_mask( |
| 267 | const std::vector<float> & generated, |