Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / QtCollider / widgets / soundfileview / view.hpp
blob0294816c862292196732de5d7876cf1b155ade10
1 /************************************************************************
3 * Copyright 2010 Jakob Leben (jakob.leben@gmail.com)
5 * This file is part of SuperCollider Qt GUI.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ************************************************************************/
22 #ifndef QC_SOUND_FILE_VIEW_H
23 #define QC_SOUND_FILE_VIEW_H
25 #include "../../Common.h"
26 #include "../../QcHelper.h"
28 #include <sndfile.h>
30 #include <QVBoxLayout>
31 #include <QScrollBar>
32 #include <QSlider>
33 #include <QPixmap>
34 #include <QThread>
36 class QcWaveform;
37 class SoundCacheStream;
39 struct SoundCache {
40 SoundCache() : min(0), max(0), sum(0), sum2(0) {};
41 ~SoundCache() {
42 delete [] min;
43 delete [] max;
44 delete [] sum;
45 delete [] sum2;
47 short *min;
48 short *max;
49 float *sum;
50 float *sum2;
53 class QcWaveform : public QWidget, public QcHelper {
55 Q_OBJECT
57 Q_PROPERTY( float readProgress READ loadProgress );
58 Q_PROPERTY( int startFrame READ startFrame );
59 Q_PROPERTY( int frames READ frames );
60 Q_PROPERTY( double viewFrames READ viewFrames );
61 Q_PROPERTY( double viewStartFrame READ viewStartFrame WRITE scrollTo );
62 Q_PROPERTY( float scrollPos READ scrollPos WRITE setScrollPos );
63 Q_PROPERTY( int currentSelection READ currentSelection WRITE setCurrentSelection );
64 Q_PROPERTY( VariantList selections READ selections );
66 Q_PROPERTY( float yZoom READ yZoom WRITE setYZoom );
67 Q_PROPERTY( float xZoom READ xZoom WRITE setXZoom );
68 Q_PROPERTY( bool cursorVisible READ cursorVisible WRITE setCursorVisible );
69 Q_PROPERTY( bool cursorEditable READ cursorEditable WRITE setCursorEditable );
70 Q_PROPERTY( int cursorPosition READ cursorPosition WRITE setCursorPosition );
71 Q_PROPERTY( bool gridVisible READ gridVisible WRITE setGridVisible );
72 Q_PROPERTY( float gridOffset READ gridOffset WRITE setGridOffset );
73 Q_PROPERTY( float gridResolution READ gridResolution WRITE setGridResolution );
74 Q_PROPERTY( bool drawsWaveform READ drawsWaveform WRITE setDrawsWaveform );
75 Q_PROPERTY( QColor background READ background WRITE setBackground );
76 Q_PROPERTY( QColor peakColor READ peakColor WRITE setPeakColor );
77 Q_PROPERTY( QColor rmsColor READ rmsColor WRITE setRmsColor );
78 Q_PROPERTY( QColor cursorColor READ cursorColor WRITE setCursorColor );
79 Q_PROPERTY( QColor gridColor READ gridColor WRITE setGridColor );
81 public:
82 Q_INVOKABLE void load( const QString& filename );
84 // NOTE: Using int instead of sf_count_t for accessibility from SC language.
85 Q_INVOKABLE void load( const QString& filename, int beginning, int duration );
87 Q_INVOKABLE void load( const QVector<double> & data, int offset = 0,
88 int channels = 1, int samplerate = 44100 );
90 Q_INVOKABLE void allocate ( int frames, int channels = 1, int samplerate = 44100 );
92 Q_INVOKABLE void write( const QVector<double> & data, int offset );
94 public:
96 struct Selection {
97 Selection() : start(0), size(0), editable(true), color(QColor(0,0,150)) {}
98 sf_count_t start;
99 sf_count_t size;
100 bool editable;
101 QColor color;
104 QcWaveform( QWidget * parent = 0 );
105 ~QcWaveform();
107 float loadProgress();
108 sf_count_t startFrame() { return _rangeBeg; }
109 sf_count_t frames() { return _rangeDur; }
111 double viewStartFrame() { return _beg; }
112 double viewFrames() { return _dur; }
113 float scrollPos(); // as fraction of scrolling range
114 float zoom(); //visible fraction
115 float xZoom(); //visible seconds
116 float yZoom(); //factor
118 VariantList selections() const;
119 int currentSelection() const { return _curSel; }
120 void setCurrentSelection( int i );
121 // for SC: selection start relative to first loaded frame
122 Q_INVOKABLE VariantList selection( int index ) const;
123 // for SC: selection start relative to first loaded frame
124 Q_INVOKABLE void setSelection( int index, VariantList data );
125 void setSelection( int i, sf_count_t a, sf_count_t b );
126 Q_INVOKABLE void setSelectionStart( int i, sf_count_t frame );
127 Q_INVOKABLE void setSelectionEnd( int i, sf_count_t frame );
128 Q_INVOKABLE void setSelectionEditable( int index, bool editable );
129 Q_INVOKABLE void setSelectionColor( int index, const QColor &clr );
130 Q_PROPERTY( VariantList waveColors READ waveColors WRITE setWaveColors );
132 bool cursorVisible() const { return _showCursor; }
133 void setCursorVisible( bool b ) { _showCursor = b; update(); }
134 int cursorPosition() const { return _cursorPos; }
135 void setCursorPosition( int pos ) { _cursorPos = pos; update(); }
136 bool cursorEditable() const { return _cursorEditable; }
137 void setCursorEditable( bool b ) { _cursorEditable = b; }
139 bool gridVisible() const { return _showGrid; }
140 void setGridVisible( bool b ) { _showGrid = b; update(); }
141 float gridOffset() const { return _gridOffset; }
142 void setGridOffset( float f ) { _gridOffset = f; update(); }
143 float gridResolution() const { return _gridResolution; }
144 void setGridResolution( float f ) { _gridResolution = f; update(); }
146 bool drawsWaveform() const { return _drawWaveform; }
147 void setDrawsWaveform( bool b ) { _drawWaveform = b; update(); }
148 VariantList waveColors() const;
149 void setWaveColors( const VariantList & );
151 const QColor & background() const { return _bkgColor; }
152 void setBackground( const QColor &c )
154 if(_bkgColor == c) return;
155 _bkgColor = c;
156 setAttribute(Qt::WA_OpaquePaintEvent, c.isValid() && c.alpha() == 255);
157 update();
159 const QColor & peakColor() const { return _peakColor; }
160 void setPeakColor( const QColor &clr ) { _peakColor = clr; redraw(); }
161 const QColor & rmsColor() const { return _rmsColor; }
162 void setRmsColor( const QColor &clr ) { _rmsColor = clr; redraw(); }
163 const QColor & cursorColor() const { return _cursorColor; }
164 void setCursorColor( const QColor &c ) { _cursorColor = c; update(); }
165 const QColor & gridColor() const { return _gridColor; }
166 void setGridColor( const QColor &c ) { _gridColor = c; update(); }
168 QSize sizeHint() const { return QSize( 400, 200 ); }
169 QSize minimumSizeHint() const { return QSize( 100, 20 ); }
171 public Q_SLOTS:
172 void zoomTo( double fraction );
173 //void zoomTo( float fraction, quint64 frame );
174 void zoomBy( double factor );
175 void zoomAllOut();
176 void zoomSelection( int selectionIndex );
177 void scrollTo( double frame );
178 void scrollBy( double frames );
179 void setScrollPos( double fraction ); // as fraction of scrolling range
180 void scrollToStart();
181 void scrollToEnd();
182 void setYZoom( double factor );
183 void setXZoom( double seconds );
186 Q_SIGNALS:
188 void loadProgress( int );
189 void loadingDone();
191 void action();
192 void metaAction();
194 public Q_SLOTS:
196 void redraw() {
197 dirty = true;
198 update();
201 protected:
203 virtual void resizeEvent( QResizeEvent * );
204 virtual void paintEvent( QPaintEvent * );
205 virtual void keyPressEvent( QKeyEvent * );
206 virtual void mousePressEvent( QMouseEvent * );
207 virtual void mouseDoubleClickEvent ( QMouseEvent * );
208 virtual void mouseMoveEvent( QMouseEvent * );
210 private:
212 void doLoad( SNDFILE *new_sf, const SF_INFO &new_info, sf_count_t beginning, sf_count_t duration );
213 inline void updateFPP() { _fpp = width() ? (double) _dur / width() : 0.0; }
214 void rebuildCache ( int maxFramesPerCache, int maxRawFrames );
215 void draw ( QPixmap *, int x, int width, double beginning, double duration );
217 // data
218 SNDFILE *sf;
219 SF_INFO sfInfo;
220 sf_count_t _rangeBeg;
221 sf_count_t _rangeDur;
222 sf_count_t _rangeEnd;
224 SoundCacheStream *_cache;
226 // selections
227 Selection _selections[64];
228 int _curSel;
230 // cursor
231 bool _showCursor;
232 sf_count_t _cursorPos;
233 bool _cursorEditable;
235 //grid
236 bool _showGrid;
237 float _gridResolution;
238 float _gridOffset;
240 // view
241 double _beg;
242 double _dur;
243 double _fpp;
244 float _yZoom;
246 // painting
247 QPixmap *pixmap;
248 QColor _bkgColor;
249 QColor _peakColor;
250 QColor _rmsColor;
251 QColor _cursorColor;
252 QColor _gridColor;
253 bool dirty;
254 bool _drawWaveform;
255 QList<QColor> _waveColors;
257 // interaction
258 enum DragAction {
259 NoDragAction,
260 Navigate,
261 Select,
262 MoveSelection,
263 MoveCursor
265 DragAction _dragAction;
266 QPointF _dragPoint;
267 sf_count_t _dragFrame;
268 double _dragData;
269 double _dragData2;
272 class SoundStream {
273 public:
274 inline int channels() { return _ch; }
276 inline sf_count_t beginning() { return _beg; }
278 inline sf_count_t duration() { return _dur; }
280 virtual bool displayData( int channel, double offset, double duration,
281 short *minBuffer,
282 short *maxBuffer,
283 short *minRMS,
284 short *maxRMS,
285 int bufferSize ) = 0;
287 virtual short *rawFrames( int channel, sf_count_t beginning, sf_count_t duration, bool *interleaved ) = 0;
289 protected:
290 SoundStream()
291 : _ch( 0 ), _beg( 0 ), _dur( 0 ) {}
293 SoundStream( int channels, sf_count_t beginning, sf_count_t duration ) :
294 _ch( channels ), _beg( beginning ), _dur( duration ) {}
296 int _ch;
297 sf_count_t _beg;
298 sf_count_t _dur;
301 class SoundFileStream : public SoundStream
303 public:
304 SoundFileStream();
305 SoundFileStream( SNDFILE *sf, const SF_INFO &sf_info, sf_count_t beginning, sf_count_t duration );
306 ~SoundFileStream();
307 void load( SNDFILE *sf, const SF_INFO &sf_info, sf_count_t beginning, sf_count_t duration );
308 bool integrate( int channel, double offset, double duration,
309 short *minBuffer,
310 short *maxBuffer,
311 float *sumBuffer,
312 float *sum2Buffer,
313 int bufferSize );
314 bool displayData( int channel, double offset, double duration,
315 short *minBuffer,
316 short *maxBuffer,
317 short *minRMS,
318 short *maxRMS,
319 int bufferSize );
320 short *rawFrames( int channel, sf_count_t beginning, sf_count_t duration, bool *interleaved );
321 private:
322 short *_data;
323 sf_count_t _dataSize;
324 sf_count_t _dataOffset;
327 class SoundCacheLoader;
329 class SoundCacheStream : public QObject, public SoundStream
331 friend class SoundCacheLoader;
333 Q_OBJECT
335 public:
336 SoundCacheStream();
337 ~SoundCacheStream();
338 void load( const QVector<double> & data, int frames, int offset, int channels );
339 void load( SNDFILE *sf, const SF_INFO &info, sf_count_t beg, sf_count_t dur,
340 int maxFramesPerUnit, int maxRawFrames );
341 void allocate ( int frames, int channels );
342 void write( const QVector<double> & data, int offset, int count );
344 inline double fpu() { return _fpu; }
345 inline bool ready() { return _ready; }
346 inline bool loading() { return _loading; }
347 inline int loadProgress() { return _loadProgress; }
348 bool displayData( int channel, double offset, double duration,
349 short *minBuffer,
350 short *maxBuffer,
351 short *minRMS,
352 short *maxRMS,
353 int bufferSize );
354 short *rawFrames( int channel, sf_count_t beginning, sf_count_t duration, bool *interleaved );
356 Q_SIGNALS:
357 void loadProgress( int );
358 void loadingDone();
360 private Q_SLOTS:
361 void onLoadProgress( int );
362 void onLoadingDone();
364 private:
365 SoundCache *_caches;
366 double _fpu; // soundfile frames per cache unit
367 sf_count_t _dataOffset; // offset into soundfile of first frame cached (in frames)
368 sf_count_t _dataSize; // amount of cache units
369 bool _ready;
370 bool _loading;
371 SoundCacheLoader *_loader;
372 int _loadProgress;
375 class SoundCacheLoader : public QThread
377 Q_OBJECT
378 public:
379 SoundCacheLoader( SoundCacheStream *cache ) : QThread( cache ), _cache( cache ), _sf(0) {}
380 void load( SNDFILE *sf, const SF_INFO &info );
382 Q_SIGNALS:
383 void loadProgress( int );
384 void loadingDone();
385 private:
386 void run();
388 SoundCacheStream *_cache;
389 SNDFILE *_sf;
390 SF_INFO _info;
393 #endif