Chris@1068: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@1068: Chris@1068: /* Chris@1068: Sonic Visualiser Chris@1068: An audio file viewer and annotation editor. Chris@1068: Centre for Digital Music, Queen Mary, University of London. Chris@1068: This file copyright 2006-2016 Chris Cannam and QMUL. Chris@1068: Chris@1068: This program is free software; you can redistribute it and/or Chris@1068: modify it under the terms of the GNU General Public License as Chris@1068: published by the Free Software Foundation; either version 2 of the Chris@1068: License, or (at your option) any later version. See the file Chris@1068: COPYING included with this distribution for more information. Chris@1068: */ Chris@1068: Chris@1068: #include "ColourScale.h" Chris@1068: Chris@1068: #include "base/AudioLevel.h" Chris@1068: #include "base/LogRange.h" Chris@1068: Chris@1068: #include Chris@1068: Chris@1068: int ColourScale::m_maxPixel = 255; Chris@1068: Chris@1068: ColourScale::ColourScale(int colourMap, Chris@1068: Scale scale, Chris@1068: double minValue, Chris@1068: double maxValue, Chris@1068: double threshold, Chris@1068: double gain) : Chris@1068: m_mapper(colourMap, 1.f, double(m_maxPixel)), Chris@1068: m_scale(scale), Chris@1068: m_min(minValue), Chris@1068: m_max(maxValue), Chris@1068: m_threshold(threshold), Chris@1068: m_gain(gain) Chris@1068: { Chris@1068: if (minValue >= maxValue) { Chris@1068: throw std::logic_error("maxValue must be greater than minValue"); Chris@1068: } Chris@1068: Chris@1068: m_mappedMin = m_min; Chris@1068: m_mappedMax = m_max; Chris@1068: Chris@1068: if (m_scale == LogColourScale) { Chris@1068: Chris@1068: LogRange::mapRange(m_mappedMin, m_mappedMax); Chris@1068: Chris@1068: } else if (m_scale == PlusMinusOneScale) { Chris@1068: Chris@1068: m_mappedMin = -1.0; Chris@1068: m_mappedMax = 1.0; Chris@1068: Chris@1068: } else if (m_scale == AbsoluteScale) { Chris@1068: Chris@1068: m_mappedMin = fabs(m_mappedMin); Chris@1068: m_mappedMax = fabs(m_mappedMax); Chris@1068: if (m_mappedMin >= m_mappedMax) { Chris@1068: std::swap(m_mappedMin, m_mappedMax); Chris@1068: } Chris@1068: } Chris@1068: Chris@1068: if (m_mappedMin >= m_mappedMax) { Chris@1068: throw std::logic_error("maxValue must be greater than minValue [after mapping]"); Chris@1068: } Chris@1068: } Chris@1068: Chris@1068: int Chris@1068: ColourScale::getPixel(double value) Chris@1068: { Chris@1068: double maxPixF = m_maxPixel; Chris@1068: Chris@1068: if (m_scale == PhaseColourScale) { Chris@1068: double half = (maxPixF - 1.f) / 2.f; Chris@1068: return 1 + int((value * half) / M_PI + half); Chris@1068: } Chris@1068: Chris@1068: value *= m_gain; Chris@1068: Chris@1068: if (value < m_threshold) return 0; Chris@1068: Chris@1068: double mapped = value; Chris@1068: Chris@1068: if (m_scale == LogColourScale) { Chris@1068: mapped = LogRange::map(value); Chris@1068: } else if (m_scale == PlusMinusOneScale) { Chris@1068: if (mapped < -1.f) mapped = -1.f; Chris@1068: if (mapped > 1.f) mapped = 1.f; Chris@1068: } else if (m_scale == AbsoluteScale) { Chris@1068: if (mapped < 0.f) mapped = -mapped; Chris@1068: } Chris@1068: Chris@1068: if (mapped < m_mappedMin) { Chris@1068: mapped = m_mappedMin; Chris@1068: } Chris@1068: if (mapped > m_mappedMax) { Chris@1068: mapped = m_mappedMax; Chris@1068: } Chris@1068: Chris@1068: double proportion = (mapped - m_mappedMin) / (m_mappedMax - m_mappedMin); Chris@1068: Chris@1068: int pixel = 0; Chris@1068: Chris@1068: if (m_scale == MeterColourScale) { Chris@1068: pixel = AudioLevel::multiplier_to_preview(proportion, m_maxPixel-1) + 1; Chris@1068: } else { Chris@1068: pixel = int(proportion * maxPixF) + 1; Chris@1068: } Chris@1068: Chris@1068: if (pixel > m_maxPixel) pixel = m_maxPixel; Chris@1068: if (pixel < 0) pixel = 0; Chris@1068: return pixel; Chris@1068: } Chris@1068: Chris@1068: QColor Chris@1068: ColourScale::getColourForPixel(int pixel, int rotation) Chris@1068: { Chris@1068: if (pixel < 0) { Chris@1068: pixel = 0; Chris@1068: } Chris@1068: if (pixel > m_maxPixel) { Chris@1068: pixel = m_maxPixel; Chris@1068: } Chris@1068: if (pixel == 0) { Chris@1068: if (m_mapper.hasLightBackground()) { Chris@1068: return Qt::white; Chris@1068: } else { Chris@1068: return Qt::black; Chris@1068: } Chris@1068: } else { Chris@1068: int target = int(pixel) + rotation; Chris@1068: while (target < 1) target += m_maxPixel; Chris@1068: while (target > m_maxPixel) target -= m_maxPixel; Chris@1068: return m_mapper.map(double(target)); Chris@1068: } Chris@1068: }