mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-02 08:39:46 +02:00
OpenMP TrackArtist::DrawSpectrum (#165)
- make 2nd loop parallelizable - remove number scale from both loops, only calculate one time - initialize Acolor::GetColorGradient separately
This commit is contained in:
parent
b17a14ccc2
commit
8e1b084f01
@ -148,10 +148,9 @@ class AColor {
|
|||||||
inline void GetColorGradient(float value,
|
inline void GetColorGradient(float value,
|
||||||
AColor::ColorGradientChoice selected,
|
AColor::ColorGradientChoice selected,
|
||||||
bool grayscale,
|
bool grayscale,
|
||||||
unsigned char *red,
|
unsigned char * __restrict red,
|
||||||
unsigned char *green, unsigned char *blue) {
|
unsigned char * __restrict green,
|
||||||
if (!AColor::gradient_inited)
|
unsigned char * __restrict blue) {
|
||||||
AColor::PreComputeGradient();
|
|
||||||
|
|
||||||
int idx = value * (AColor::gradientSteps - 1);
|
int idx = value * (AColor::gradientSteps - 1);
|
||||||
|
|
||||||
|
@ -151,6 +151,10 @@ audio tracks.
|
|||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
#ifdef HAVE_ALLOCA_H
|
||||||
|
#include <alloca.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <wx/brush.h>
|
#include <wx/brush.h>
|
||||||
#include <wx/colour.h>
|
#include <wx/colour.h>
|
||||||
#include <wx/dc.h>
|
#include <wx/dc.h>
|
||||||
@ -182,7 +186,6 @@ audio tracks.
|
|||||||
#include "widgets/Ruler.h"
|
#include "widgets/Ruler.h"
|
||||||
#include "Theme.h"
|
#include "Theme.h"
|
||||||
#include "AllThemeResources.h"
|
#include "AllThemeResources.h"
|
||||||
|
|
||||||
#include "Experimental.h"
|
#include "Experimental.h"
|
||||||
|
|
||||||
#undef PROFILE_WAVEFORM
|
#undef PROFILE_WAVEFORM
|
||||||
@ -2002,7 +2005,6 @@ void TrackArtist::DrawTimeSlider(wxDC & dc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TrackArtist::DrawSpectrum(const WaveTrack *track,
|
void TrackArtist::DrawSpectrum(const WaveTrack *track,
|
||||||
wxDC & dc,
|
wxDC & dc,
|
||||||
const wxRect & rect,
|
const wxRect & rect,
|
||||||
@ -2126,8 +2128,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
|||||||
|
|
||||||
const double &t0 = params.t0;
|
const double &t0 = params.t0;
|
||||||
const double &tOffset = params.tOffset;
|
const double &tOffset = params.tOffset;
|
||||||
const auto ssel0 = params.ssel0;
|
const auto &ssel0 = params.ssel0;
|
||||||
const auto ssel1 = params.ssel1;
|
const auto &ssel1 = params.ssel1;
|
||||||
const double &averagePixelsPerSample = params.averagePixelsPerSample;
|
const double &averagePixelsPerSample = params.averagePixelsPerSample;
|
||||||
const double &rate = params.rate;
|
const double &rate = params.rate;
|
||||||
const double &hiddenLeftOffset = params.hiddenLeftOffset;
|
const double &hiddenLeftOffset = params.hiddenLeftOffset;
|
||||||
@ -2148,6 +2150,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
|||||||
const bool &isGrayscale = settings.isGrayscale;
|
const bool &isGrayscale = settings.isGrayscale;
|
||||||
const int &range = settings.range;
|
const int &range = settings.range;
|
||||||
const int &gain = settings.gain;
|
const int &gain = settings.gain;
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_FIND_NOTES
|
#ifdef EXPERIMENTAL_FIND_NOTES
|
||||||
const bool &fftFindNotes = settings.fftFindNotes;
|
const bool &fftFindNotes = settings.fftFindNotes;
|
||||||
const bool &findNotesMinA = settings.findNotesMinA;
|
const bool &findNotesMinA = settings.findNotesMinA;
|
||||||
@ -2186,7 +2189,22 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
|||||||
|
|
||||||
const SpectrogramSettings::ScaleType scaleType = settings.scaleType;
|
const SpectrogramSettings::ScaleType scaleType = settings.scaleType;
|
||||||
|
|
||||||
const NumberScale numberScale(settings.GetScale(minFreq, maxFreq, rate, true));
|
// nearest frequency to each pixel row from number scale, for selecting
|
||||||
|
// the desired fft bin(s) for display on that row
|
||||||
|
float *bins = (float*)alloca(sizeof(*bins)*(hiddenMid.height + 1));
|
||||||
|
{
|
||||||
|
const NumberScale numberScale(settings.GetScale(minFreq, maxFreq, rate, true));
|
||||||
|
|
||||||
|
NumberScale::Iterator it = numberScale.begin(mid.height);
|
||||||
|
float nextBin = std::max(0.0f, std::min(float(half - 1), *it));
|
||||||
|
|
||||||
|
int yy;
|
||||||
|
for (yy = 0; yy < hiddenMid.height; ++yy) {
|
||||||
|
bins[yy] = nextBin;
|
||||||
|
nextBin = std::max(0.0f, std::min(float(half - 1), *++it));
|
||||||
|
}
|
||||||
|
bins[yy] = nextBin;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_FFT_Y_GRID
|
#ifdef EXPERIMENTAL_FFT_Y_GRID
|
||||||
const float
|
const float
|
||||||
@ -2266,12 +2284,13 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
|||||||
int *indexes = new int[maxTableSize];
|
int *indexes = new int[maxTableSize];
|
||||||
#endif //EXPERIMENTAL_FIND_NOTES
|
#endif //EXPERIMENTAL_FIND_NOTES
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for
|
||||||
|
#endif
|
||||||
for (int xx = 0; xx < hiddenMid.width; ++xx) {
|
for (int xx = 0; xx < hiddenMid.width; ++xx) {
|
||||||
NumberScale::Iterator it = numberScale.begin(mid.height);
|
|
||||||
float nextBin = std::max(0.0f, std::min(float(half - 1), *it));
|
|
||||||
for (int yy = 0; yy < hiddenMid.height; ++yy) {
|
for (int yy = 0; yy < hiddenMid.height; ++yy) {
|
||||||
const float bin = nextBin;
|
const float bin = bins[yy];
|
||||||
nextBin = std::max(0.0f, std::min(float(half - 1), *++it));
|
const float nextBin = bins[yy+1];
|
||||||
|
|
||||||
if (settings.scaleType != SpectrogramSettings::stLogarithmic) {
|
if (settings.scaleType != SpectrogramSettings::stLogarithmic) {
|
||||||
const float value = findValue
|
const float value = findValue
|
||||||
@ -2391,10 +2410,6 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
|||||||
float selBinCenter =
|
float selBinCenter =
|
||||||
((freqLo < 0 || freqHi < 0) ? -1 : sqrt(freqLo * freqHi)) / binUnit;
|
((freqLo < 0 || freqHi < 0) ? -1 : sqrt(freqLo * freqHi)) / binUnit;
|
||||||
|
|
||||||
sampleCount w1(0.5 + rate *
|
|
||||||
(zoomInfo.PositionToTime(0, -leftOffset) - tOffset)
|
|
||||||
);
|
|
||||||
|
|
||||||
const bool isSpectral = settings.SpectralSelectionEnabled();
|
const bool isSpectral = settings.SpectralSelectionEnabled();
|
||||||
const bool hidden = (ZoomInfo::HIDDEN == zoomInfo.GetFisheyeState());
|
const bool hidden = (ZoomInfo::HIDDEN == zoomInfo.GetFisheyeState());
|
||||||
const int begin = hidden
|
const int begin = hidden
|
||||||
@ -2423,38 +2438,62 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
int correctedX = leftOffset - hiddenLeftOffset;
|
// build color gradient tables (not thread safe)
|
||||||
int fisheyeColumn = 0;
|
if (!AColor::gradient_inited)
|
||||||
for (int xx = 0; xx < mid.width; ++xx, ++correctedX)
|
AColor::PreComputeGradient();
|
||||||
{
|
|
||||||
const bool inFisheye = zoomInfo.InFisheye(xx, -leftOffset);
|
|
||||||
float *const uncached =
|
|
||||||
inFisheye ? &specCache.freq[(fisheyeColumn++) * half] : 0;
|
|
||||||
|
|
||||||
auto w0 = w1;
|
// left pixel column of the fisheye
|
||||||
w1 = sampleCount(0.5 + rate *
|
int fisheyeLeft = zoomInfo.GetFisheyeLeftBoundary(-leftOffset);
|
||||||
(zoomInfo.PositionToTime(xx + 1, -leftOffset) - tOffset)
|
|
||||||
);
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for
|
||||||
|
#endif
|
||||||
|
for (int xx = 0; xx < mid.width; ++xx) {
|
||||||
|
|
||||||
|
int correctedX = xx + leftOffset - hiddenLeftOffset;
|
||||||
|
|
||||||
|
// in fisheye mode the time scale has changed, so the row values aren't cached
|
||||||
|
// in the loop above, and must be fetched from fft cache
|
||||||
|
float* uncached;
|
||||||
|
if (!zoomInfo.InFisheye(xx, -leftOffset)) {
|
||||||
|
uncached = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int specIndex = (xx - fisheyeLeft) * half;
|
||||||
|
wxASSERT(specIndex >= 0 && specIndex < specCache.freq.size());
|
||||||
|
uncached = &specCache.freq[specIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
// zoomInfo must be queried for each column since with fisheye enabled
|
||||||
|
// time between columns is variable
|
||||||
|
auto w0 = sampleCount(0.5 + rate *
|
||||||
|
(zoomInfo.PositionToTime(xx, -leftOffset) - tOffset));
|
||||||
|
|
||||||
|
auto w1 = sampleCount(0.5 + rate *
|
||||||
|
(zoomInfo.PositionToTime(xx+1, -leftOffset) - tOffset));
|
||||||
|
|
||||||
|
bool maybeSelected = ssel0 <= w0 && w1 < ssel1;
|
||||||
|
|
||||||
NumberScale::Iterator it = numberScale.begin(mid.height);
|
|
||||||
float nextBin = std::max(0.0f, std::min(float(half - 1), *it));
|
|
||||||
for (int yy = 0; yy < hiddenMid.height; ++yy) {
|
for (int yy = 0; yy < hiddenMid.height; ++yy) {
|
||||||
const float bin = nextBin;
|
const float bin = bins[yy];
|
||||||
nextBin = std::max(0.0f, std::min(float(half - 1), *++it));
|
const float nextBin = bins[yy+1];
|
||||||
|
|
||||||
// For spectral selection, determine what colour
|
// For spectral selection, determine what colour
|
||||||
// set to use. We use a darker selection if
|
// set to use. We use a darker selection if
|
||||||
// in both spectral range and time range.
|
// in both spectral range and time range.
|
||||||
|
|
||||||
AColor::ColorGradientChoice selected = AColor::ColorGradientUnselected;
|
AColor::ColorGradientChoice selected = AColor::ColorGradientUnselected;
|
||||||
|
|
||||||
// If we are in the time selected range, then we may use a different color set.
|
// If we are in the time selected range, then we may use a different color set.
|
||||||
if (ssel0 <= w0 && w1 < ssel1)
|
if (maybeSelected)
|
||||||
selected =
|
selected =
|
||||||
ChooseColorSet(bin, nextBin, selBinLo, selBinCenter, selBinHi,
|
ChooseColorSet(bin, nextBin, selBinLo, selBinCenter, selBinHi,
|
||||||
(xx + leftOffset - hiddenLeftOffset) / DASH_LENGTH, isSpectral);
|
(xx + leftOffset - hiddenLeftOffset) / DASH_LENGTH, isSpectral);
|
||||||
|
|
||||||
const float value = uncached
|
const float value = uncached
|
||||||
? findValue(uncached, bin, nextBin, half, autocorrelation, gain, range)
|
? findValue(uncached, bin, nextBin, half, autocorrelation, gain, range)
|
||||||
: clip->mSpecPxCache->values[correctedX * hiddenMid.height + yy];
|
: clip->mSpecPxCache->values[correctedX * hiddenMid.height + yy];
|
||||||
|
|
||||||
unsigned char rv, gv, bv;
|
unsigned char rv, gv, bv;
|
||||||
GetColorGradient(value, selected, isGrayscale, &rv, &gv, &bv);
|
GetColorGradient(value, selected, isGrayscale, &rv, &gv, &bv);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user