|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2017 - ROLI Ltd.
-
- JUCE is an open source library subject to commercial or open-source
- licensing.
-
- By using JUCE, you agree to the terms of both the JUCE 5 End-User License
- Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
- 27th April 2017).
-
- End User License Agreement: www.juce.com/juce-5-licence
- Privacy Policy: www.juce.com/juce-5-privacy-policy
-
- Or: You may also use this code under the terms of the GPL v3 (see
- www.gnu.org/licenses).
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- namespace juce
- {
-
- struct AudioVisualiserComponent::ChannelInfo
- {
- ChannelInfo (AudioVisualiserComponent& o, int bufferSize)
- : owner (o), nextSample (0), subSample (0)
- {
- setBufferSize (bufferSize);
- clear();
- }
-
- void clear() noexcept
- {
- for (int i = 0; i < levels.size(); ++i)
- levels.getReference(i) = Range<float>();
-
- value = Range<float>();
- subSample = 0;
- }
-
- void pushSamples (const float* inputSamples, const int num) noexcept
- {
- for (int i = 0; i < num; ++i)
- pushSample (inputSamples[i]);
- }
-
- void pushSample (const float newSample) noexcept
- {
- if (--subSample <= 0)
- {
- nextSample %= levels.size();
- levels.getReference (nextSample++) = value;
- subSample = owner.getSamplesPerBlock();
- value = Range<float> (newSample, newSample);
- }
- else
- {
- value = value.getUnionWith (newSample);
- }
- }
-
- void setBufferSize (int newSize)
- {
- levels.removeRange (newSize, levels.size());
- levels.insertMultiple (-1, Range<float>(), newSize - levels.size());
-
- if (nextSample >= newSize)
- nextSample = 0;
- }
-
- AudioVisualiserComponent& owner;
- Array<Range<float>> levels;
- Range<float> value;
- int nextSample, subSample;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChannelInfo)
- };
-
- //==============================================================================
- AudioVisualiserComponent::AudioVisualiserComponent (const int initialNumChannels)
- : numSamples (1024),
- inputSamplesPerBlock (256),
- backgroundColour (Colours::black),
- waveformColour (Colours::white)
- {
- setOpaque (true);
- setNumChannels (initialNumChannels);
- setRepaintRate (60);
- }
-
- AudioVisualiserComponent::~AudioVisualiserComponent()
- {
- }
-
- void AudioVisualiserComponent::setNumChannels (const int numChannels)
- {
- channels.clear();
-
- for (int i = 0; i < numChannels; ++i)
- channels.add (new ChannelInfo (*this, numSamples));
- }
-
- void AudioVisualiserComponent::setBufferSize (int newNumSamples)
- {
- numSamples = newNumSamples;
-
- for (int i = 0; i < channels.size(); ++i)
- channels.getUnchecked(i)->setBufferSize (newNumSamples);
- }
-
- void AudioVisualiserComponent::clear()
- {
- for (int i = 0; i < channels.size(); ++i)
- channels.getUnchecked(i)->clear();
- }
-
- void AudioVisualiserComponent::pushBuffer (const float** d, int numChannels, int num)
- {
- numChannels = jmin (numChannels, channels.size());
-
- for (int i = 0; i < numChannels; ++i)
- channels.getUnchecked(i)->pushSamples (d[i], num);
- }
-
- void AudioVisualiserComponent::pushBuffer (const AudioBuffer<float>& buffer)
- {
- pushBuffer (buffer.getArrayOfReadPointers(),
- buffer.getNumChannels(),
- buffer.getNumSamples());
- }
-
- void AudioVisualiserComponent::pushBuffer (const AudioSourceChannelInfo& buffer)
- {
- const int numChannels = jmin (buffer.buffer->getNumChannels(), channels.size());
-
- for (int i = 0; i < numChannels; ++i)
- channels.getUnchecked(i)->pushSamples (buffer.buffer->getReadPointer (i, buffer.startSample),
- buffer.numSamples);
- }
-
- void AudioVisualiserComponent::pushSample (const float* d, int numChannels)
- {
- numChannels = jmin (numChannels, channels.size());
-
- for (int i = 0; i < numChannels; ++i)
- channels.getUnchecked(i)->pushSample (d[i]);
- }
-
- void AudioVisualiserComponent::setSamplesPerBlock (int newSamplesPerPixel) noexcept
- {
- inputSamplesPerBlock = newSamplesPerPixel;
- }
-
- void AudioVisualiserComponent::setRepaintRate (int frequencyInHz)
- {
- startTimerHz (frequencyInHz);
- }
-
- void AudioVisualiserComponent::timerCallback()
- {
- repaint();
- }
-
- void AudioVisualiserComponent::setColours (Colour bk, Colour fg) noexcept
- {
- backgroundColour = bk;
- waveformColour = fg;
- repaint();
- }
-
- void AudioVisualiserComponent::paint (Graphics& g)
- {
- g.fillAll (backgroundColour);
-
- Rectangle<float> r (getLocalBounds().toFloat());
- const float channelHeight = r.getHeight() / channels.size();
-
- g.setColour (waveformColour);
-
- for (int i = 0; i < channels.size(); ++i)
- {
- const ChannelInfo& c = *channels.getUnchecked(i);
-
- paintChannel (g, r.removeFromTop (channelHeight),
- c.levels.begin(), c.levels.size(), c.nextSample);
- }
- }
-
- void AudioVisualiserComponent::getChannelAsPath (Path& path, const Range<float>* levels, int numLevels, int nextSample)
- {
- path.preallocateSpace (4 * numLevels + 8);
-
- for (int i = 0; i < numLevels; ++i)
- {
- const float level = -(levels[(nextSample + i) % numLevels].getEnd());
-
- if (i == 0)
- path.startNewSubPath (0.0f, level);
- else
- path.lineTo ((float) i, level);
- }
-
- for (int i = numLevels; --i >= 0;)
- path.lineTo ((float) i, -(levels[(nextSample + i) % numLevels].getStart()));
-
- path.closeSubPath();
- }
-
- void AudioVisualiserComponent::paintChannel (Graphics& g, Rectangle<float> area,
- const Range<float>* levels, int numLevels, int nextSample)
- {
- Path p;
- getChannelAsPath (p, levels, numLevels, nextSample);
-
- g.fillPath (p, AffineTransform::fromTargetPoints (0.0f, -1.0f, area.getX(), area.getY(),
- 0.0f, 1.0f, area.getX(), area.getBottom(),
- (float) numLevels, -1.0f, area.getRight(), area.getY()));
- }
-
- } // namespace juce
|