kwave  18.07.70
Kwave::SonagramPlugin Class Reference

#include <SonagramPlugin.h>

Inheritance diagram for Kwave::SonagramPlugin:
Inheritance graph
Collaboration diagram for Kwave::SonagramPlugin:
Collaboration graph

Classes

struct  Slice
 

Signals

void sliceAvailable (Kwave::SonagramPlugin::Slice *slice)
 
- Signals inherited from Kwave::Plugin
void sigRunning (Kwave::Plugin *plugin)
 
void sigDone (Kwave::Plugin *plugin)
 
void sigClosed (Kwave::Plugin *p)
 
void sigCommand (const QString &command)
 
void setProgressText (const QString &text)
 

Public Member Functions

 SonagramPlugin (QObject *parent, const QVariantList &args)
 
virtual ~SonagramPlugin () Q_DECL_OVERRIDE
 
virtual QStringList * setup (QStringList &previous_params) Q_DECL_OVERRIDE
 
virtual int start (QStringList &params) Q_DECL_OVERRIDE
 
virtual void run (QStringList params) Q_DECL_OVERRIDE
 
- Public Member Functions inherited from Kwave::Plugin
 Plugin (QObject *parent, const QVariantList &args)
 
virtual ~Plugin () Q_DECL_OVERRIDE
 
virtual QString name () const
 
virtual QString description () const
 
virtual QString progressText ()
 
virtual bool canClose () const
 
bool isRunning () const
 
bool shouldStop () const
 
virtual void load (QStringList &params)
 
virtual void unload ()
 
virtual int stop ()
 
Kwave::PluginManagermanager () const
 
Kwave::SignalManagersignalManager ()
 
QWidget * parentWidget () const
 
QString signalName ()
 
virtual sample_index_t signalLength ()
 
virtual double signalRate ()
 
virtual const QList< unsigned int > selectedTracks ()
 
virtual sample_index_t selection (QList< unsigned int > *tracks=Q_NULLPTR, sample_index_t *left=Q_NULLPTR, sample_index_t *right=Q_NULLPTR, bool expand_if_empty=false)
 
virtual void selectRange (sample_index_t offset, sample_index_t length)
 
virtual void migrateToActiveContext ()
 
- Public Member Functions inherited from Kwave::Runnable
virtual ~Runnable ()
 

Protected Member Functions

int interpreteParameters (QStringList &params)
 
- Protected Member Functions inherited from Kwave::Plugin
int execute (QStringList &params)
 
void emitCommand (const QString &command)
 
void use ()
 
void setPluginManager (Kwave::PluginManager *new_plugin_manager)
 
virtual void run_wrapper (const QVariant &params) Q_DECL_OVERRIDE
 

Private Slots

void validate ()
 
void windowDestroyed ()
 
void insertSlice (Kwave::SonagramPlugin::Slice *slice)
 
void refreshOverview ()
 
void slotTrackInserted (const QUuid &track_id)
 
void slotTrackDeleted (const QUuid &track_id)
 
void slotInvalidated (const QUuid *track_id, sample_index_t first, sample_index_t last)
 

Private Member Functions

void makeAllValid ()
 
void requestValidation ()
 
void calculateSlice (Kwave::SonagramPlugin::Slice *slice)
 
void createNewImage (const unsigned int width, const unsigned int height)
 

Private Attributes

Kwave::SonagramWindowm_sonagram_window
 
Kwave::SelectionTrackerm_selection
 
unsigned int m_slices
 
unsigned int m_fft_points
 
Kwave::window_function_t m_window_type
 
bool m_color
 
bool m_track_changes
 
bool m_follow_selection
 
QImage m_image
 
Kwave::OverViewCachem_overview_cache
 
Kwave::FixedPool< MAX_FFT_JOBS, Slicem_slice_pool
 
QBitArray m_valid
 
QReadWriteLock m_pending_jobs
 
QMutex m_lock_job_list
 
QFuture< void > m_future
 
QTimer m_repaint_timer
 

Additional Inherited Members

- Public Slots inherited from Kwave::Plugin
virtual void setProgressDialogEnabled (bool enable)
 
virtual void updateProgress (qreal progress)
 
virtual void cancel ()
 
virtual void close ()
 
void release ()
 

Detailed Description

plugin that shows a sonagram window

Definition at line 64 of file SonagramPlugin.h.

Constructor & Destructor Documentation

◆ SonagramPlugin()

Kwave::SonagramPlugin::SonagramPlugin ( QObject *  parent,
const QVariantList &  args 
)

Constructor

Parameters
parentreference to our plugin manager
argsargument list [unused]

Definition at line 62 of file SonagramPlugin.cpp.

References Kwave::connect(), insertSlice(), m_repaint_timer, sliceAvailable(), and validate().

