annotate layer/ColourScale.cpp @ 1139:2976f57164ac spectrogram-minor-refactor

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