1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
|
/***************************************************************************
TrackPixmap.h - buffered pixmap for displaying a kwave track
-------------------
begin : Tue Mar 20 2001
copyright : (C) 2001 by Thomas Eschenbacher
email : Thomas.Eschenbacher@gmx.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef TRACK_PIXMAP_H
#define TRACK_PIXMAP_H
#include "config.h"
#include "libkwavegui_export.h"
#include <math.h>
#include <QtGlobal>
#include <QBitArray>
#include <QColor>
#include <QMutex>
#include <QObject>
#include <QPixmap>
#include <QVector>
#include "libkwave/Sample.h"
#include "libkwave/SampleArray.h"
#include "libkwave/Utils.h"
#include "libgui/Colors.h"
/**
* The TrackPixmap is a graphical representation of a track's sample
* data. It is connected directly to a Track object so that it is able
* to get any needed sample data on it's own. It provides internal
* caching mechanisms for reducing (slow) accesses to the track; this
* is especially needed for speeding up the handling large wav files.
*
* @note The sample ranges in this class are a kind of "virtual", it is
* possible that the length of this pixmap in samples is larger
* than the track. However, this should not do any harm and might
* even be useful if a track grows.
*
* @todo If the "interpolated mode" is used, the sample buffer should
* contain some samples before and some samples after the current
* view. (m_extra_samples, calculated in set_zoom, !=0 only in
* interpolation mode, ignored in all other modes.
*
* @todo Check setOffset()
* @todo optimizations if zoom factor is multiple of last zoom factor
* @todo optimizations in slotSamplesDeleted and slotSamplesInserted if
* parts of the current buffers can be re-used
*
* @author Thomas Eschenbacher <Thomas.Eschenbacher@gmx.de>
*/
namespace Kwave
{
class Track;
class LIBKWAVEGUI_EXPORT TrackPixmap: public QObject
{
Q_OBJECT
public:
/** Default constructor */
explicit TrackPixmap(Kwave::Track &track);
/** Destructor */
~TrackPixmap() override;
/**
* Resize the pixmap.
* @param width new width in pixels
* @param height new height in pixels
*/
virtual void resize(int width, int height);
/**
* Get the width of the pixmap
* @return the width of the pixmap in pixels
*/
virtual int width() const { return m_pixmap.width(); }
/**
* Get the height of the pixmap
* @return the height of the pixmap in pixels
*/
virtual int height() const { return m_pixmap.height(); }
/**
* Get the internal QPixmap object
* @return reference to m_pixmap
*/
virtual const QPixmap &pixmap() const { return m_pixmap; }
/**
* Repaints the current pixmap. After the repaint the pixmap is no
* longer in status "modified". If it was not modified before, this
* is a no-op.
*/
virtual void repaint();
/**
* Sets a new vertical zoom factor.
* @param zoom new vertical zoom
*/
virtual void setVerticalZoom(double zoom);
/**
* Returns "true" if the buffer has changed and the pixmap has to
* be re-painted.
*/
virtual bool isModified();
/** Sets the internal "modified" flag */
virtual void setModified() { m_modified = true; }
signals:
/** Emitted if the content of the pixmap was modified. */
void sigModified();
public slots:
/**
* Sets a new sample offset and moves the signal display
* left or right. Only the new areas that were moved in
* will be redrawn.
* @param offset index of the first visible sample
*/
void setOffset(sample_index_t offset);
/**
* Sets a new zoom factor in samples per pixel. This normally
* affects the number of visible samples and a redraw of
* the current view.
*/
void setZoom(double zoom);
private slots:
/**
* Connected to the track's sigSamplesInserted.
* @param src source track
* @param offset position from which the data was inserted
* @param length number of samples inserted
* @see Track::sigSamplesInserted
* @internal
*/
void slotSamplesInserted(Kwave::Track *src, sample_index_t offset,
sample_index_t length);
/**
* Connected to the track's sigSamplesDeleted.
* @param src source track
* @param offset position from which the data was removed
* @param length number of samples deleted
* @see Track::sigSamplesDeleted
* @internal
*/
void slotSamplesDeleted(Kwave::Track *src, sample_index_t offset,
sample_index_t length);
/**
* Connected to the track's sigSamplesModified
* @param src source track
* @param offset position from which the data was modified
* @param length number of samples modified
* @see Track::sigSamplesModified
* @internal
*/
void slotSamplesModified(Kwave::Track *src, sample_index_t offset,
sample_index_t length);
/**
* Sets the state of the pixmap to "modified" whenever the
* selection of the track has changed
*/
void selectionChanged();
private:
/**
* Resizes the current buffer and sets all new entries to
* invalid (if any).
*/
void resizeBuffer();
/**
* Sets the current buffer to "invalid" state. Note: this does
* not include any resize!
*/
void invalidateBuffer();
/**
* Adapts the current mode and size of the buffers and fills all
* areas that do not contain valid data with fresh samples. In other
* words: it makes the buffer "valid" and consistent.
* @return true if the buffer content has changed, false if no
* invalid samples were found
*/
bool validateBuffer();
/**
* Draws the signal as an overview with multiple samples per
* pixel.
* @param p reference to a QPainter
* @param middle the y position of the zero line [pixels]
* @param height the height of the pixmap [pixels]
* @param first the offset of the first pixel
* @param last the offset of the last pixel
*/
void drawOverview(QPainter &p, int middle, int height,
int first, int last);
/**
* Calculates the parameters for interpolation of the graphical
* display when zoomed in. Allocates (new) buffer for the
* filter coefficients of the low pass filter used for interpolation.
* @see m_interpolation_alpha
*/
void calculateInterpolation();
/**
* Draws the signal and interpolates the pixels between the
* samples. The interpolation is done by using a simple FIR
* lowpass filter.
* @param p reference to a QPainter
* @param width the width of the pixmap in pixels
* @param middle the y position of the zero line in the drawing
* area [pixels]
* @param height the height of the drawing are [pixels]
* @see #calculateInterpolation()
*/
void drawInterpolatedSignal(QPainter &p, int width, int middle,
int height);
/**
* Draws the signal and connects the pixels between the samples
* by using a simple poly-line. This gets used if the current zoom
* factor is not suitable for either an overview nor an interpolated
* signal display.
* @param p reference to a QPainter
* @param width the width of the pixmap in pixels
* @param middle the y position of the zero line in the drawing
* area [pixels]
* @param height the height of the drawing are [pixels]
*/
void drawPolyLineSignal(QPainter &p, int width, int middle, int height);
/**
* Converts a pixel offset into a sample offset.
*/
inline sample_index_t pixels2samples(int pixels) {
return static_cast<sample_index_t>(rint(
static_cast<double>(pixels) * m_zoom));
}
/**
* Converts a sample offset into a pixel offset.
*/
inline int samples2pixels(sample_index_t samples) {
if (m_zoom <= 0) return 0;
return Kwave::toInt(rint(static_cast<double>(samples) / m_zoom));
}
/**
* Converts the offset and length of an overlapping region into buffer
* indices, depending on the current mode. If the given region does
* not overlap at all, the length of the area will be set to zero.
* The length will be truncated to the end of the current buffer(s).
* @note If the resulting or given length is zero, the offset value
* is not necessarily valid and should be ignored!
* @param offset reference to the source sample index, will be converted
* into buffer index
* @param length reference to the length in samples, will be converted
* to the number of buffer indices
*/
void convertOverlap(sample_index_t &offset, sample_index_t &length);
private:
/** The QPixmap with the bitmap data */
QPixmap m_pixmap;
/**
* Reference to the track with our sample data.
*/
Kwave::Track &m_track;
/**
* Index of the first sample. Needed for converting pixel
* positions into absolute sample numbers. This is always
* in units of samples, independent of the current mode!
*/
sample_index_t m_offset;
/**
* Zoom factor in samples/pixel. Needed for converting
* sample indices into pixels and vice-versa.
*/
double m_zoom;
/**
* vertical zoom factor. Default is 1.0
*/
double m_vertical_zoom;
/**
* If true, we are in min/max mode. This means that m_sample_buffer
* is not used and m_minmax_buffer contains is used instead.
*/
bool m_minmax_mode;
/**
* Array with samples needed for drawing when not in min/max mode.
* This might sometimes include one sample before or after the
* current view.
*/
Kwave::SampleArray m_sample_buffer;
/**
* Array with minimum sample values, if in min/max mode.
*/
Kwave::SampleArray m_min_buffer;
/**
* Array with maximum sample values, if in min/max mode.
*/
Kwave::SampleArray m_max_buffer;
/** Indicates that the buffer content was modified */
bool m_modified;
/**
* Array with one bit for each position in the internal
* buffers. If the bit corresponding to a certain buffer
* index is set to "1", the position contains valid data,
* if "0" the content of the buffer is invalid.
*/
QBitArray m_valid;
/** Mutex for exclusive access to the buffers. */
QMutex m_lock_buffer;
/**
* order of the low pass filter used for interpolation
*/
int m_interpolation_order;
/**
* Buffer for filter coefficients of the low pass used for
* interpolation.
* @see #calculateInterpolation()
*/
QVector<double> m_interpolation_alpha;
/** set of colors for drawing */
Kwave::Colors::ColorSet m_colors;
};
}
#endif /* TRACK_PIXMAP_H */
//***************************************************************************
//***************************************************************************
|