64  :Kwave::Plugin(parent, args),
65  m_sonagram_window(Q_NULLPTR),
66  m_selection(Q_NULLPTR),
67  m_slices(0), m_fft_points(0),
70  m_overview_cache(Q_NULLPTR), m_slice_pool(), m_valid(MAX_SLICES, false),
71  m_pending_jobs(), m_lock_job_list(QMutex::Recursive), m_future(),
73 {
74  i18n("Sonagram");
75 
76  // connect the output ouf the sonagram worker thread
79  Qt::QueuedConnection);
80 
81  // connect repaint timer
82  connect(&m_repaint_timer, SIGNAL(timeout()),
83  this, SLOT(validate()));
84 }
unsigned int m_fft_points
QFuture< void > m_future
Kwave::FixedPool< MAX_FFT_JOBS, Slice > m_slice_pool
void sliceAvailable(Kwave::SonagramPlugin::Slice *slice)
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
QReadWriteLock m_pending_jobs
Kwave::SonagramWindow * m_sonagram_window
#define MAX_SLICES
Kwave::window_function_t m_window_type
Kwave::SelectionTracker * m_selection
Kwave::OverViewCache * m_overview_cache
void insertSlice(Kwave::SonagramPlugin::Slice *slice)
Here is the call graph for this function:

◆ ~SonagramPlugin()

Kwave::SonagramPlugin::~SonagramPlugin ( )
virtual

Destructor

Definition at line 87 of file SonagramPlugin.cpp.

References m_repaint_timer, m_selection, and m_sonagram_window.

88 {
89  m_repaint_timer.stop();
90 
92  m_sonagram_window = Q_NULLPTR;
93 
94  if (m_selection) delete m_selection;
95  m_selection = Q_NULLPTR;
96 }
Kwave::SonagramWindow * m_sonagram_window
Kwave::SelectionTracker * m_selection

Member Function Documentation

◆ calculateSlice()

void Kwave::SonagramPlugin::calculateSlice ( Kwave::SonagramPlugin::Slice slice)
private

do the FFT calculation on a slice

Parameters
slicestructure with the input data and output buffer

Definition at line 399 of file SonagramPlugin.cpp.

References m_fft_points, Kwave::SonagramPlugin::Slice::m_input, Kwave::SonagramPlugin::Slice::m_output, Kwave::SonagramPlugin::Slice::m_result, and sliceAvailable().

Referenced by makeAllValid().

400 {
401  fftw_plan p;
402 
403  // prepare for a 1-dimensional real-to-complex DFT
404  {
405  Kwave::GlobalLock _lock; // libfftw is not threadsafe!
406  p = fftw_plan_dft_r2c_1d(
407  m_fft_points,
408  &(slice->m_input[0]),
409  &(slice->m_output[0]),
410  FFTW_ESTIMATE
411  );
412  }
413  Q_ASSERT(p);
414  if (!p) return;
415 
416  // calculate the fft (according to the specs, this is the one and only
417  // libfft function that is threadsafe!)
418  fftw_execute(p);
419 
420  // norm all values to [0...254] and use them as pixel value
421  const double scale = static_cast<double>(m_fft_points) / 254.0;
422  for (unsigned int j = 0; j < m_fft_points / 2; j++) {
423  // get singal energy and scale to [0 .. 254]
424  double rea = slice->m_output[j][0];
425  double ima = slice->m_output[j][1];
426  double a = ((rea * rea) + (ima * ima)) / scale;
427 
428  slice->m_result[j] = static_cast<unsigned char>(qMin(a, double(254.0)));
429  }
430 
431  // free the allocated FFT resources
432  {
433  Kwave::GlobalLock _lock; // libfftw is not threadsafe!
434  fftw_destroy_plan(p);
435  }
436 
437  // emit the slice data to be synchronously inserted into
438  // the current image in the context of the main thread
439  // (Qt does the queuing for us)
440  emit sliceAvailable(slice);
441 }
unsigned int m_fft_points
void sliceAvailable(Kwave::SonagramPlugin::Slice *slice)
unsigned char m_result[MAX_FFT_POINTS]
fftw_complex m_output[MAX_FFT_POINTS]
double m_input[MAX_FFT_POINTS]
Here is the caller graph for this function:

◆ createNewImage()

void Kwave::SonagramPlugin::createNewImage ( const unsigned int  width,
const unsigned int  height 
)
private

Creates a new image for the current processing. If an old image exists, it will be deleted first, a new image will not be created if either width or height is zero. The image will get 8 bits depth and use a color or a greyscale palette.

Parameters
widthnumber of horizontal pixels (slices = signal length / fft points, rounded up) [1..32767]
heightnumber of vertical pixels (= fft points / 2) [1..32767]

Definition at line 469 of file SonagramPlugin.cpp.

References m_image, m_sonagram_window, and Kwave::SonagramWindow::setImage().

Referenced by start().

471 {
472  // delete the previous image
473  m_image = QImage();
475 
476  // do not create a new image if one dimension is zero!
477  Q_ASSERT(width);
478  Q_ASSERT(height);
479  if (!width || !height) return;
480 
481  // also do not create if the image size is out of range
482  Q_ASSERT(width <= 32767);
483  Q_ASSERT(height <= 32767);
484  if ((width >= 32767) || (height >= 32767)) return;
485 
486  // create the new image object
487  m_image = QImage(width, height, QImage::Format_Indexed8);
488  Q_ASSERT(!m_image.isNull());
489  if (m_image.isNull()) return;
490 
491  // initialize the image's palette with transparecy
492  m_image.setColorCount(256);
493  for (int i = 0; i < 256; i++) {
494  m_image.setColor(i, 0x00000000);
495  }
496 
497  // fill the image with "empty" (transparent)
498  m_image.fill(0xFF);
499 }
Kwave::SonagramWindow * m_sonagram_window
void setImage(QImage image)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ insertSlice

