annotate layer/ColourScale.cpp @ 1069:0c4734cd33c1 spectrogram-minor-refactor

Add ColourScale
author Chris Cannam
date Thu, 23 Jun 2016 14:43:14 +0100
parents 521f7e8b0559
children 27163db978d8
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@1068 22
Chris@1068 23 int ColourScale::m_maxPixel = 255;
Chris@1068 24
Chris@1068 25 ColourScale::ColourScale(int colourMap,
Chris@1068 26 Scale scale,
Chris@1068 27 double minValue,
Chris@1068 28 double maxValue,
Chris@1068 29 double threshold,
Chris@1068 30 double gain) :
Chris@1068 31 m_mapper(colourMap, 1.f, double(m_maxPixel)),
Chris@1068 32 m_scale(scale),
Chris@1068 33 m_min(minValue),
Chris@1068 34 m_max(maxValue),
Chris@1068 35 m_threshold(threshold),
Chris@1068 36 m_gain(gain)
Chris@1068 37 {
Chris@1068 38 if (minValue >= maxValue) {
Chris@1068 39 throw std::logic_error("maxValue must be greater than minValue");
Chris@1068 40 }
Chris@1068 41
Chris@1068 42 m_mappedMin = m_min;
Chris@1068 43 m_mappedMax = m_max;
Chris@1068 44
Chris@1068 45 if (m_scale == LogColourScale) {
Chris@1068 46
Chris@1068 47 LogRange::mapRange(m_mappedMin, m_mappedMax);
Chris@1068 48
Chris@1068 49 } else if (m_scale == PlusMinusOneScale) {
Chris@1068 50
Chris@1068 51 m_mappedMin = -1.0;
Chris@1068 52 m_mappedMax = 1.0;
Chris@1068 53
Chris@1068 54 } else if (m_scale == AbsoluteScale) {
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@1068 64 throw std::logic_error("maxValue must be greater than minValue [after mapping]");
Chris@1068 65 }
Chris@1068 66 }
Chris@1068 67
Chris@1068 68 int
Chris@1068 69 ColourScale::getPixel(double value)
Chris@1068 70 {
Chris@1068 71 double maxPixF = m_maxPixel;
Chris@1068 72
Chris@1068 73 if (m_scale == PhaseColourScale) {
Chris@1068 74 double half = (maxPixF - 1.f) / 2.f;
Chris@1068 75 return 1 + int((value * half) / M_PI + half);
Chris@1068 76 }
Chris@1068 77
Chris@1068 78 value *= m_gain;
Chris@1068 79
Chris@1068 80 if (value < m_threshold) return 0;
Chris@1068 81
Chris@1068 82 double mapped = value;
Chris@1068 83
Chris@1068 84 if (m_scale == LogColourScale) {
Chris@1068 85 mapped = LogRange::map(value);
Chris@1068 86 } else if (m_scale == PlusMinusOneScale) {
Chris@1068 87 if (mapped < -1.f) mapped = -1.f;
Chris@1068 88 if (mapped > 1.f) mapped = 1.f;
Chris@1068 89 } else if (m_scale == AbsoluteScale) {
Chris@1068 90 if (mapped < 0.f) mapped = -mapped;
Chris@1068 91 }
Chris@1068 92
Chris@1068 93 if (mapped < m_mappedMin) {
Chris@1068 94 mapped = m_mappedMin;
Chris@1068 95 }
Chris@1068 96 if (mapped > m_mappedMax) {
Chris@1068 97 mapped = m_mappedMax;
Chris@1068 98 }
Chris@1068 99
Chris@1068 100 double proportion = (mapped - m_mappedMin) / (m_mappedMax - m_mappedMin);
Chris@1068 101
Chris@1068 102 int pixel = 0;
Chris@1068 103
Chris@1068 104 if (m_scale == MeterColourScale) {
Chris@1068 105 pixel = AudioLevel::multiplier_to_preview(proportion, m_maxPixel-1) + 1;
Chris@1068 106 } else {
Chris@1068 107 pixel = int(proportion * maxPixF) + 1;
Chris@1068 108 }
Chris@1068 109
Chris@1068 110 if (pixel > m_maxPixel) pixel = m_maxPixel;
Chris@1068 111 if (pixel < 0) pixel = 0;
Chris@1068 112 return pixel;
Chris@1068 113 }
Chris@1068 114
Chris@1068 115 QColor
Chris@1068 116 ColourScale::getColourForPixel(int pixel, int rotation)
Chris@1068 117 {
Chris@1068 118 if (pixel < 0) {
Chris@1068 119 pixel = 0;
Chris@1068 120 }
Chris@1068 121 if (pixel > m_maxPixel) {
Chris@1068 122 pixel = m_maxPixel;
Chris@1068 123 }
Chris@1068 124 if (pixel == 0) {
Chris@1068 125 if (m_mapper.hasLightBackground()) {
Chris@1068 126 return Qt::white;
Chris@1068 127 } else {
Chris@1068 128 return Qt::black;
Chris@1068 129 }
Chris@1068 130 } else {
Chris@1068 131 int target = int(pixel) + rotation;
Chris@1068 132 while (target < 1) target += m_maxPixel;
Chris@1068 133 while (target > m_maxPixel) target -= m_maxPixel;
Chris@1068 134 return m_mapper.map(double(target));
Chris@1068 135 }
Chris@1068 136 }