Hi all
I am working on my first project, a pitch tracker, and found a nice looking library to use: http://www.schmittmachine.com/dywapitchtrack.html
I have use the LiveScrollingAudioDisplay class from the Juce Demo as a starting point, to learn about live sampling of audio input. I managed to extract that class into a seperate project and get it working. However it is only a header file with definitions inside.. I'm not sure the reason for this.
I am having troubles getting the dywapitchtrack library working. When I use the 'dywapitch_computepitch' function I get a 'No matching function for call' error. However, I have included the header file, and can navigate to it by ctrl-click and 'Jump to definition'.
My code is below if anyone feels like having a look.
Thanks in advance!
#include "dywapitchtrack.h" //============================================================================== /* This component scrolls a continuous waveform showing the audio that's coming into whatever audio inputs this object is connected to. Copied from Juce demo. */ class LiveScrollingAudioDisplay : public Component, public AudioIODeviceCallback, public dywapitchtracker, private Timer { public: LiveScrollingAudioDisplay() : nextSample (0), subSample (0), accumulator (0) { setOpaque (true); clear(); startTimer (1000 / 75); // use a timer to keep repainting this component dywapitch_inittracking (&pitchtracker); } //============================================================================== void audioDeviceAboutToStart (AudioIODevice*) override { clear(); } void audioDeviceStopped() override { clear(); } void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels, float** outputChannelData, int numOutputChannels, int numSamples) override { for (int i = 0; i < numSamples; ++i) { float inputSample = 0; for (int chan = 0; chan < numInputChannels; ++chan) if (inputChannelData[chan] != nullptr) inputSample += std::abs (inputChannelData[chan][i]); // find the sum of all the channels <-- might not want to do this... psamples[i] = inputSample; pushSample (5.0f * inputSample); // boost the level to make it more easily visible. } // We need to clear the output buffers before returning, in case they're full of junk.. for (int j = 0; j < numOutputChannels; ++j) if (outputChannelData[j] != nullptr) zeromem (outputChannelData[j], sizeof (float) * (size_t) numSamples); } private: static const int bufferSize = 1024; float samples[bufferSize]; float psamples[bufferSize]; double currentPitch; int nextSample, subSample; float accumulator; dywapitchtracker pitchtracker; void clear() { zeromem (samples, sizeof (samples)); accumulator = 0; subSample = 0; } void paint (Graphics& g) override { g.fillAll (Colours::black); const float midY = getHeight() * 0.5f; int samplesAgo = (nextSample + numElementsInArray (samples) - 1); RectangleList<float> waveform; for (int x = jmin (getWidth(), (int) numElementsInArray (samples)); --x >= 0;) { const float sampleSize = midY * samples [samplesAgo-- % numElementsInArray (samples)]; waveform.addWithoutMerging (Rectangle<float> ((float) x, midY - sampleSize, 1.0f, sampleSize * 2.0f)); } currentPitch = dywapitch_computepitch(&pitchtracker, psamples, 0, 1024); g.drawText((String)currentPitch, 1, 1, 50, 15, Justification::topLeft, true); g.setColour (Colours::lightgreen); g.fillRectList (waveform); } void timerCallback() override { repaint(); } void pushSample (const float newSample) { accumulator += newSample; if (subSample == 0) { const int inputSamplesPerPixel = 200; samples[nextSample] = accumulator / inputSamplesPerPixel; nextSample = (nextSample + 1) % numElementsInArray (samples); subSample = inputSamplesPerPixel; accumulator = 0; } else { --subSample; } } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LiveScrollingAudioDisplay); };