void Kwave::SonagramPlugin::insertSlice ( Kwave::SonagramPlugin::Slice slice)
privateslot

Internally used to synchronously insert the data of one sonagram slice int the current image and refresh the display.

Note
DO NOT CALL DIRECTLY!
Parameters
slicea slice data container, including result

Definition at line 444 of file SonagramPlugin.cpp.

References Kwave::SonagramWindow::insertSlice(), m_fft_points, Kwave::SonagramPlugin::Slice::m_index, m_pending_jobs, Kwave::SonagramPlugin::Slice::m_result, m_slice_pool, and m_sonagram_window.

Referenced by SonagramPlugin().

445 {
446  // check: this must be called from the GUI thread only!
447  Q_ASSERT(this->thread() == QThread::currentThread());
448  Q_ASSERT(this->thread() == qApp->thread());
449 
450  Q_ASSERT(slice);
451  if (!slice) return;
452 
453  QByteArray result;
454  result.setRawData(reinterpret_cast<char *>(&(slice->m_result[0])),
455  m_fft_points / 2);
456  unsigned int nr = slice->m_index;
457 
458  // forward the slice to the window to display it
460 
461  // return the slice into the pool
462  m_slice_pool.release(slice);
463 
464  // job is done
465  m_pending_jobs.unlock();
466 }
unsigned int m_fft_points
Kwave::FixedPool< MAX_FFT_JOBS, Slice > m_slice_pool
void insertSlice(const unsigned int slice_nr, const QByteArray &slice)
unsigned char m_result[MAX_FFT_POINTS]
QReadWriteLock m_pending_jobs
Kwave::SonagramWindow * m_sonagram_window
Here is the call graph for this function:
Here is the caller graph for this function:

◆ interpreteParameters()

int Kwave::SonagramPlugin::interpreteParameters ( QStringList &  params)
protected

interpretes a given parameter list and sets up internal coordinates accordingly

Parameters
paramsreference to a QStringList with parameters
Returns
0 if ok, or an error code if failed

Definition at line 126 of file SonagramPlugin.cpp.

References Kwave::WindowFunction::findFromName(), m_color, m_fft_points, m_follow_selection, m_track_changes, m_window_type, and MAX_FFT_POINTS.

Referenced by setup(), and start().

127 {
128  bool ok;
129  QString param;
130 
131  // evaluate the parameter list
132  if (params.count() != 5) return -EINVAL;
133 
134  param = params[0];
135  m_fft_points = param.toUInt(&ok);
136  if (!ok) return -EINVAL;
138 
139  param = params[1];
141  if (!ok) return -EINVAL;
142 
143  param = params[2];
144  m_color = (param.toUInt(&ok) != 0);
145  if (!ok) return -EINVAL;
146 
147  param = params[3];
148  m_track_changes = (param.toUInt(&ok) != 0);
149  if (!ok) return -EINVAL;
150 
151  param = params[4];
152  m_follow_selection = (param.toUInt(&ok) != 0);
153  if (!ok) return -EINVAL;
154 
155  return 0;
156 }
unsigned int m_fft_points
static window_function_t findFromName(const QString &name)
Kwave::window_function_t m_window_type
#define MAX_FFT_POINTS
Here is the call graph for this function:
Here is the caller graph for this function:

◆ makeAllValid()

void Kwave::SonagramPlugin::makeAllValid ( )
private

will be run in a background thread to make all stripes valid.

Definition at line 271 of file SonagramPlugin.cpp.

References Kwave::SelectionTracker::allTracks(), Kwave::SignalManager::allTracks(), calculateSlice(), Kwave::MultiTrackReader::eof(), Kwave::SelectionTracker::first(), Kwave::SelectionTracker::last(), Kwave::SelectionTracker::length(), m_fft_points, m_lock_job_list, m_pending_jobs, m_selection, m_slice_pool, m_slices, m_valid, m_window_type, Kwave::WindowFunction::points(), sample2double(), Kwave::MultiTrackReader::seek(), Kwave::Plugin::shouldStop(), Kwave::Plugin::signalManager(), Kwave::SinglePassForward, sliceAvailable(), and Kwave::toInt().

Referenced by run(), and validate().

