Skip to content

Commit 2e7e18f

Browse files
committed
Added loop toggle in Audio menu
1 parent 869c8c8 commit 2e7e18f

File tree

7 files changed

+111
-49
lines changed

7 files changed

+111
-49
lines changed

LoopableBuffer.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "LoopableBuffer.h"
2+
3+
LoopableBuffer::LoopableBuffer(QObject* _parent)
4+
: QBuffer(_parent), m_loop(false)
5+
{
6+
}
7+
8+
LoopableBuffer::LoopableBuffer(QByteArray *_byteArray, QObject* _parent)
9+
: QBuffer(_byteArray, _parent), m_loop(false)
10+
{
11+
}
12+
13+
qint64 LoopableBuffer::readData(char *_data, qint64 _len)
14+
{
15+
if(_len <= 0)
16+
return qint64(0);
17+
18+
if(m_loop)
19+
{
20+
qint64 dataPos = 0;
21+
qint64 tmpLen = 0;
22+
while(dataPos < _len)
23+
{
24+
tmpLen = qMin(_len - dataPos, size() - pos());
25+
dataPos += QBuffer::readData(_data + dataPos, tmpLen);
26+
if(atEnd())
27+
reset();
28+
}
29+
return dataPos;
30+
}
31+
else
32+
{
33+
return QBuffer::readData(_data, _len);
34+
}
35+
}

LoopableBuffer.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef LOOPABLEBUFFER_H
2+
#define LOOPABLEBUFFER_H
3+
4+
#include <QBuffer>
5+
6+
class LoopableBuffer : public QBuffer
7+
{
8+
public:
9+
LoopableBuffer(QObject* _parent = nullptr);
10+
LoopableBuffer(QByteArray *_byteArray, QObject* _parent = nullptr);
11+
12+
inline void setLoop(bool _loop) { m_loop = _loop; }
13+
inline bool loop() { return m_loop; }
14+
15+
protected:
16+
virtual qint64 readData(char* _data, qint64 _len) override;
17+
18+
private:
19+
bool m_loop;
20+
};
21+
22+
#endif // LOOPABLEBUFFER_H

Signal.cpp

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "Components.h"
2626
#include <QAudioRecorder>
2727
#include "WAVFormat.h"
28+
#include "LoopableBuffer.h"
2829

2930
Signal::Signal(QObject *parent)
3031
: QObject(parent),
@@ -78,12 +79,14 @@ Signal::Signal(QObject *parent)
7879
connect(m_audio, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChanged(QAudio::State)));
7980
m_audio->setVolume(0.2);
8081

81-
// start audio with buffer
82-
m_buffer = new QBuffer(m_samples);
82+
// create the buffer with the audio samples
83+
m_buffer = new LoopableBuffer(m_samples);
84+
m_buffer->open(QIODevice::ReadOnly);
8385
}
8486

