comparison layer/ColourScale.cpp @ 1146:74f2706995b7 3.0-integration

Merge work on unified spectrogram and colour 3d plot caching renderer
author Chris Cannam
date Fri, 05 Aug 2016 15:05:02 +0100
parents c53ed1a6fcbd
children 822edd9bb665
comparison
equal deleted inserted replaced
1056:b4fd6c67fce5 1146:74f2706995b7
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006-2016 Chris Cannam and QMUL.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "ColourScale.h"
17
18 #include "base/AudioLevel.h"
19 #include "base/LogRange.h"
20
21 #include <cmath>
22 #include <iostream>
23
24 using namespace std;
25
26 int ColourScale::m_maxPixel = 255;
27
28 ColourScale::ColourScale(Parameters parameters) :
29 m_params(parameters),
30 m_mapper(m_params.colourMap, 1.f, double(m_maxPixel))
31 {
32 if (m_params.minValue >= m_params.maxValue) {
33 cerr << "ERROR: ColourScale::ColourScale: minValue = "
34 << m_params.minValue << ", maxValue = " << m_params.maxValue << endl;
35 throw std::logic_error("maxValue must be greater than minValue");
36 }
37
38 m_mappedMin = m_params.minValue;
39 m_mappedMax = m_params.maxValue;
40
41 if (m_mappedMin < m_params.threshold) {
42 m_mappedMin = m_params.threshold;
43 }
44
45 if (m_params.scaleType == ColourScaleType::Log) {
46
47 LogRange::mapRange(m_mappedMin, m_mappedMax);
48
49 } else if (m_params.scaleType == ColourScaleType::PlusMinusOne) {
50
51 m_mappedMin = -1.0;
52 m_mappedMax = 1.0;
53
54 } else if (m_params.scaleType == ColourScaleType::Absolute) {
55
56 m_mappedMin = fabs(m_mappedMin);
57 m_mappedMax = fabs(m_mappedMax);
58 if (m_mappedMin >= m_mappedMax) {
59 std::swap(m_mappedMin, m_mappedMax);
60 }
61 }
62
63 if (m_mappedMin >= m_mappedMax) {
64 cerr << "ERROR: ColourScale::ColourScale: minValue = " << m_params.minValue
65 << ", maxValue = " << m_params.maxValue
66 << ", threshold = " << m_params.threshold
67 << ", scale = " << int(m_params.scaleType)
68 << " resulting in mapped minValue = " << m_mappedMin
69 << ", mapped maxValue = " << m_mappedMax << endl;
70 throw std::logic_error("maxValue must be greater than minValue [after mapping]");
71 }
72 }
73
74 ColourScale::~ColourScale()
75 {
76 }
77
78 ColourScaleType
79 ColourScale::getScale() const
80 {
81 return m_params.scaleType;
82 }
83
84 int
85 ColourScale::getPixel(double value) const
86 {
87 double maxPixF = m_maxPixel;
88
89 if (m_params.scaleType == ColourScaleType::Phase) {
90 double half = (maxPixF - 1.f) / 2.f;
91 int pixel = 1 + int((value * half) / M_PI + half);
92 // cerr << "phase = " << value << " pixel = " << pixel << endl;
93 return pixel;
94 }
95
96 value *= m_params.gain;
97
98 if (value < m_params.threshold) return 0;
99
100 double mapped = value;
101
102 if (m_params.scaleType == ColourScaleType::Log) {
103 mapped = LogRange::map(value);
104 } else if (m_params.scaleType == ColourScaleType::PlusMinusOne) {
105 if (mapped < -1.f) mapped = -1.f;
106 if (mapped > 1.f) mapped = 1.f;
107 } else if (m_params.scaleType == ColourScaleType::Absolute) {
108 if (mapped < 0.f) mapped = -mapped;
109 }
110
111 mapped *= m_params.multiple;
112
113 if (mapped < m_mappedMin) {
114 mapped = m_mappedMin;
115 }
116 if (mapped > m_mappedMax) {
117 mapped = m_mappedMax;
118 }
119
120 double proportion = (mapped - m_mappedMin) / (m_mappedMax - m_mappedMin);
121
122 int pixel = 0;
123
124 if (m_params.scaleType == ColourScaleType::Meter) {
125 pixel = AudioLevel::multiplier_to_preview(proportion, m_maxPixel-1) + 1;
126 } else {
127 pixel = int(proportion * maxPixF) + 1;
128 }
129
130 if (pixel < 0) {
131 pixel = 0;
132 }
133 if (pixel > m_maxPixel) {
134 pixel = m_maxPixel;
135 }
136 return pixel;
137 }
138
139 QColor
140 ColourScale::getColourForPixel(int pixel, int rotation) const
141 {
142 if (pixel < 0) {
143 pixel = 0;
144 }
145 if (pixel > m_maxPixel) {
146 pixel = m_maxPixel;
147 }
148 if (pixel == 0) {
149 if (m_mapper.hasLightBackground()) {
150 return Qt::white;
151 } else {
152 return Qt::black;
153 }
154 } else {
155 int target = int(pixel) + rotation;
156 while (target < 1) target += m_maxPixel;
157 while (target > m_maxPixel) target -= m_maxPixel;
158 return m_mapper.map(double(target));
159 }
160 }