272 {
273  unsigned int fft_points;
274  unsigned int slices;
275  Kwave::window_function_t window_type;
276  sample_index_t first_sample;
277  sample_index_t last_sample;
278  QBitArray valid;
279  QList<unsigned int> track_list;
280 
281  {
282  QMutexLocker _lock(&m_lock_job_list);
283 
284  if (!m_selection) return;
285  if (!m_selection->length() || (m_fft_points < 4)) return;
286 
287  fft_points = m_fft_points;
288  slices = m_slices;
289  window_type = m_window_type;
290  first_sample = m_selection->first();
291  last_sample = m_selection->last();
292  valid = m_valid;
293  m_valid.fill(true);
294 
295  const QList<QUuid> selected_tracks(m_selection->allTracks());
296  foreach (unsigned int track, signalManager().allTracks())
297  if (selected_tracks.contains(signalManager().uuidOfTrack(track)))
298  track_list.append(track);
299  }
300  const unsigned int tracks = track_list.count();
301 
302  Kwave::WindowFunction func(window_type);
303  const QVector<double> windowfunction = func.points(fft_points);
304  Q_ASSERT(windowfunction.count() == Kwave::toInt(fft_points));
305  if (windowfunction.count() != Kwave::toInt(fft_points)) return;
306 
308  signalManager(), track_list, first_sample, last_sample);
309 
310 // qDebug("SonagramPlugin[%p]::makeAllValid() [%llu .. %llu]",
311 // static_cast<void *>(this), first_sample, last_sample);
312 
313  QFutureSynchronizer<void> synchronizer;
314  for (unsigned int slice_nr = 0; slice_nr < slices; slice_nr++) {
315 // qDebug("SonagramPlugin::run(): calculating slice %d of %d",
316 // slice_nr, m_slices);
317 
318  if (valid[slice_nr]) continue;
319 
320  // determine start of the stripe
321  sample_index_t pos = first_sample + (slice_nr * fft_points);
322 
323  // get a new slice from the pool and initialize it
324  Kwave::SonagramPlugin::Slice *slice = m_slice_pool.allocate();
325  Q_ASSERT(slice);
326 
327  slice->m_index = slice_nr;
328  memset(slice->m_input, 0x00, sizeof(slice->m_input));
329  memset(slice->m_output, 0x00, sizeof(slice->m_output));
330 
331  if ((pos <= last_sample) && (tracks)) {
332  // initialize result with zeroes
333  memset(slice->m_result, 0x00, sizeof(slice->m_result));
334 
335  // seek to the start of the slice
336  source.seek(pos);
337 
338  // we have a new slice, now fill it's input buffer
339  double *in = slice->m_input;
340  for (unsigned int j = 0; j < fft_points; j++) {
341  double value = 0.0;
342  if (!(source.eof())) {
343  for (unsigned int t = 0; t < tracks; t++) {
344  sample_t s = 0;
345  Kwave::SampleReader *reader = source[t];
346  Q_ASSERT(reader);
347  if (reader) *reader >> s;
348  value += sample2double(s);
349  }
350  value /= tracks;
351  }
352  in[j] = value * windowfunction[j];
353  }
354 
355  // a background job is running soon
356  // (for counterpart, see insertSlice(...) below [main thread])
357  m_pending_jobs.lockForRead();
358 
359  // run the FFT in a background thread
360  synchronizer.addFuture(QtConcurrent::run(
362  );
363  } else {
364  // range has been deleted -> fill with "empty"
365  memset(slice->m_result, 0xFF, sizeof(slice->m_result));
366  m_pending_jobs.lockForRead();
367  emit sliceAvailable(slice);
368  }
369 
370  if (shouldStop()) break;
371  }
372 
373 // qDebug("SonagramPlugin::makeAllValid(): waiting for background jobs...");
374 
375  // wait for all worker threads
376  synchronizer.waitForFinished();
377 
378  // wait for queued signals
379  m_pending_jobs.lockForWrite();
380  m_pending_jobs.unlock();
381 
382 // qDebug("SonagramPlugin::makeAllValid(): done.");
383 }
unsigned int m_fft_points
sample_index_t first() const
window_function_t
Kwave::FixedPool< MAX_FFT_JOBS, Slice > m_slice_pool
void sliceAvailable(Kwave::SonagramPlugin::Slice *slice)
Kwave::SignalManager & signalManager()
Definition: Plugin.cpp:444
QList< QUuid > allTracks()
quint64 sample_index_t
Definition: Sample.h:28
QReadWriteLock m_pending_jobs
int toInt(T x)
Definition: Utils.h:127
sample_index_t last() const
const QList< unsigned int > allTracks()
static double sample2double(const sample_t s)
Definition: Sample.h:73
Kwave::window_function_t m_window_type
void calculateSlice(Kwave::SonagramPlugin::Slice *slice)
Kwave::SelectionTracker * m_selection
bool shouldStop() const
Definition: Plugin.h:120
sample_index_t length() const
qint32 sample_t
Definition: Sample.h:37
Here is the call graph for this function:
Here is the caller graph for this function:

◆ refreshOverview

void Kwave::SonagramPlugin::refreshOverview ( )
privateslot

Updates the overview image under the sonagram

Definition at line 502 of file SonagramPlugin.cpp.

References Kwave::OverViewCache::getOverView(), m_overview_cache, m_sonagram_window, Kwave::SonagramWindow::setOverView(), and SONAGRAM_OVERVIEW_HEIGHT.

Referenced by start().

