23 m_hopSizeSamples =
static_cast<int>(round(m_sampleRate * m_hopSizeSec));
26 m_earFilter.configure(fs);
29 m_hi = std::min(m_hi, m_sampleRate / 2.0f - cferb(m_sampleRate / 2.0f) / 2.0f);
32 m_wSize =
static_cast<int>(std::pow(2.0f, getNextPowerOfTwo(m_ERD * m_sampleRate * 2.0f)));
35 m_gtWin = gtWindow(m_wSize, (
float)m_wSize / (m_ERD * m_sampleRate), 4);
41 std::vector<float> filteredSignal = applyEarFilter(inputSignal);
42 int length =
static_cast<int>(filteredSignal.size());
46 std::vector<float> gtWinSquared;
47 gtWinSquared.reserve(m_gtWin.size());
49 std::transform(m_gtWin.begin(), m_gtWin.end(), std::back_inserter(gtWinSquared), [](
float n) { return n * n; });
51 int zpOffest =
static_cast<int>(std::ceil(centroid(gtWinSquared) - 1.0f));
53 filteredSignal.insert(filteredSignal.begin(), zpOffest, 0.0f);
56 int lastIndex = (length - (m_wSize - zpOffest)) / m_hopSizeSamples * m_hopSizeSamples + 1;
57 std::vector<float> startSamples;
58 for (
int i = 0; i <= lastIndex; i += m_hopSizeSamples)
60 startSamples.push_back(
static_cast<float>(i));
64 buildFilterBank(
static_cast<int>(startSamples.size()));
67 std::vector<std::vector<float>> fr(m_wSize, std::vector<float>(startSamples.size()));
70 for (
int i = 0; i < startSamples.size(); ++i)
72 for (
int j = 0; j < m_wSize; ++j)
74 fr[j][i] = filteredSignal[
static_cast<int>(startSamples[i]) + j] * m_gtWin[j];
79 std::vector<std::vector<float>> powerSpec = calculatePowerSpectrum(fr);
81 std::vector<std::vector<float>> tmp(powerSpec[0].size(), std::vector<float>(m_wfunct[0].size(), 0.0f));
83 for (
size_t i = 0; i < m_wfunct[0].size(); ++i)
85 for (
size_t j = 0; j < powerSpec[0].size(); ++j)
87 for (
size_t k = 0; k < m_wfunct.size(); ++k)
89 tmp[j][i] +=
static_cast<float>(m_wfunct[k][i]) * powerSpec[k][j];
91 tmp[j][i] = std::pow(tmp[j][i], 0.25f);
115 std::vector<float> b = cferb(m_cfArray);
118 float scalar = 0.982f;
119 transform(b.begin(), b.end(), b.begin(), [scalar](
float value) { return value / scalar; });
121 std::vector<float> bb(b.size());
122 transform(b.begin(), b.end(), bb.begin(), [=](
float x) {
123 float diffSquared = x * x - m_b0 * m_b0;
124 return std::sqrt(diffSquared);
129 std::vector<std::vector<float>> fSupport(m_wSize / 2, std::vector<float>(m_numChans));
130 for (
int i = 0; i < m_wSize / 2; i++)
132 for (
int j = 0; j < m_numChans; j++)
134 fSupport[i][j] =
static_cast<float>(i + 1) * m_sampleRate / m_wSize;
138 std::vector<std::vector<float>> cf(m_wSize / 2, std::vector<float>(m_cfArray.size()));
139 for (
int i = 0; i < m_wSize / 2; i++)
141 for (
int j = 0; j < m_cfArray.size(); j++)
143 cf[i][j] = m_cfArray[j];
147 std::vector<std::vector<float>> repeated_bb(m_wSize / 2, std::vector<float>(bb.size()));
148 for (
int i = 0; i < m_wSize / 2; ++i)
155 size_t rows = fSupport.size();
156 size_t cols = cf[0].size();
157 m_wfunct.resize(rows, std::vector<double>(cols));
159 for (
size_t i = 0; i < rows; ++i)
161 for (
size_t j = 0; j < cols; ++j)
163 double term = std::pow((1.0 / (startSamplesSize * (fSupport[i][j] - cf[i][j]) + repeated_bb[i][j])), 4.0);
164 m_wfunct[i][j] = std::abs(std::pow(term, 2.0));
169 std::vector<double> adjustweight(m_cfArray.size());
170 for (
size_t j = 0; j < m_wfunct[0].size(); ++j)
172 double sum_wfunct = 0.0;
173 for (
size_t i = 0; i < m_wfunct.size(); ++i)
175 sum_wfunct += m_wfunct[i][j];
178 adjustweight[j] = cferb(
static_cast<double>(m_cfArray[j])) / sum_wfunct;
185 size_t adjustweight_size = adjustweight.size();
186 for (
size_t i = 0; i < m_wfunct.size(); ++i)
188 for (
size_t j = 0; j < m_wfunct[0].size(); ++j)
190 m_wfunct[i][j] *= adjustweight[j % adjustweight_size];
196 for (
const auto& row : m_wfunct)
198 auto maxElement = std::max_element(row.begin(), row.end());
199 if (maxElement != row.end() && *maxElement > maxVal)
201 maxVal = *maxElement;
206 for (
auto& row : m_wfunct)
208 std::transform(row.begin(), row.end(), row.begin(), [maxVal](
double val) { return val / maxVal; });
296 const std::vector<std::vector<float>>& inFrames)
298 size_t numRows = inFrames.size();
299 size_t numCols = inFrames[0].size();
300 size_t fftSize = numRows;
302 std::vector<std::vector<float>> powerSpectrum(numRows, std::vector<float>(numCols));
305 int fftOrder =
static_cast<int>(log2(fftSize));
306 dsp::FFT fft(fftOrder);
307 m_fftSize =
static_cast<int>(fftSize);
310 std::vector<float> inputBuffer(2 * fftSize, 0.0f);
312 for (
size_t col = 0; col < numCols; ++col)
315 for (
size_t row = 0; row < numRows; ++row)
317 inputBuffer[row] = inFrames[row][col];
321 fft.performFrequencyOnlyForwardTransform(inputBuffer.data());
324 for (
size_t row = 0; row < numRows; ++row)
326 float magnitudeSquared = std::norm(inputBuffer[row]);
327 powerSpectrum[row][col] = magnitudeSquared;
331 std::fill(inputBuffer.begin(), inputBuffer.end(), 0.0f);
334 return powerSpectrum;
339 auto numOfFrames = stftMatrix.size();
341 auto imageWidth = image.getWidth();
342 auto imageHeight = image.getHeight();
344 jassert(imageWidth > 0 && imageHeight > 0);
346 float factor = (
static_cast<float>(numOfFrames)) / (
static_cast<float>(imageWidth));
348 for (
int x = 0; x < imageWidth; x++)
350 int frameIndex =
static_cast<int>(factor *
static_cast<float>(x));
352 jassert(frameIndex <= numOfFrames);
354 for (
auto y = 1; y < imageHeight; ++y)
356 auto maxLevel = juce::FloatVectorOperations::findMinAndMax(stftMatrix.at(frameIndex).data(), m_fftSize);
359 auto skewedProportionY = 1.0f - std::exp(std::log((
float)y / (
float)imageHeight) * m_scalingConstant);
361 auto fftDataIndex = (size_t)juce::jlimit(
364 (
int)(skewedProportionY * m_fftSize));
367 auto level = juce::jmap( stftMatrix.at(frameIndex).at(fftDataIndex),
369 juce::jmax(maxLevel.getEnd(), 1e-5f),
373 image.setPixelAt(x, y, juce::Colour::fromHSV(level, 1.0f, level, 1.0f));
390 std::vector<float> hzVector(erbsVector.size());
392 std::transform(erbsVector.begin(), erbsVector.end(), hzVector.begin(),
393 [](
float hz) { return std::pow(2.0f, (hz / 6.44f) + 7.84f) - 229.0f; });