kwave  18.07.70
Signal.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  Signal.cpp - representation of a Kwave signal with multiple tracks
3  -------------------
4  begin : Sat Feb 03 2001
5  copyright : (C) 2001 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 
20 #include <math.h>
21 #include <new>
22 #include <stdio.h>
23 #include <stdlib.h>
24 
25 #include <QReadLocker>
26 #include <QWriteLocker>
27 
28 #include <KLocalizedString>
29 
30 #include "libkwave/Curve.h"
31 #include "libkwave/Filter.h"
32 #include "libkwave/Interpolation.h"
33 #include "libkwave/MessageBox.h"
34 #include "libkwave/Signal.h"
35 #include "libkwave/Track.h"
36 #include "libkwave/Utils.h"
38 
39 //***************************************************************************
41  :m_tracks(), m_lock_tracks()
42 {
43 }
44 
45 //***************************************************************************
48 {
49  while (tracks--) {
50  appendTrack(length, Q_NULLPTR);
51  }
52 }
53 
54 //***************************************************************************
56 {
57  close();
58 }
59 
60 //***************************************************************************
62 {
63  unsigned int count;
64  while ((count = tracks()))
65  deleteTrack(count - 1);
66 }
67 
68 //***************************************************************************
71  QUuid *uuid)
72 {
73  Kwave::Track *t = Q_NULLPTR;
74  {
75  QWriteLocker lock(&m_lock_tracks);
76 
77  t = new(std::nothrow) Kwave::Track(length, uuid);
78  Q_ASSERT(t);
79  if (!t) return Q_NULLPTR;
80 
81  // clip the track index
82  if (Kwave::toInt(index) > m_tracks.count())
83  index = m_tracks.count();
84 
85  // insert / append to the list
86  m_tracks.insert(index, t);
87 
88  // connect to the new track's signals
92  sample_index_t)));
96  sample_index_t)));
100  sample_index_t)));
101 
102  connect(t, SIGNAL(sigSelectionChanged(bool)),
103  this, SIGNAL(sigTrackSelectionChanged(bool)));
104  }
105 
106  // track has been inserted
107  emit sigTrackInserted(index, t);
108  return t;
109 }
110 
111 
112 //***************************************************************************
114 {
115  return insertTrack(tracks(), length, uuid);
116 }
117 
118 //***************************************************************************
119 void Kwave::Signal::deleteTrack(unsigned int index)
120 {
121  // remove the track from the list but do not delete it
122  Kwave::Track *t = Q_NULLPTR;
123  {
124  QWriteLocker lock(&m_lock_tracks);
125  if (Kwave::toInt(index) > m_tracks.count())
126  return; // bail out if not in range
127 
128  t = m_tracks.at(index);
129  m_tracks.removeAt(index);
130  }
131 
132  // now emit a signal that the track has been deleted. Maybe
133  // someone is still using a reference to it, so we have not
134  // deleted it yet - still only unlinked from the track list!
135  emit sigTrackDeleted(index, t);
136 
137  // as everybody now knows that the track is gone, we can safely
138  // delete it now.
139  if (t) delete t;
140 }
141 
142 //***************************************************************************
144  unsigned int track, sample_index_t left, sample_index_t right)
145 {
146  QReadLocker lock(&m_lock_tracks);
147 
148  Q_ASSERT(Kwave::toInt(track) < m_tracks.count());
149  if (Kwave::toInt(track) >= m_tracks.count()) {
150  return Q_NULLPTR; // track does not exist !
151  }
152 
153  Kwave::Track *t = m_tracks.at(track);
154  Q_ASSERT(t);
155  return (t) ? t->openWriter(mode, left, right) : Q_NULLPTR;
156 }
157 
158 //***************************************************************************
160  unsigned int track,
161  sample_index_t left,
162  sample_index_t right)
163 {
164  QReadLocker lock(&m_lock_tracks);
165 
166  if (Kwave::toInt(track) >= m_tracks.count())
167  return Q_NULLPTR; // track does not exist !
168 
169  Kwave::Track *t = m_tracks.at(track);
170  Q_ASSERT(t);
171  return (t) ? t->openReader(mode, left, right) : Q_NULLPTR;
172 }
173 
174 //***************************************************************************
176  sample_index_t left,
177  sample_index_t right)
178 {
179  QReadLocker lock(&m_lock_tracks);
180 
181  if (Kwave::toInt(track) < m_tracks.count()) {
182  Kwave::Track *t = m_tracks.at(track);
183  Q_ASSERT(t);
184  if (t) return t->stripes(left, right);
185  }
186  return Kwave::Stripe::List(); // track does not exist !
187 }
188 
189 //***************************************************************************
191  unsigned int track)
192 {
193  QReadLocker lock(&m_lock_tracks);
194 
195  if (Kwave::toInt(track) >= m_tracks.count())
196  return false;
197 
198  Kwave::Track *t = m_tracks.at(track);
199  Q_ASSERT(t);
200  if (!t) return false;
201 
202  return t->mergeStripes(stripes);
203 }
204 
205 //***************************************************************************
206 QList<unsigned int> Kwave::Signal::allTracks()
207 {
208  unsigned int track;
209  unsigned int tracks = this->tracks();
210  QList<unsigned int> list;
211 
212  for (track=0; track < tracks; track++) {
213  list.append(track);
214  }
215 
216  return list;
217 }
218 
219 //***************************************************************************
220 void Kwave::Signal::deleteRange(unsigned int track,
221  sample_index_t offset,
223 {
224  QReadLocker lock(&m_lock_tracks);
225 
226  Q_ASSERT(Kwave::toInt(track) < m_tracks.count());
227  if (Kwave::toInt(track) >= m_tracks.count())
228  return; // track does not exist !
229 
230  Kwave::Track *t = m_tracks.at(track);
231  Q_ASSERT(t);
232  if (t) t->deleteRange(offset, length);
233 }
234 
235 //***************************************************************************
236 void Kwave::Signal::insertSpace(unsigned int track, sample_index_t offset,
238 {
239  QReadLocker lock(&m_lock_tracks);
240 
241  Q_ASSERT(Kwave::toInt(track) < m_tracks.count());
242  if (Kwave::toInt(track) >= m_tracks.count())
243  return; // track does not exist !
244 
245  Kwave::Track *t = m_tracks.at(track);
246  Q_ASSERT(t);
247  if (t) t->insertSpace(offset, length);
248 }
249 
250 //***************************************************************************
251 unsigned int Kwave::Signal::tracks()
252 {
253  QReadLocker lock(&m_lock_tracks);
254  return m_tracks.count();
255 }
256 
257 //***************************************************************************
259 {
260  QReadLocker lock(&m_lock_tracks);
261 
262  sample_index_t max = 0;
263  foreach (Kwave::Track *track, m_tracks) {
264  if (!track) continue;
265  sample_index_t len = track->length();
266  if (len > max) max = len;
267  }
268  return max;
269 }
270 
271 //***************************************************************************
272 bool Kwave::Signal::trackSelected(unsigned int track)
273 {
274  QReadLocker lock(&m_lock_tracks);
275 
276  if (Kwave::toInt(track) >= m_tracks.count()) return false;
277  if (!m_tracks.at(track)) return false;
278 
279  return m_tracks.at(track)->selected();
280 }
281 
282 //***************************************************************************
283 void Kwave::Signal::selectTrack(unsigned int track, bool select)
284 {
285  QReadLocker lock(&m_lock_tracks);
286 
287  Q_ASSERT(Kwave::toInt(track) < m_tracks.count());
288  if (Kwave::toInt(track) >= m_tracks.count()) return;
289  Q_ASSERT(m_tracks.at(track));
290  if (!m_tracks.at(track)) return;
291 
292  m_tracks.at(track)->select(select);
293 }
294 
295 //***************************************************************************
296 QUuid Kwave::Signal::uuidOfTrack(unsigned int track)
297 {
298  QReadLocker lock(&m_lock_tracks);
299 
300  if (Kwave::toInt(track) >= m_tracks.count()) return QUuid();
301  Q_ASSERT(m_tracks.at(track));
302  if (!m_tracks.at(track)) return QUuid();
303 
304  return m_tracks.at(track)->uuid();
305 }
306 
309 //#define MAXPRIME 512
310 //int Signal::getChannelMaximum () {
311 // int max = 0;
312 // for (int i = 0; i < length; i++)
313 // if (max < qAbs(sample[i])) max = qAbs(sample[i]);
314 //
315 // return max;
316 //}
318 //int getMaxPrimeFactor (int len) {
319 // int max = 1;
320 // int tst = len;
321 //
322 // //here follows the canonical slow prime factor search, but it does its job
323 // //with small numbers, greater ones should not occur within this program...
324 //
325 // if (((tst % 2)) == 0) {
326 // max = 2;
327 // tst /= 2;
328 // while ((tst % 2) == 0) tst /= 2; //remove prime factor 2
329 // }
330 //
331 //
332 // for (int i = 3; i <= sqrt(tst); i += 2)
333 // if ((tst % i) == 0) {
334 // if (i > max) max = i;
335 // while ((tst % i) == 0) tst /= i; //divide the current prime factor until it is not present any more
336 // }
337 //
338 //
339 // if (tst > max) max = tst;
340 //
341 // return max;
342 //}
344 
345 //void Signal::fft (int windowtype, bool accurate)
346 //{
347 // complex *data = 0;
348 //
349 // if (!accurate) {
350 // int reduce = 1;
351 // int max = getMaxPrimeFactor (len); //get biggest prime factor
352 //
353 // if (max > MAXPRIME) {
354 // while ((len - reduce > MAXPRIME) && (getMaxPrimeFactor(len - reduce) > MAXPRIME)) reduce++;
355 // len -= reduce; //correct length of buffer to be transferred
356 // }
357 //
358 //
359 // }
360 //
361 // data = new complex[len];
362 //
363 // if (data) {
364 // double rea, ima, max = 0;
365 //
366 // for (int i = 0; i < len; i++) {
367 // data[i].real = ((double)(sample[begin + i]) / (1 << 23));
368 // data[i].imag = 0;
369 // }
370 //
371 // gsl_fft_complex_wavetable table;
372 //
373 // gsl_fft_complex_wavetable_alloc (len, &table);
374 //
375 // gsl_fft_complex_init (len, &table);
376 //
377 // gsl_fft_complex_forward (data, len, &table);
378 // gsl_fft_complex_wavetable_free (&table);
379 //
380 // for (int i = 0; i < len; i++) {
381 // rea = data[i].real;
382 // ima = data[i].imag;
383 // rea = sqrt(rea * rea + ima * ima); //get amplitude
384 // if (max < rea) max = rea;
385 // }
386 //
387 // } else {
388 // if (data) delete data;
389 // Kwave::MessageBox::error
390 // (0, i18n("Info"), i18n("No Memory for FFT-buffers available."), 2);
391 // }
392 //}
393 //
395 //void Signal::averageFFT (int points, window_function_t windowtype) {
463 //}
465 //void Kwave::Signal::movingFilter (Kwave::Filter *filter, int tap,
466 // Kwave::Curve *points, int low, int high)
467 //{
468 // Kwave::Interpolation interpolation (0);
469 //
470 // QMemArray<double> *move = interpolation.interpolation (points, len);
471 // if (move) {
472 // for (int i = 0; i < len; i++)
473 // //rescale range of filtermovement...
474 // move[i] = ((double)low) / 1000 + (((double)(high - low)) / 1000 * *move[i]);
475 //
476 // double val;
477 // double addup = 0;
478 // unsigned int max = 0;
479 // unsigned int num = filter->count();
480 //
481 // for (unsigned int j = 0; j < num; j++) {
482 // addup += fabs(filter->coeff(j));
483 // if (max < filter->delay(j)) max = filter->delay(j); //find maximum offset
484 // }
485 //
486 // if (filter->isFIR()) {
487 // for (unsigned int i = begin + len - 1; i >= begin + max; i--) {
488 // filter->setCoeff(tap, (*move[i - begin]));
489 // val = filter->coeff(0) * sample[i];
490 // for (unsigned int j = 1; j < filter->count(); j++)
491 // val += filter->coeff(j) * sample[i - filter->delay(j)];
492 // sample[i] = (int)(val / addup); //renormalize
493 // }
494 //
495 //
496 // // slower routine because of check, needed only in this range...
497 // for (unsigned int i = begin + max - 1; i >= begin; i--)
498 // {
499 // filter->setCoeff(tap, *move[i - begin]);
500 // val = filter->coeff(0) * sample[i];
501 // for (unsigned int j = 1; j < filter->count(); j++)
502 // if (i - filter->delay(j) > 0)
503 // val += filter->coeff(j) * sample[i - filter->delay(j)];
504 // sample[i] = (int)(val / addup); //renormalize
505 // }
506 //
507 //
508 // } else {
509 // // basically the same,but the loops go viceversa
510 //
511 // //slower routine because of check, needed only in this range...
512 // for (unsigned int i = begin; i < begin + max; i++) {
513 // filter->setCoeff(tap, *move[i - begin]);
514 // val = filter->coeff(0) * sample[i];
515 // for (unsigned int j = 1; j < filter->count(); j++)
516 // if (i - filter->delay(j) > 0)
517 // val += filter->coeff(j) * sample[i - filter->delay(j)];
518 // sample[i] = (int)(val / addup); //renormalize
519 // }
520 //
521 //
522 // for (unsigned int i = begin + max; i < begin + len; i++) {
523 // filter->setCoeff(tap, *move[i - begin]);
524 // val = filter->coeff(0) * sample[i];
525 // for (unsigned int j = 1; j < filter->count(); j++)
526 // val += filter->coeff(j) * sample[i - filter->delay(j)];
527 // sample[i] = (int)(val / addup); //renormalize
528 // }
529 //
530 //
531 // }
532 //
533 // delete move;
534 // }
535 //}
536 //
538 //void Kwave::Signal::replaceStutter (int len1, int len2) {
539 // int *sample = &(this->sample[lmarker]);
540 //
541 // int j;
542 // int i = len2;
543 // while (i < len - len1) {
544 // for (j = 0; j < len1; j++) sample[i + j] = 0;
545 // i += len1 + len2;
546 // counter = i;
547 // }
548 // counter = -1;
549 //}
550 //
552 //void Kwave::Signal::mixPaste (Signal *signal) {
553 // int pastelength = signal->getLength ();
554 // int *paste = signal->getSample();
555 // int marked = (lmarker != rmarker) ? rmarker - lmarker + 1 : length;
556 // if (pastelength > marked) pastelength = marked;
557 // if (lmarker + pastelength > length) pastelength = length - lmarker;
558 //
559 // int *sample = this->sample + lmarker;
560 // while (pastelength--) {
561 // *sample = (*paste + *sample) >> 1;
562 // sample++;
563 // paste++;
564 // }
565 
566 //***************************************************************************
567 unsigned int Kwave::Signal::trackIndex(const Kwave::Track *track)
568 {
569  QReadLocker lock(&m_lock_tracks);
570 
571  int index = m_tracks.indexOf(const_cast<Kwave::Track *>(track));
572  return (index >= 0) ? index : m_tracks.count();
573 }
574 
575 //***************************************************************************
577  sample_index_t offset,
579 {
580  unsigned int track = trackIndex(src);
581  emit sigSamplesInserted(track, offset, length);
582 }
583 
584 //***************************************************************************
586  sample_index_t offset,
588 {
589  unsigned int track = trackIndex(src);
590  emit sigSamplesDeleted(track, offset, length);
591 }
592 
593 //***************************************************************************
595  sample_index_t offset,
597 {
598  unsigned int track = trackIndex(src);
599  emit sigSamplesModified(track, offset, length);
600 }
601 
602 //***************************************************************************
603 //***************************************************************************
void sigTrackSelectionChanged(bool enabled)
void deleteTrack(unsigned int index)
Definition: Signal.cpp:119
unsigned int trackIndex(const Kwave::Track *track)
Definition: Signal.cpp:567
sample_index_t length()
Definition: Signal.cpp:258
void slotSamplesModified(Kwave::Track *src, sample_index_t offset, sample_index_t length)
Definition: Signal.cpp:594
Kwave::Stripe::List stripes(unsigned int track, sample_index_t left=0, sample_index_t right=SAMPLE_INDEX_MAX)
Definition: Signal.cpp:175
Kwave::Track * appendTrack(sample_index_t length, QUuid *uuid)
Definition: Signal.cpp:113
void deleteRange(sample_index_t offset, sample_index_t length, bool make_gap=false)
Definition: Track.cpp:293
ReaderMode
Definition: ReaderMode.h:27
void sigTrackInserted(unsigned int index, Kwave::Track *track)
Kwave::SampleReader * openReader(Kwave::ReaderMode mode, sample_index_t left=0, sample_index_t right=SAMPLE_INDEX_MAX)
Definition: Track.cpp:274
quint64 sample_index_t
Definition: Sample.h:28
bool mergeStripes(const Kwave::Stripe::List &stripes)
Definition: Track.cpp:251
bool insertSpace(sample_index_t offset, sample_index_t shift)
Definition: Track.cpp:314
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
void sigSamplesDeleted(unsigned int track, sample_index_t offset, sample_index_t length)
QUuid uuidOfTrack(unsigned int track)
Definition: Signal.cpp:296
QList< Kwave::Track * > m_tracks
Definition: Signal.h:313
QReadWriteLock m_lock_tracks
Definition: Signal.h:316
void slotSamplesDeleted(Kwave::Track *src, sample_index_t offset, sample_index_t length)
Definition: Signal.cpp:585
void deleteRange(unsigned int track, sample_index_t offset, sample_index_t length)
Definition: Signal.cpp:220
virtual ~Signal()
Definition: Signal.cpp:55
Kwave::SampleReader * openReader(Kwave::ReaderMode mode, unsigned int track, sample_index_t left=0, sample_index_t right=SAMPLE_INDEX_MAX)
Definition: Signal.cpp:159
int toInt(T x)
Definition: Utils.h:127
void sigTrackDeleted(unsigned int index, Kwave::Track *track)
Kwave::Track * insertTrack(unsigned int index, sample_index_t length, QUuid *uuid)
Definition: Signal.cpp:69
void sigSamplesModified(unsigned int track, sample_index_t offset, sample_index_t length)
void slotSamplesInserted(Kwave::Track *src, sample_index_t offset, sample_index_t length)
Definition: Signal.cpp:576
Kwave::Writer * openWriter(Kwave::InsertMode mode, sample_index_t left=0, sample_index_t right=0)
Definition: Track.cpp:188
void sigSamplesInserted(unsigned int track, sample_index_t offset, sample_index_t length)
Kwave::Writer * openWriter(Kwave::InsertMode mode, unsigned int track, sample_index_t left=0, sample_index_t right=0)
Definition: Signal.cpp:143
InsertMode
Definition: InsertMode.h:26
void close()
Definition: Signal.cpp:61
void insertSpace(unsigned int track, sample_index_t offset, sample_index_t length)
Definition: Signal.cpp:236
QList< unsigned int > allTracks()
Definition: Signal.cpp:206
bool mergeStripes(const Kwave::Stripe::List &stripes, unsigned int track)
Definition: Signal.cpp:190
Kwave::Stripe::List stripes(sample_index_t left, sample_index_t right)
Definition: Track.cpp:209
bool trackSelected(unsigned int track)
Definition: Signal.cpp:272
sample_index_t length()
Definition: Track.cpp:173
unsigned int tracks()
Definition: Signal.cpp:251
void selectTrack(unsigned int track, bool select)
Definition: Signal.cpp:283