8587
Signal::~Signal()
8688
{
89+
stop();
8790
m_buffer->close();
8891
delete m_audio;
8992
delete m_buffer;
@@ -123,26 +126,14 @@ qint32 Signal::getSample(int index)
123126
{
124127
if(m_samples != nullptr && index * 4 >= 0 && index * 4 <= m_samples->size() - 4)
125128
{
126-
//qint32 convertedValue =
127129
return qFromLittleEndian<qint32>(m_samples->constData() + (index * 4));
128-
//m_samples->append(convertedValue, 4);
129130
}
130131
return 0;
131132
}
132133

133134
void Signal::generate()
134135
{
135-
// if(m_samples != nullptr)
136-
// {
137-
// delete m_samples;
138-
// }
139-
140-
141-
142-
143136
int totalSample = qRound(m_duration * m_sampleRate);
144-
//m_samples = new QByteArray(totalSample, NULL);
145-
//output.init();
146137

147138
m_samples->clear();
148139

@@ -154,17 +145,14 @@ void Signal::generate()
154145
for (int i = 0; i < totalSample; i++)
155146
{
156147
qreal x = qreal(i) / m_sampleRate;
157-
//qDebug() << "time: " << x;
158-
//qreal sample = Utils::Clamp(sin(400.0 * x), -1.0, 1.0);
159-
//qreal sample = qSin(400.0 * x * 2 * M_PI);
160148
qreal sample = m_component != nullptr ? Utils::Clamp(m_component->getOutput(x), -1., 1.) : 0.0;
161149

162150
//qDebug() << "time: " << x << " | value: " << sample;
163151
qint32 value = qint32(qRound(INT32_MAX * sample));
164152

165153
char convertedValue[4] = {0};
166154
qToLittleEndian(value, convertedValue);
167-
m_samples->append(convertedValue, 4);//QByteArray::number(convertedValue));
155+
m_samples->append(convertedValue, 4);
168156
}
169157

170158
qDebug() << "Generated!";
@@ -178,21 +166,49 @@ void Signal::exportWAV(QString fileName)
178166
wav.writeToFile(fileName, m_samples);
179167
}
180168

169+
void Signal::loop(bool enable)
170+
{
171+
m_buffer->setLoop(enable);
172+
}
173+
181174
void Signal::play()
182175
{
183-
if(m_buffer->isOpen())
176+
if(m_audio->state() == QAudio::SuspendedState)
184177
{
185-
m_audio->stop();
186-
m_buffer->close();
178+
m_audio->resume();
187179
}
180+
else
181+
{
182+
stop();
183+
toStart();
184+
m_audio->start(m_buffer);
185+
}
186+
}
188187

189-
m_buffer->open(QIODevice::ReadOnly);
190-
m_audio->start(m_buffer);
188+
void Signal::stop()
189+
{
190+
if(m_audio->state() == QAudio::ActiveState)
191+
{
192+
m_audio->stop();
193+
}
191194
}
192195

193196
void Signal::pause()
194197
{
198+
if(m_audio->state() == QAudio::ActiveState)
199+
{
200+
m_audio->suspend();
201+
}
202+
}
203+
204+
void Signal::toStart()
205+
{
206+
m_buffer->reset();
207+
}
195208

209+
void Signal::toEnd()
210+
{
211+
m_buffer->seek(qMax(qint64(0), m_buffer->size() - 1));
196212
}
197213

198214

Signal.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <QAudioOutput>
2828

2929
class Component;
30+
class LoopableBuffer;
3031

3132
class Signal : public QObject
3233
{
@@ -52,9 +53,13 @@ class Signal : public QObject
5253

5354
public slots:
5455
void play();
56+
void stop();
5557
void pause();
58+
void toStart();
59+
void toEnd();
5660
void generate();
5761
void exportWAV(QString fileName);
62+
void loop(bool enable);
5863

5964
private slots:
6065
void handleStateChanged(QAudio::State newState);
@@ -64,7 +69,7 @@ private slots:
6469
qreal m_duration;
6570
QAudioOutput* m_audio;
6671
QByteArray* m_samples;
67-
QBuffer* m_buffer;
72+
LoopableBuffer* m_buffer;
6873
Component* m_component;
6974
};
7075

SoundGenerator.pro

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ SOURCES += \
6464
UI/PinOutputItem.cpp \
6565
UI/PushOrDragButton.cpp \
6666
UI/WaveFormChunk.cpp \
67-
UI/WaveFormView.cpp
67+
UI/WaveFormView.cpp \
68+
LoopableBuffer.cpp
6869

6970
HEADERS += \
7071
Components/AddComponent.h \
@@ -104,7 +105,8 @@ HEADERS += \
104105
UI/PinOutputItem.h \
105106
UI/PushOrDragButton.h \
106107
UI/WaveFormChunk.h \
107-
UI/WaveFormView.h
108+
UI/WaveFormView.h \
109+
LoopableBuffer.h
108110

109111
FORMS += \
110112
UI/mainwindow.ui

UI/MainWindow.cpp

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ MainWindow::MainWindow(QWidget *parent) :
129129

130130
QAction* act_loop = new QAction("Loop", this);
131131
act_loop->setCheckable(true);
132+
connect(act_loop, SIGNAL(triggered(bool)), &m_signal, SLOT(loop(bool)));
132133

133134
// ===== File Edit =====
134135

@@ -193,7 +194,7 @@ MainWindow::MainWindow(QWidget *parent) :
193194

194195
ui->menuAudio->addAction(act_generate);
195196
ui->menuAudio->addAction(act_play);
196-
//ui->menuAudio->addAction(act_loop);
197+
ui->menuAudio->addAction(act_loop);
197198

198199
ui->mainToolBar->clear();
199200
ui->mainToolBar->addAction(act_newFile);
@@ -251,20 +252,10 @@ MainWindow::MainWindow(QWidget *parent) :
251252
m_dirtyable = true;
252253
}
253254

254-
QMenu* MainWindow::getMenu(QString name)
255+
MainWindow::~MainWindow()
255256
{
256-
QMenu* menu = nullptr;
257-
258-
QList<QMenu*> menus = ui->menuBar->findChildren<QMenu*>();
259-
for(int i = 0; i < menus.size() && menu == nullptr; i++)
260-
{
261-
if(menus[i]->title() == name)
262-
{
263-
menu = menus[i];
264-
}
265-
}
266-
267-
return menu;
257+
delete m_scene;
258+
delete ui;
268259
}
269260

270261
void MainWindow::setFileName(QString fileName)
@@ -335,12 +326,6 @@ void MainWindow::mousePressEvent(QMouseEvent *event)
335326
QMainWindow::mousePressEvent(event);
336327
}
337328

338-
MainWindow::~MainWindow()
339-
{
340-
delete m_scene;
341-
delete ui;
342-
}
343-
344329
void MainWindow::newFile()
345330
{
346331
QMessageBox::StandardButton reply = askSaveChanges("creating a new project");

UI/MainWindow.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,9 @@ class MainWindow : public QMainWindow
4141
explicit MainWindow(QWidget *parent = nullptr);
4242
virtual ~MainWindow() override;
4343

44-
QMenu* getMenu(QString name);
4544
QString fileName() { return m_fileName; }
4645
void setFileName(QString fileName);
47-
4846
void readSettings();
49-
5047

5148
protected:
5249
virtual void closeEvent(QCloseEvent* event) override;

0 commit comments

Comments
 (0)