503 {
504  if (!m_overview_cache || !m_sonagram_window) return;
505 
506  QColor fg = m_sonagram_window->palette().light().color();
507  QColor bg = m_sonagram_window->palette().mid().color();
508  QImage overview = m_overview_cache->getOverView(
509  m_sonagram_window->width(), SONAGRAM_OVERVIEW_HEIGHT, fg, bg);
510 
511  m_sonagram_window->setOverView(overview);
512 }
virtual QImage getOverView(int width, int height, const QColor &fg, const QColor &bg, double gain=1.0)
#define SONAGRAM_OVERVIEW_HEIGHT
Kwave::SonagramWindow * m_sonagram_window
void setOverView(const QImage &image)
Kwave::OverViewCache * m_overview_cache
Here is the call graph for this function:
Here is the caller graph for this function:

◆ requestValidation()

void Kwave::SonagramPlugin::requestValidation ( )
private

Requests an update of the sonagram or portions of it

Definition at line 515 of file SonagramPlugin.cpp.

References m_repaint_timer, and REPAINT_INTERVAL.

Referenced by slotInvalidated(), slotTrackDeleted(), slotTrackInserted(), and validate().

516 {
517  // only re-start the repaint timer, this hides some GUI update artifacts
518  if (!m_repaint_timer.isActive()) {
519  m_repaint_timer.stop();
520  m_repaint_timer.setSingleShot(true);
522  }
523 }
#define REPAINT_INTERVAL
Here is the caller graph for this function:

◆ run()

void Kwave::SonagramPlugin::run ( QStringList  params)
virtual

Runns once until all slices of the sonagram are calculated.

Parameters
paramslist of strings with parameters
See also
Kwave::Plugin::run()

Reimplemented from Kwave::Plugin.

Definition at line 386 of file SonagramPlugin.cpp.

References m_lock_job_list, m_valid, and makeAllValid().

387 {
388  qDebug("SonagramPlugin::run()");
389  Q_UNUSED(params);
390  {
391  // invalidate all slices
392  QMutexLocker _lock(&m_lock_job_list);
393  m_valid.fill(false);
394  }
395  makeAllValid();
396 }
Here is the call graph for this function:

◆ setup()

QStringList * Kwave::SonagramPlugin::setup ( QStringList &  previous_params)
virtual
See also
Kwave::Plugin::setup()

Reimplemented from Kwave::Plugin.

Definition at line 99 of file SonagramPlugin.cpp.

References interpreteParameters(), m_color, m_follow_selection, m_track_changes, m_window_type, Kwave::SonagramDialog::parameters(), Kwave::SonagramDialog::setColorMode(), Kwave::SonagramDialog::setFollowSelection(), Kwave::SonagramDialog::setTrackChanges(), and Kwave::SonagramDialog::setWindowFunction().

100 {
101  QStringList *result = Q_NULLPTR;
102 
103  // try to interprete the list of previous parameters, ignore errors
104  if (previous_params.count()) interpreteParameters(previous_params);
105 
106  Kwave::SonagramDialog *dlg = new(std::nothrow) Kwave::SonagramDialog(*this);
107  Q_ASSERT(dlg);
108  if (!dlg) return Q_NULLPTR;
109 
111  dlg->setColorMode(m_color ? 1 : 0);
114 
115  if (dlg->exec() == QDialog::Accepted) {
116  result = new QStringList();
117  Q_ASSERT(result);
118  if (result) dlg->parameters(*result);
119  };
120 
121  delete dlg;
122  return result;
123 }
void parameters(QStringList &list)
int interpreteParameters(QStringList &params)
void setColorMode(int color)
void setTrackChanges(bool track_changes)
void setFollowSelection(bool follow_selection)
Kwave::window_function_t m_window_type
void setWindowFunction(Kwave::window_function_t type)
Here is the call graph for this function:

◆ sliceAvailable

void Kwave::SonagramPlugin::sliceAvailable ( Kwave::SonagramPlugin::Slice slice)
signal

emitted when a new slice has been calculated in calculateSlice()

Parameters
slicethe slice data container, including result

Referenced by calculateSlice(), makeAllValid(), and SonagramPlugin().

Here is the caller graph for this function:

◆ slotInvalidated

void Kwave::SonagramPlugin::slotInvalidated ( const QUuid *  track_id,
sample_index_t  first,
sample_index_t  last 
)
privateslot

Connected to the selection tracker's sigInvalidated.

Parameters
track_idUUID of the track or null for "all tracks"
firstindex of the first invalidated sample
lastindex of the last invalidated sample

Definition at line 569 of file SonagramPlugin.cpp.

References m_fft_points, m_lock_job_list, m_selection, m_slices, m_track_changes, m_valid, Kwave::SelectionTracker::offset(), requestValidation(), Kwave::round_up(), SAMPLE_INDEX_MAX, and Kwave::toUint().

Referenced by start().

