Chris@189: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@189: 
Chris@189: /*
Chris@189:     Sonic Visualiser
Chris@189:     An audio file viewer and annotation editor.
Chris@189:     Centre for Digital Music, Queen Mary, University of London.
Chris@202:     This file copyright 2006 QMUL.
Chris@189:     
Chris@189:     This program is free software; you can redistribute it and/or
Chris@189:     modify it under the terms of the GNU General Public License as
Chris@189:     published by the Free Software Foundation; either version 2 of the
Chris@189:     License, or (at your option) any later version.  See the file
Chris@189:     COPYING included with this distribution for more information.
Chris@189: */
Chris@189: 
Chris@189: #include "RangeMapper.h"
Chris@189: 
Chris@189: #include <cassert>
Chris@189: #include <cmath>
Chris@189: 
Chris@189: #include <iostream>
Chris@189: 
Chris@189: LinearRangeMapper::LinearRangeMapper(int minpos, int maxpos,
Chris@189: 				     float minval, float maxval,
Chris@464:                                      QString unit, bool inverted) :
Chris@189:     m_minpos(minpos),
Chris@189:     m_maxpos(maxpos),
Chris@189:     m_minval(minval),
Chris@189:     m_maxval(maxval),
Chris@464:     m_unit(unit),
Chris@464:     m_inverted(inverted)
Chris@189: {
Chris@189:     assert(m_maxval != m_minval);
Chris@189:     assert(m_maxpos != m_minpos);
Chris@189: }
Chris@189: 
Chris@189: int
Chris@189: LinearRangeMapper::getPositionForValue(float value) const
Chris@189: {
Chris@190:     int position = m_minpos +
Chris@190:         lrintf(((value - m_minval) / (m_maxval - m_minval))
Chris@190:                * (m_maxpos - m_minpos));
Chris@189:     if (position < m_minpos) position = m_minpos;
Chris@189:     if (position > m_maxpos) position = m_maxpos;
Chris@241: //    std::cerr << "LinearRangeMapper::getPositionForValue: " << value << " -> "
Chris@241: //              << position << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", minval " << m_minval << ", maxval " << m_maxval << ")" << std::endl;
Chris@464:     if (m_inverted) return m_maxpos - position;
Chris@464:     else return position;
Chris@189: }
Chris@189: 
Chris@189: float
Chris@189: LinearRangeMapper::getValueForPosition(int position) const
Chris@189: {
Chris@464:     if (m_inverted) position = m_maxpos - position;
Chris@190:     float value = m_minval +
Chris@190:         ((float(position - m_minpos) / float(m_maxpos - m_minpos))
Chris@190:          * (m_maxval - m_minval));
Chris@189:     if (value < m_minval) value = m_minval;
Chris@189:     if (value > m_maxval) value = m_maxval;
Chris@241: //    std::cerr << "LinearRangeMapper::getValueForPosition: " << position << " -> "
Chris@241: //              << value << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", minval " << m_minval << ", maxval " << m_maxval << ")" << std::endl;
Chris@189:     return value;
Chris@189: }
Chris@189: 
Chris@189: LogRangeMapper::LogRangeMapper(int minpos, int maxpos,
Chris@356:                                float minval, float maxval,
Chris@464:                                QString unit, bool inverted) :
Chris@189:     m_minpos(minpos),
Chris@189:     m_maxpos(maxpos),
Chris@464:     m_unit(unit),
Chris@464:     m_inverted(inverted)
Chris@189: {
Chris@356:     convertMinMax(minpos, maxpos, minval, maxval, m_minlog, m_ratio);
Chris@356: 
Chris@356:     std::cerr << "LogRangeMapper: minpos " << minpos << ", maxpos "
Chris@356:               << maxpos << ", minval " << minval << ", maxval "
Chris@356:               << maxval << ", minlog " << m_minlog << ", ratio " << m_ratio
Chris@356:               << ", unit " << unit.toStdString() << std::endl;
Chris@356: 
Chris@189:     assert(m_maxpos != m_minpos);
Chris@189: 
Chris@189:     m_maxlog = (m_maxpos - m_minpos) / m_ratio + m_minlog;
Chris@189: }
Chris@189: 
Chris@356: void
Chris@356: LogRangeMapper::convertMinMax(int minpos, int maxpos,
Chris@356:                               float minval, float maxval,
Chris@356:                               float &minlog, float &ratio)
Chris@356: {
Chris@356:     static float thresh = powf(10, -10);
Chris@356:     if (minval < thresh) minval = thresh;
Chris@356:     minlog = log10f(minval);
Chris@356:     ratio = (maxpos - minpos) / (log10f(maxval) - minlog);
Chris@356: }
Chris@356: 
Chris@356: void
Chris@356: LogRangeMapper::convertRatioMinLog(float ratio, float minlog,
Chris@356:                                    int minpos, int maxpos,
Chris@356:                                    float &minval, float &maxval)
Chris@356: {
Chris@356:     minval = powf(10, minlog);
Chris@356:     maxval = powf(10, (maxpos - minpos) / ratio + minlog);
Chris@356: }
Chris@356: 
Chris@189: int
Chris@189: LogRangeMapper::getPositionForValue(float value) const
Chris@189: {
Chris@341:     int position = (log10(value) - m_minlog) * m_ratio + m_minpos;
Chris@189:     if (position < m_minpos) position = m_minpos;
Chris@189:     if (position > m_maxpos) position = m_maxpos;
Chris@464: //    std::cerr << "LogRangeMapper::getPositionForValue: " << value << " -> "
Chris@464: //              << position << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", ratio " << m_ratio << ", minlog " << m_minlog << ")" << std::endl;
Chris@464:     if (m_inverted) return m_maxpos - position;
Chris@464:     else return position;
Chris@189: }
Chris@189: 
Chris@189: float
Chris@189: LogRangeMapper::getValueForPosition(int position) const
Chris@189: {
Chris@464:     if (m_inverted) position = m_maxpos - position;
Chris@189:     float value = powf(10, (position - m_minpos) / m_ratio + m_minlog);
Chris@464: //    std::cerr << "LogRangeMapper::getValueForPosition: " << position << " -> "
Chris@464: //              << value << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", ratio " << m_ratio << ", minlog " << m_minlog << ")" << std::endl;
Chris@189:     return value;
Chris@189: }
Chris@189: