| 629 | } |
| 630 | |
| 631 | AudioTensor MelFilterbank::compute_custom( |
| 632 | const std::vector<float> & power_spec, |
| 633 | int64_t batch, |
| 634 | int64_t freq_bins, |
| 635 | int64_t frames, |
| 636 | const AudioTensor & filterbank) const { |
| 637 | if (static_cast<int64_t>(power_spec.size()) != checked_product({batch, freq_bins, frames})) { |
| 638 | throw std::runtime_error("MelFilterbank input size mismatch"); |
| 639 | } |
| 640 | if (filterbank.shape.size() != 2 || filterbank.shape[1] != freq_bins) { |
| 641 | throw std::runtime_error("MelFilterbank custom filterbank shape mismatch"); |
| 642 | } |
| 643 | const int64_t n_mels = filterbank.shape[0]; |
| 644 | if (static_cast<int64_t>(filterbank.values.size()) != checked_product({n_mels, freq_bins})) { |
| 645 | throw std::runtime_error("MelFilterbank custom filterbank value count mismatch"); |
| 646 | } |
| 647 | |
| 648 | AudioTensor result; |
| 649 | result.shape = {batch, n_mels, frames}; |
| 650 | result.values.assign(static_cast<size_t>(checked_product({batch, n_mels, frames})), 0.0f); |
| 651 | #ifdef _OPENMP |
| 652 | #pragma omp parallel for collapse(3) if(batch * n_mels * frames >= 4096) |
| 653 | #endif |
| 654 | for (int64_t b = 0; b < batch; ++b) { |
| 655 | for (int64_t m = 0; m < n_mels; ++m) { |
| 656 | for (int64_t t = 0; t < frames; ++t) { |
| 657 | long double sum = 0.0; |
| 658 | for (int64_t f = 0; f < freq_bins; ++f) { |
| 659 | sum += static_cast<long double>(filterbank.values[static_cast<size_t>(m * freq_bins + f)]) * |
| 660 | static_cast<long double>(power_spec[static_cast<size_t>(((b * freq_bins) + f) * frames + t)]); |
| 661 | } |
| 662 | result.values[static_cast<size_t>(((b * n_mels) + m) * frames + t)] = static_cast<float>(sum); |
| 663 | } |
| 664 | } |
| 665 | } |
| 666 | return result; |
| 667 | } |
| 668 | |
| 669 | AudioTensor MelFilterbank::compute_custom_sparse_from_magnitude( |
| 670 | const std::vector<float> & magnitude, |
no test coverage detected