572 {
573  QMutexLocker lock(&m_lock_job_list);
574 
575  Q_UNUSED(track_id);
576 // qDebug("SonagramPlugin[%p]::slotInvalidated(%s, %llu, %llu)",
577 // static_cast<void *>(this),
578 // (track_id) ? DBG(track_id->toString()) : "*", first, last);
579 
580  // check for "track changes" mode
581  if (!m_track_changes) return;
582 
583  // adjust offsets, absolute -> relative
584  sample_index_t offset = (m_selection) ? m_selection->offset() : 0;
585  Q_ASSERT(first >= offset);
586  Q_ASSERT(last >= offset);
587  Q_ASSERT(last >= first);
588  first -= offset;
589  last -= offset;
590 
591  unsigned int first_idx = Kwave::toUint(first / m_fft_points);
592  unsigned int last_idx;
593  if (last >= (SAMPLE_INDEX_MAX - (m_fft_points - 1)))
594  last_idx = m_slices - 1;
595  else
596  last_idx = Kwave::toUint(qMin(Kwave::round_up(last,
597  static_cast<sample_index_t>(m_fft_points)) / m_fft_points,
598  static_cast<sample_index_t>(m_slices - 1))
599  );
600 
601  m_valid.fill(false, first_idx, last_idx + 1);
603 }
unsigned int m_fft_points
sample_index_t offset() const
quint64 sample_index_t
Definition: Sample.h:28
T round_up(T x, const T s)
Definition: Utils.h:96
unsigned int toUint(T x)
Definition: Utils.h:109
#define SAMPLE_INDEX_MAX
Definition: Sample.h:31
Kwave::SelectionTracker * m_selection
Here is the call graph for this function:
Here is the caller graph for this function:

◆ slotTrackDeleted

void Kwave::SonagramPlugin::slotTrackDeleted ( const QUuid &  track_id)
privateslot

Connected to the selection tracker's sigTrackInserted.

Parameters
track_idunique ID of the track
See also
SelectionTracker::sigTrackDeleted

Definition at line 554 of file SonagramPlugin.cpp.

References m_lock_job_list, m_slices, m_track_changes, m_valid, and requestValidation().

Referenced by start().

