kwave  18.07.70
ReversePlugin.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  ReversePlugin.cpp - reverses the current selection
3  -------------------
4  begin : Tue Jun 09 2009
5  copyright : (C) 2009 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 #include <math.h>
20 #include <new>
21 
22 #include <KLocalizedString> // for the i18n macro
23 
24 #include <QFutureSynchronizer>
25 #include <QList>
26 #include <QSharedPointer>
27 #include <QStringList>
28 #include <QThread>
29 #include <QtConcurrentRun>
30 
32 #include "libkwave/PluginManager.h"
33 #include "libkwave/SignalManager.h"
34 #include "libkwave/String.h"
35 #include "libkwave/Utils.h"
36 #include "libkwave/Writer.h"
38 
39 #include "libgui/SelectTimeWidget.h" // for selection mode
40 
41 #include "ReversePlugin.h"
42 #include "UndoReverseAction.h"
43 
44 KWAVE_PLUGIN(reverse, ReversePlugin)
45 
46 //***************************************************************************
47 Kwave::ReversePlugin::ReversePlugin(QObject *parent,
48  const QVariantList &args)
49  :Kwave::Plugin(parent, args)
50 {
51 }
52 
53 //***************************************************************************
55 {
56 }
57 
58 //***************************************************************************
59 void Kwave::ReversePlugin::run(QStringList params)
60 {
61  Kwave::SignalManager &signal_manager = signalManager();
62 
63  QSharedPointer<Kwave::UndoTransactionGuard> undo_guard;
64 
65  // get the current selection and the list of affected tracks
66  QList<unsigned int> tracks;
67  sample_index_t first = 0;
68  sample_index_t last = 0;
69  sample_index_t length = selection(&tracks, &first, &last, true);
70  if (!length || tracks.isEmpty())
71  return;
72 
73  if ((params.count() != 1) || (params.first() != _("noundo"))) {
74  // undo is enabled, create a undo guard
75  undo_guard = QSharedPointer<Kwave::UndoTransactionGuard>(
76  new(std::nothrow) Kwave::UndoTransactionGuard(
77  *this, i18n("Reverse")));
78  if (!undo_guard) return;
79 
80  // try to save undo information
81  Kwave::UndoAction *undo =
82  new(std::nothrow) Kwave::UndoReverseAction(manager());
83  if (!undo_guard->registerUndoAction(undo))
84  return;
85  undo->store(signal_manager);
86  }
87 
89  signalManager(), tracks, first, last);
91  signalManager(), tracks, first, last);
92 
93  // break if aborted
94  if (!source_a.tracks() || !source_b.tracks())
95  return;
96 
97  // connect the progress dialog
98  connect(&source_a, SIGNAL(progress(qreal)),
99  this, SLOT(updateProgress(qreal)),
100  Qt::BlockingQueuedConnection);
101 
102  // use a reasonably big buffer size
103  const unsigned int block_size = 5 * source_a.blockSize();
104 
105  // loop over the sample range
106  while ((first < last) && !shouldStop()) {
107  QFutureSynchronizer<void> synchronizer;
108 
110  slice_params.m_first = first;
111  slice_params.m_last = last;
112  slice_params.m_block_size = block_size;
113 
114  // loop over all tracks
115  for (int i = 0; i < tracks.count(); i++) {
116  synchronizer.addFuture(QtConcurrent::run(
117  this,
119  tracks[i], source_a[i], source_b[i],
120  slice_params)
121  );
122  }
123 
124  // next positions
125  first += block_size;
126  last = (last > block_size) ? (last - block_size) : 0;
127 
128  synchronizer.waitForFinished();
129  }
130 
131 }
132 
133 //***************************************************************************
134 void Kwave::ReversePlugin::reverseSlice(unsigned int track,
136  const Kwave::ReversePlugin::SliceParams &params)
137 {
138  Kwave::SignalManager &signal_manager = signalManager();
139  const sample_index_t first = params.m_first;
140  const sample_index_t last = params.m_last;
141  const unsigned int block_size = params.m_block_size;
142  const sample_index_t start_a = first;
143  const sample_index_t start_b = (last >= block_size) ?
144  (last - block_size) : 0;
145  bool ok = true;
146 
147  if (start_a + block_size < start_b) {
148  // read from start
149  Kwave::SampleArray buffer_a;
150  ok &= buffer_a.resize(block_size);
151  Q_ASSERT(ok);
152  *src_a >> buffer_a;
153 
154  // read from end
155  Kwave::SampleArray buffer_b;
156  ok &= buffer_b.resize(block_size);
157  Q_ASSERT(ok);
158  src_b->seek(start_b);
159  *src_b >> buffer_b;
160 
161  // swap the contents
162  reverse(buffer_a);
163  reverse(buffer_b);
164 
165  // write back buffer from the end at the start
166  Kwave::Writer *dst_a = signal_manager.openWriter(
167  Kwave::Overwrite, track,
168  start_a, start_a + block_size - 1);
169  Q_ASSERT(dst_a);
170  if (!dst_a) return;
171  *dst_a << buffer_b;
172  dst_a->flush();
173  delete dst_a;
174 
175  // write back buffer from the start at the end
176  Kwave::Writer *dst_b = signal_manager.openWriter(
177  Kwave::Overwrite, track,
178  start_b, start_b + block_size - 1);
179  Q_ASSERT(dst_b);
180  if (!dst_b) return;
181  *dst_b << buffer_a << flush;
182  delete dst_b;
183  } else {
184  // single buffer with last block
185  Kwave::SampleArray buffer;
186  ok &= buffer.resize(Kwave::toUint(last - first + 1));
187  Q_ASSERT(ok);
188 
189  // read from start
190  *src_a >> buffer;
191 
192  // swap content
193  reverse(buffer);
194 
195  // write back
196  Kwave::Writer *dst = signal_manager.openWriter(
197  Kwave::Overwrite, track, first, last);
198  if (!dst) return;
199  (*dst) << buffer << flush;
200  delete dst;
201  }
202 }
203 
204 //***************************************************************************
206 {
207  unsigned int count = buffer.size() >> 1;
208  if (count <= 1) return;
209 
210  sample_t *a = buffer.data();
211  sample_t *b = buffer.data() + (buffer.size() - 1);
212  for (; count; count--) {
213  sample_t h = *a;
214  *a++ = *b;
215  *b-- = h;
216  }
217 }
218 
219 //***************************************************************************
221 {
222  Kwave::Plugin::updateProgress(progress + progress);
223 }
224 
225 //***************************************************************************
226 #include "ReversePlugin.moc"
227 //***************************************************************************
228 //***************************************************************************
Definition: App.h:33
void reverse(Kwave::SampleArray &buffer)
virtual unsigned int tracks() const Q_DECL_OVERRIDE
Kwave::SignalManager & signalManager()
Definition: Plugin.cpp:444
virtual void updateProgress(qreal progress) Q_DECL_OVERRIDE
Kwave::Writer * openWriter(Kwave::InsertMode mode, unsigned int track, sample_index_t left=0, sample_index_t right=0)
bool flush()
Definition: Writer.h:94
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 seek(sample_index_t pos)
virtual void run(QStringList params) Q_DECL_OVERRIDE
virtual ~ReversePlugin() Q_DECL_OVERRIDE
void reverseSlice(unsigned int track, Kwave::SampleReader *src_a, Kwave::SampleReader *src_b, const Kwave::ReversePlugin::SliceParams &params)
virtual unsigned int blockSize() const
#define KWAVE_PLUGIN(name, class)
Definition: Plugin.h:54
#define _(m)
Definition: memcpy.c:66
unsigned int size() const
Kwave::Writer & flush(Kwave::Writer &s)
Definition: Writer.cpp:145
virtual void updateProgress(qreal progress)
Definition: Plugin.cpp:260
unsigned int toUint(T x)
Definition: Utils.h:109
sample_t * data()
Definition: SampleArray.h:62
bool resize(unsigned int size) Q_REQUIRED_RESULT
bool shouldStop() const
Definition: Plugin.h:120
virtual bool store(Kwave::SignalManager &manager)=0
qint32 sample_t
Definition: Sample.h:37
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