| 62 | } |
| 63 | |
| 64 | bool Wav2LetterPreprocessor::Invoke(const float* audioData, const uint32_t audioDataLen, std::vector<int8_t>& output, |
| 65 | int quantOffset, float quantScale) |
| 66 | { |
| 67 | this->m_window = SlidingWindow<const float>( |
| 68 | audioData, audioDataLen, |
| 69 | this->m_windowLen, this->m_windowStride); |
| 70 | |
| 71 | uint32_t mfccBufIdx = 0; |
| 72 | |
| 73 | // Init buffers with 0 |
| 74 | std::fill(m_mfccBuf.begin(), m_mfccBuf.end(), 0.f); |
| 75 | std::fill(m_delta1Buf.begin(), m_delta1Buf.end(), 0.f); |
| 76 | std::fill(m_delta2Buf.begin(), m_delta2Buf.end(), 0.f); |
| 77 | |
| 78 | // While we can slide over the window |
| 79 | while (this->m_window.HasNext()) |
| 80 | { |
| 81 | const float* mfccWindow = this->m_window.Next(); |
| 82 | auto mfccAudioData = std::vector<float>( |
| 83 | mfccWindow, |
| 84 | mfccWindow + this->m_windowLen); |
| 85 | |
| 86 | auto mfcc = this->m_mfcc->MfccCompute(mfccAudioData); |
| 87 | for (size_t i = 0; i < this->m_mfccBuf.size(0); ++i) |
| 88 | { |
| 89 | this->m_mfccBuf(i, mfccBufIdx) = mfcc[i]; |
| 90 | } |
| 91 | ++mfccBufIdx; |
| 92 | } |
| 93 | |
| 94 | // Pad MFCC if needed by repeating last feature vector |
| 95 | while (mfccBufIdx != this->m_mfcc->m_params.m_numMfccVectors) |
| 96 | { |
| 97 | memcpy(&this->m_mfccBuf(0, mfccBufIdx), |
| 98 | &this->m_mfccBuf(0, mfccBufIdx - 1), sizeof(float) * this->m_mfcc->m_params.m_numMfccFeatures); |
| 99 | ++mfccBufIdx; |
| 100 | } |
| 101 | |
| 102 | // Compute first and second order deltas from MFCCs |
| 103 | Wav2LetterPreprocessor::ComputeDeltas(this->m_mfccBuf, |
| 104 | this->m_delta1Buf, |
| 105 | this->m_delta2Buf); |
| 106 | |
| 107 | // Normalise |
| 108 | this->Normalise(); |
| 109 | |
| 110 | return this->Quantise<int8_t>(output.data(), quantOffset, quantScale); |
| 111 | } |
| 112 | |
| 113 | bool Wav2LetterPreprocessor::ComputeDeltas(Array2d<float>& mfcc, |
| 114 | Array2d<float>& delta1, |