555 {
556  QMutexLocker _lock(&m_lock_job_list);
557 
558  Q_UNUSED(track_id);
559 
560  // check for "track changes" mode
561  if (!m_track_changes) return;
562 
563  // invalidate complete signal
564  m_valid.fill(false, m_slices);
566 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ slotTrackInserted

void Kwave::SonagramPlugin::slotTrackInserted ( const QUuid &  track_id)
privateslot

Connected to the selection tracker's sigTrackInserted.

Parameters
track_idunique ID of the track
See also
SelectionTracker::sigTrackInserted

Definition at line 539 of file SonagramPlugin.cpp.

References m_lock_job_list, m_slices, m_track_changes, m_valid, and requestValidation().

Referenced by start().

540 {
541  QMutexLocker _lock(&m_lock_job_list);
542 
543  Q_UNUSED(track_id);
544 
545  // check for "track changes" mode
546  if (!m_track_changes) return;
547 
548  // invalidate complete signal
549  m_valid.fill(false, m_slices);
551 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ start()

int Kwave::SonagramPlugin::start ( QStringList &  params)
virtual
See also
Kwave::Plugin::start()

Reimplemented from Kwave::Plugin.

Definition at line 159 of file SonagramPlugin.cpp.

References Kwave::Plugin::close(), Kwave::connect(), createNewImage(), Kwave::MessageBox::error(), interpreteParameters(), m_color, m_fft_points, m_image, m_overview_cache, m_selection, m_slices, m_sonagram_window, m_track_changes, Kwave::Plugin::manager(), MAX_SLICES, Kwave::Plugin::parentWidget(), refreshOverview(), Kwave::Plugin::selection(), Kwave::SonagramWindow::setColorMode(), Kwave::SonagramWindow::setImage(), Kwave::SonagramWindow::setPoints(), Kwave::SonagramWindow::setRate(), Kwave::Plugin::sigClosed(), Kwave::Plugin::signalManager(), Kwave::Plugin::signalName(), Kwave::Plugin::signalRate(), slotInvalidated(), slotTrackDeleted(), slotTrackInserted(), Kwave::toUint(), Kwave::Plugin::use(), and windowDestroyed().

160 {
161  // clean up leftovers from last run
163  m_sonagram_window = Q_NULLPTR;
164  if (m_selection) delete m_selection;
165  m_selection = Q_NULLPTR;
167  m_overview_cache = Q_NULLPTR;
168 
169  Kwave::SignalManager &sig_mgr = signalManager();
170 
171  // interprete parameter list and abort if it contains invalid data
172  int result = interpreteParameters(params);
173  if (result) return result;
174 
175  // create an empty sonagram window
176  m_sonagram_window = new(std::nothrow)
178  Q_ASSERT(m_sonagram_window);
179  if (!m_sonagram_window) return -ENOMEM;
180 
181  // if the signal closes, close the sonagram window too
182  QObject::connect(&manager(), SIGNAL(sigClosed()),
183  m_sonagram_window, SLOT(close()));
184 
185  // get the current selection
186  QList<unsigned int> selected_channels;
187  sample_index_t offset = 0;
188  sample_index_t length = 0;
189  length = selection(&selected_channels, &offset, Q_NULLPTR, true);
190 
191  // abort if nothing is selected
192  if (!length || selected_channels.isEmpty())
193  return -EINVAL;
194 
195  // calculate the number of slices (width of image)
196  m_slices = Kwave::toUint(ceil(static_cast<double>(length) /
197  static_cast<double>(m_fft_points)));
199 
200  /* limit selection to INT_MAX samples (limitation of the cache index) */
201  if ((length / m_fft_points) >= INT_MAX) {
203  i18n("File or selection too large"));
204  return -EFBIG;
205  }
206 
207  // create a selection tracker
208  m_selection = new(std::nothrow) Kwave::SelectionTracker(
209  &sig_mgr, offset, length, &selected_channels);
210  Q_ASSERT(m_selection);
211  if (!m_selection) return -ENOMEM;
212 
213  connect(m_selection, SIGNAL(sigTrackInserted(QUuid)),
214  this, SLOT(slotTrackInserted(QUuid)));
215  connect(m_selection, SIGNAL(sigTrackDeleted(QUuid)),
216  this, SLOT(slotTrackDeleted(QUuid)));
217  connect(
218  m_selection,
219  SIGNAL(sigInvalidated(const QUuid*,sample_index_t,sample_index_t)),
220  this,
221  SLOT(slotInvalidated(const QUuid*,sample_index_t,sample_index_t))
222  );
223 
224  // create a new empty image
226 
227  // set the overview
228  m_overview_cache = new(std::nothrow)
229  Kwave::OverViewCache(sig_mgr, offset, length, &selected_channels);
230  Q_ASSERT(m_overview_cache);
231  if (!m_overview_cache) return -ENOMEM;
232 
233  refreshOverview(); // <- this needs the m_overview_cache
234 
235  if (m_track_changes) {
236  // stay informed about changes in the signal
237  connect(m_overview_cache, SIGNAL(changed()),
238  this, SLOT(refreshOverview()));
239  } else {
240  // overview cache is no longer needed
241  delete m_overview_cache;
242  m_overview_cache = Q_NULLPTR;
243  }
244 
245  // connect all needed signals
246  connect(m_sonagram_window, SIGNAL(destroyed()),
247  this, SLOT(windowDestroyed()));
248 
249  // activate the window with an initial image
250  // and all necessary information
255  m_sonagram_window->show();
256 
257  if (m_track_changes) {
258  QObject::connect(static_cast<QObject*>(&(manager())),
259  SIGNAL(sigSignalNameChanged(QString)),
260  m_sonagram_window, SLOT(setName(QString)));
261  }
262 
263  // increment the usage counter and release the plugin when the
264  // sonagram window closed
265  use();
266 
267  return 0;
268 }
unsigned int m_fft_points
void slotTrackDeleted(const QUuid &track_id)
int interpreteParameters(QStringList &params)
QWidget * parentWidget() const
Definition: Plugin.cpp:450
Kwave::SignalManager & signalManager()
Definition: Plugin.cpp:444
virtual void close()
Definition: Plugin.cpp:394
quint64 sample_index_t
Definition: Sample.h:28
Kwave::PluginManager & manager() const
Definition: Plugin.cpp:437
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
void setPoints(unsigned int points)
static int error(QWidget *widget, QString message, QString caption=QString())
Definition: MessageBox.cpp:126
void setRate(double rate)
Kwave::SonagramWindow * m_sonagram_window
void sigClosed(Kwave::Plugin *p)
#define MAX_SLICES
QString signalName()
Definition: Plugin.cpp:456
virtual double signalRate()
Definition: Plugin.cpp:468
void slotTrackInserted(const QUuid &track_id)
unsigned int toUint(T x)
Definition: Utils.h:109
void use()
Definition: Plugin.cpp:412
void setImage(QImage image)
void slotInvalidated(const QUuid *track_id, sample_index_t first, sample_index_t last)
Kwave::SelectionTracker * m_selection
Kwave::OverViewCache * m_overview_cache
void createNewImage(const unsigned int width, const unsigned int height)
virtual sample_index_t selection(QList< unsigned int > *tracks=Q_NULLPTR, sample_index_t *left=Q_NULLPTR, sample_index_t *right=Q_NULLPTR, bool expand_if_empty=false)
Definition: Plugin.cpp:480
void setColorMode(int mode)
Here is the call graph for this function:

◆ validate

void Kwave::SonagramPlugin::validate ( )
privateslot

validate the sonagram by calling makeAllValid in a background thread

Definition at line 526 of file SonagramPlugin.cpp.

References m_future, makeAllValid(), and requestValidation().

Referenced by SonagramPlugin().

527 {
528  // wait for previously running jobs to finish
529  if (m_future.isRunning()) {
531  return; // job is still running, come back later...
532  }
533 
534  // queue a background thread for updates
535  m_future = QtConcurrent::run(this, &Kwave::SonagramPlugin::makeAllValid);
536 }
QFuture< void > m_future
Here is the call graph for this function:
Here is the caller graph for this function:

◆ windowDestroyed

void Kwave::SonagramPlugin::windowDestroyed ( )
privateslot

Connected to the SonagramWindow's "destroyed()" signal.

See also
class SonagramWindow

Definition at line 606 of file SonagramPlugin.cpp.

References Kwave::Plugin::cancel(), m_overview_cache, m_selection, m_sonagram_window, and Kwave::Plugin::release().

Referenced by start().

607 {
608  cancel();
609 
610  m_sonagram_window = Q_NULLPTR; // closes itself !
611 
612  if (m_selection) delete m_selection;
613  m_selection = Q_NULLPTR;
614 
616  m_overview_cache = Q_NULLPTR;
617 
618  release();
619 }
void release()
Definition: Plugin.cpp:420
Kwave::SonagramWindow * m_sonagram_window
virtual void cancel()
Definition: Plugin.cpp:325
Kwave::SelectionTracker * m_selection
Kwave::OverViewCache * m_overview_cache
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_color

bool Kwave::SonagramPlugin::m_color
private

if true, use color display, else use greyscale

Definition at line 230 of file SonagramPlugin.h.

Referenced by interpreteParameters(), setup(), and start().

◆ m_fft_points

unsigned int Kwave::SonagramPlugin::m_fft_points
private

number of fft points

Definition at line 224 of file SonagramPlugin.h.

Referenced by calculateSlice(), insertSlice(), interpreteParameters(), makeAllValid(), slotInvalidated(), and start().

◆ m_follow_selection

bool Kwave::SonagramPlugin::m_follow_selection
private

if true, update the sonagram if the selection changed

Definition at line 236 of file SonagramPlugin.h.

Referenced by interpreteParameters(), and setup().

◆ m_future

QFuture<void> Kwave::SonagramPlugin::m_future
private

the currently running background job

Definition at line 257 of file SonagramPlugin.h.

Referenced by validate().

◆ m_image

QImage Kwave::SonagramPlugin::m_image
private

stores the image that is currently in process

Definition at line 239 of file SonagramPlugin.h.

Referenced by createNewImage(), and start().

◆ m_lock_job_list

QMutex Kwave::SonagramPlugin::m_lock_job_list
private

lock to protect the job list (m_valid)

Definition at line 254 of file SonagramPlugin.h.

Referenced by makeAllValid(), run(), slotInvalidated(), slotTrackDeleted(), and slotTrackInserted().

◆ m_overview_cache

Kwave::OverViewCache* Kwave::SonagramPlugin::m_overview_cache
private

cache with the current signal overview

Definition at line 242 of file SonagramPlugin.h.

Referenced by refreshOverview(), start(), and windowDestroyed().

◆ m_pending_jobs

QReadWriteLock Kwave::SonagramPlugin::m_pending_jobs
private

lock used for tracking running background jobs

Definition at line 251 of file SonagramPlugin.h.

Referenced by insertSlice(), and makeAllValid().

◆ m_repaint_timer

QTimer Kwave::SonagramPlugin::m_repaint_timer
private

timer for refreshing the sonagram

Definition at line 260 of file SonagramPlugin.h.

Referenced by requestValidation(), SonagramPlugin(), and ~SonagramPlugin().

◆ m_selection

Kwave::SelectionTracker* Kwave::SonagramPlugin::m_selection
private

selection tracker

Definition at line 218 of file SonagramPlugin.h.

Referenced by makeAllValid(), slotInvalidated(), start(), windowDestroyed(), and ~SonagramPlugin().

◆ m_slice_pool

Kwave::FixedPool<MAX_FFT_JOBS, Slice> Kwave::SonagramPlugin::m_slice_pool
private

pool of slices

Definition at line 245 of file SonagramPlugin.h.

Referenced by insertSlice(), and makeAllValid().

◆ m_slices

unsigned int Kwave::SonagramPlugin::m_slices
private

number of slices (= width of the image in pixels)

Definition at line 221 of file SonagramPlugin.h.

Referenced by makeAllValid(), slotInvalidated(), slotTrackDeleted(), slotTrackInserted(), and start().

◆ m_sonagram_window

Kwave::SonagramWindow* Kwave::SonagramPlugin::m_sonagram_window
private

the main view of the plugin, a SonagramWindow

Definition at line 215 of file SonagramPlugin.h.

Referenced by createNewImage(), insertSlice(), refreshOverview(), start(), windowDestroyed(), and ~SonagramPlugin().

◆ m_track_changes

bool Kwave::SonagramPlugin::m_track_changes
private

if true, update the sonagram if the signal changes

Definition at line 233 of file SonagramPlugin.h.

Referenced by interpreteParameters(), setup(), slotInvalidated(), slotTrackDeleted(), slotTrackInserted(), and start().

◆ m_valid

QBitArray Kwave::SonagramPlugin::m_valid
private

bit field with "is valid" a flag for each stripe

Definition at line 248 of file SonagramPlugin.h.

Referenced by makeAllValid(), run(), slotInvalidated(), slotTrackDeleted(), and slotTrackInserted().

◆ m_window_type

Kwave::window_function_t Kwave::SonagramPlugin::m_window_type
private

index of the window function

Definition at line 227 of file SonagramPlugin.h.

Referenced by interpreteParameters(), makeAllValid(), and setup().


The documentation for this class was generated from the following files: