There seems is error:
class AnalyserComponent : public AudioAppComponent, private Timer, public AudioProcessor
{
public:
AnalyserComponent()
: forwardFFT (fftOrder),
window (fftSize, dsp::WindowingFunction<float>::hann)
{
setOpaque (true);
setAudioChannels (2, 2); // we want a couple of input channels but no outputs
startTimerHz (30);
setSize (700, 500);
}
~AnalyserComponent() override
{
shutdownAudio();
}
//==============================================================================
void prepareToPlay (int, double) override {}
void releaseResources() override {}
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
{
if (bufferToFill.buffer->getNumChannels() > 0)
{
auto* channelData = bufferToFill.buffer->getReadPointer (0, bufferToFill.startSample);
for (auto i = 0; i < bufferToFill.numSamples; ++i)
pushNextSampleIntoFifo (channelData[i]);
}
}
//==============================================================================
void paint (Graphics& g) override
{
g.fillAll (Colours::black);
g.setOpacity (1.0f);
g.setColour (Colours::white);
drawFrame (g);
drawCoordiante(g);
}
void timerCallback() override
{
if (nextFFTBlockReady)
{
drawNextFrameOfSpectrum();
nextFFTBlockReady = false;
repaint();
}
}
void drawCoordiante(Graphics& g)
{
auto area = getLocalBounds();
g.setFont(12.0f);
g.setColour(Colours::gold);
g.drawRoundedRectangle(area.toFloat(), 5, 5);
for (int i = 0; i < 5; ++i)
{
auto freq = getFrequencyForPosition(i);
g.setColour(Colours::silver.withAlpha(0.3f));
auto x = area.getX() + area.getWidth() * freq;
g.drawVerticalLine(roundToInt(x), area.getY(), area.getBottom());
g.setColour(Colours::red);
g.drawFittedText((target_frequency[i]< 1000.0f) ? String(target_frequency[i]) + " Hz" : String(target_frequency[i] / 1000, 1) + " kHz",
roundToInt(x + 3), area.getBottom() - 18, 50, 15, Justification::left, 1);
}
g.setColour(Colours::silver.withAlpha(0.3f));
g.drawHorizontalLine(roundToInt(area.getY() + 0.2 * area.getHeight()), area.getX(), area.getRight());
g.drawHorizontalLine(roundToInt(area.getY() + 0.4 * area.getHeight()), area.getX(), area.getRight());
g.drawHorizontalLine(roundToInt(area.getY() + 0.6 * area.getHeight()), area.getX(), area.getRight());
g.drawHorizontalLine(roundToInt(area.getY() + 0.8 * area.getHeight()), area.getX(), area.getRight());
g.setColour(Colours::red);
g.drawFittedText(" 0 dB", area.getX() + 3, area.getY() + 2, 50, 14, Justification::left, 1);
g.drawFittedText(" -20 dB", area.getX() + 3, roundToInt(area.getY() + 0.2 * area.getHeight()), 50, 14, Justification::left, 1);
g.drawFittedText(" -40 dB", area.getX() + 3, roundToInt(area.getY() + 0.4 * area.getHeight()), 50, 14, Justification::left, 1);
g.drawFittedText(" -60 dB", area.getX() + 3, roundToInt(area.getY() + 0.6 * area.getHeight()), 50, 14, Justification::left, 1);
g.drawFittedText(" -80 dB", area.getX() + 3, roundToInt(area.getY() + 0.8 * area.getHeight()), 50, 14, Justification::left, 1);
//g.drawFittedText(" -100 dB", area.getX() + 3, roundToInt(area.getY() - 14.0 + area.getHeight()), 50, 14, Justification::left, 1);
}
//===============================================
float getFrequencyForPosition(int pos)
{
float SampleRate = getSampleRate();
float target_fre = target_frequency[pos];
float skewedProportionX = target_fre / SampleRate;
return skewedProportionX = 1.0f - std::pow(1.0- skewedProportionX,5.0);
}
//===============================================
void pushNextSampleIntoFifo (float sample) noexcept
{
// if the fifo contains enough data, set a flag to say
// that the next frame should now be rendered..
if (fifoIndex == fftSize)
{
if (! nextFFTBlockReady)
{
zeromem (fftData, sizeof (fftData));
memcpy (fftData, fifo, sizeof (fifo));
nextFFTBlockReady = true;
}
fifoIndex = 0;
}
fifo[fifoIndex++] = sample;
}
void drawNextFrameOfSpectrum()
{
// first apply a windowing function to our data
window.multiplyWithWindowingTable (fftData, fftSize);
// then render our FFT data..
forwardFFT.performFrequencyOnlyForwardTransform (fftData);
auto mindB = -100.0f;
auto maxdB = 0.0f;
for (int i = 0; i < scopeSize; ++i)
{
auto skewedProportionX = 1.0f - std::exp (std::log (1.0f - i / (float) scopeSize) * 0.2f);
auto fftDataIndex = jlimit (0, fftSize / 2, (int) (skewedProportionX * fftSize / 2));
auto level = jmap (jlimit (mindB, maxdB, Decibels::gainToDecibels (fftData[fftDataIndex])
- Decibels::gainToDecibels ((float) fftSize)),
mindB, maxdB, 0.0f, 1.0f);
scopeData[i] = level;
}
}
void drawFrame (Graphics& g)
{
for (int i = 1; i < scopeSize; ++i)
{
auto width = getLocalBounds().getWidth();
auto height = getLocalBounds().getHeight();
g.drawLine ({ (float) jmap (i - 1, 0, scopeSize - 1, 0, width),
jmap (scopeData[i - 1], 0.0f, 1.0f, (float) height, 0.0f),
(float) jmap (i, 0, scopeSize - 1, 0, width),
jmap (scopeData[i], 0.0f, 1.0f, (float) height, 0.0f) });
}
}
enum
{
fftOrder = 11,
fftSize = 1 << fftOrder,
scopeSize = 512
};
//=================
const String getName() override
{
}
void prepareToPlay(double sampleRate, int maximumExpectedSamplesPerBlock)override
{
}
//void releaseResources()override
//{
//}
void processBlock(AudioBuffer< float >& buffer, MidiBuffer& midiMessages)override
{
}
double getTailLengthSeconds() const override
{
}
bool acceptsMidi() const override
{
}
bool producesMidi() const override
{
}
AudioProcessorEditor* createEditor()override
{
}
bool hasEditor() const override
{
}
int getNumPrograms()override
{
}
int getCurrentProgram()override
{
}
void setCurrentProgram(int index) override
{
}
const String getProgramName(int index)override
{
}
void changeProgramName(int index, const String& newName)override
{
}
void getStateInformation(juce::MemoryBlock& destData)override
{
}
//================
private:
dsp::FFT forwardFFT;
dsp::WindowingFunction<float> window;
float fifo [fftSize];
float fftData [2 * fftSize];
int fifoIndex = 0;
bool nextFFTBlockReady = false;
float scopeData [scopeSize];
float target_frequency[5] = {100.0f, 500.0f, 1000.0f, 5000.0f, 10000.0f};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnalyserComponent)
};