• R/O
  • SSH
  • HTTPS

cadencii: コミット


コミットメタ情報

リビジョン1986 (tree)
日時2012-02-19 07:15:53
作者haruneko24

ログメッセージ

[StandConverter] Qtで音を鳴らす機能を実装.標本化周波数が異なるときの挙動が怪しい.

変更サマリ

差分

--- vConnect/trunk/stand2.0/StandConverter/stand.h (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/stand.h (revision 1986)
@@ -0,0 +1,11 @@
1+#ifndef STAND_H
2+#define STAND_H
3+
4+/*
5+ * use FFTW or SPTK FFT ?
6+ * If you want to use FFTW, define USE_FFTW.
7+ * otherwise, undef USE_FFTW.
8+ */
9+#define USE_FFTW
10+
11+#endif // STAND_H
--- vConnect/trunk/stand2.0/StandConverter/gui/VerticalPianoView.h (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/gui/VerticalPianoView.h (revision 1986)
@@ -0,0 +1,24 @@
1+#ifndef VERTICALPIANOVIEW_H
2+#define VERTICALPIANOVIEW_H
3+
4+#include "HorizontalPianoView.h"
5+
6+namespace stand
7+{
8+namespace gui
9+{
10+
11+class VerticalPianoView : public HorizontalPianoView
12+{
13+ Q_OBJECT
14+public:
15+ explicit VerticalPianoView(QWidget *parent = 0);
16+ ~VerticalPianoView();
17+
18+ void paintEvent(QPaintEvent *e);
19+};
20+
21+}
22+}
23+
24+#endif // VERTICALPIANOVIEW_H
--- vConnect/trunk/stand2.0/StandConverter/gui/HorizontalPianoView.cpp (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/gui/HorizontalPianoView.cpp (revision 1986)
@@ -30,16 +30,20 @@
3030 setMinimumSize(_MINIMUM_WIDTH, _MINIMUM_HEIGHT);
3131 }
3232
33+HorizontalPianoView::~HorizontalPianoView()
34+{
35+}
36+
3337 void HorizontalPianoView::paintEvent(QPaintEvent *e)
3438 {
3539 QPainter p(this);
3640 int begin = (double)(e->rect().x() - 1) / width() * 128;
3741 int end = (double)(e->rect().x() + e->rect().width() + 1) / width() * 128;
42+ p.fillRect(e->rect(), Qt::white);
3843 for(int i = begin; i < end; i++)
3944 {
4045 int x = i / 128.0 * width();
4146 int w = (i + 1) / 128.0 * width() - x;
42- p.fillRect(x, 0, w, height(), Qt::white);
4347 if(_IS_BLACK[i%12])
4448 {
4549 p.fillRect(x, 0, w, height() * 2 / 3, QColor(128, 128, 128));
--- vConnect/trunk/stand2.0/StandConverter/gui/WorldWindow.cpp (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/gui/WorldWindow.cpp (revision 1986)
@@ -3,7 +3,10 @@
33
44 #include "math/World.h"
55 #include "math/SpecgramSet.h"
6-#include "io/WaveFile.h"
6+#include "math/LPCSet.h"
7+#include "../io/WaveFile.h"
8+#include "../io/audio/AudioMixer.h"
9+#include "../io/audio/RawWaveTrack.h"
710
811 #include <QFileInfo>
912 #include <QMessageBox>
@@ -21,11 +24,21 @@
2124 _wave = NULL;
2225
2326 ui->ViewerArea->setWidget(new QLabel(""));
27+
28+ _f.setByteOrder(QAudioFormat::LittleEndian);
29+ _f.setChannels(2);
30+ _f.setCodec("audio/pcm");
31+ _f.setSampleRate(44100);
32+ _f.setSampleSize(16);
33+ _f.setSampleType(QAudioFormat::SignedInt);
34+
35+ _mixer = new stand::io::audio::AudioMixer(_f, this);
2436 }
2537
2638 WorldWindow::~WorldWindow()
2739 {
2840 delete ui;
41+ delete _mixer;
2942 _destroy();
3043 }
3144
@@ -50,13 +63,16 @@
5063 _destroy();
5164 _wave = new stand::io::WaveFile(fileInfo.absoluteFilePath().toLocal8Bit().data());
5265 _s = new stand::math::SpecgramSet();
66+ _lpc = new stand::math::LPCSet();
5367 _w = new stand::math::world::WorldSet();
5468 // 読み込めていたら.
5569 if(_s && _w)
5670 {
5771 _s->compute(_wave->data(), _wave->length());
72+ _lpc->compute(_wave->data(), _wave->length());
5873 _w->compute(_wave->data(), _wave->length());
5974 _imagePowerSpec.set(_s->specgram(), _s->tLen(), _s->fftl() / 2 + 1, _s->samplingFrequency() / 2);
75+ _imageLPCSpec.set(_lpc->specgram(), _lpc->tLen(), _lpc->fftl() / 2 + 1, _lpc->samplingFrequency() / 2);
6076 _imageStarSpec.set(_w->specgram(), _w->tLen(), _w->fftl() / 2 + 1, _w->samplingFrequency() / 2);
6177 changeSpectrumType(true);
6278 }
@@ -73,6 +89,10 @@
7389 {
7490 image = _imagePowerSpec.image();
7591 }
92+ else if(ui->TypeLPC->isChecked())
93+ {
94+ image = _imageLPCSpec.image();
95+ }
7696 else if(ui->TypeStar->isChecked())
7797 {
7898 image = _imageStarSpec.image();
@@ -90,4 +110,24 @@
90110 ui->FileNameEdit->setText(fileName);
91111 }
92112
113+void WorldWindow::playSound()
114+{
115+ if(!_w)
116+ {
117+ return;
118+ }
119+ if(ui->pushButton->text() == "Play")
120+ {
121+ stand::io::audio::RawWaveTrack *t = new stand::io::audio::RawWaveTrack(_wave, _f, this);
122+ _mixer->addTrack(t, 1, 0);
123+ _mixer->start();
124+ ui->pushButton->setText("Stop");
125+ }
126+ else
127+ {
128+ _mixer->stop();
129+ ui->pushButton->setText("Play");
130+ }
131+}
93132
133+
--- vConnect/trunk/stand2.0/StandConverter/gui/HorizontalPianoView.h (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/gui/HorizontalPianoView.h (revision 1986)
@@ -13,10 +13,11 @@
1313 Q_OBJECT
1414 public:
1515 explicit HorizontalPianoView(QWidget *parent = 0);
16+ virtual ~HorizontalPianoView();
1617
17- void paintEvent(QPaintEvent *e);
18+ virtual void paintEvent(QPaintEvent *e);
1819
19-private:
20+protected:
2021 static const int _MINIMUM_WIDTH;
2122 static const int _MINIMUM_HEIGHT;
2223 static const bool _IS_BLACK[12];
--- vConnect/trunk/stand2.0/StandConverter/gui/WorldWindow.h (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/gui/WorldWindow.h (revision 1986)
@@ -2,6 +2,7 @@
22 #define WORLDWINDOW_H
33
44 #include <QMainWindow>
5+#include <QAudioFormat>
56 #include "../io/SpecgramImage.h"
67
78 namespace Ui {
@@ -13,6 +14,7 @@
1314 namespace math
1415 {
1516 class SpecgramSet;
17+class LPCSet;
1618 namespace world
1719 {
1820 class WorldSet;
@@ -21,7 +23,11 @@
2123 namespace io
2224 {
2325 class WaveFile;
26+namespace audio
27+{
28+class AudioMixer;
2429 }
30+}
2531 namespace gui
2632 {
2733
@@ -36,16 +42,22 @@
3642 void beginAnalyze();
3743 void searchDirectory();
3844 void changeSpectrumType(bool b);
45+ void playSound();
3946
4047 private:
4148 void _destroy();
4249 Ui::WorldWindow *ui;
4350 stand::math::SpecgramSet *_s;
51+ stand::math::LPCSet *_lpc;
4452 stand::math::world::WorldSet *_w;
4553 stand::io::WaveFile *_wave;
4654
4755 stand::io::SpecgramImage _imagePowerSpec;
4856 stand::io::SpecgramImage _imageStarSpec;
57+ stand::io::SpecgramImage _imageLPCSpec;
58+
59+ QAudioFormat _f;
60+ stand::io::audio::AudioMixer *_mixer;
4961 };
5062
5163 }
--- vConnect/trunk/stand2.0/StandConverter/gui/VerticalPianoView.cpp (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/gui/VerticalPianoView.cpp (revision 1986)
@@ -0,0 +1,39 @@
1+#include "VerticalPianoView.h"
2+
3+#include <QPainter>
4+#include <QPaintEvent>
5+
6+using namespace stand::gui;
7+
8+VerticalPianoView::VerticalPianoView(QWidget *parent) :
9+ HorizontalPianoView(parent)
10+{
11+ setMinimumSize(_MINIMUM_HEIGHT, _MINIMUM_WIDTH);
12+}
13+
14+VerticalPianoView::~VerticalPianoView()
15+{
16+}
17+
18+void VerticalPianoView::paintEvent(QPaintEvent *e)
19+{
20+ QPainter p(this);
21+ int begin = (double)(e->rect().y() - 1) / height() * 128;
22+ int end = (double)(e->rect().y() + e->rect().height() + 1) / height() * 128;
23+ p.fillRect(e->rect(), Qt::white);
24+ for(int i = begin; i < end; i++)
25+ {
26+ int y = i / 128.0 * height();
27+ int h = (i + 1) / 128.0 * height() - y;
28+ if(_IS_BLACK[(127 - i)%12])
29+ {
30+ p.fillRect(0, y, width() * 2 / 3, h, QColor(128, 128, 128));
31+ }
32+ if((127 - i) == 60)
33+ {
34+ p.fillRect(0, y, width(), h, Qt::red);
35+ }
36+ p.setPen(QColor(192, 192, 192));
37+ p.drawLine(0, y, width(), y);
38+ }
39+}
--- vConnect/trunk/stand2.0/StandConverter/main.cpp (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/main.cpp (revision 1986)
@@ -19,8 +19,8 @@
1919 QTextCodec::setCodecForTr(codec);
2020
2121 // 実行
22- //WorldWindow w;
23- ConverterWindow w;
22+ WorldWindow w;
23+// ConverterWindow w;
2424 w.setWindowTitle("Compressor");
2525 // TranscriberWindow w;
2626 // w.setWindowTitle("Transcriber");
--- vConnect/trunk/stand2.0/StandConverter/io/audio/StreamDevice.h (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/io/audio/StreamDevice.h (revision 1986)
@@ -0,0 +1,56 @@
1+#ifndef STREAMDEVICE_H
2+#define STREAMDEVICE_H
3+
4+#include <QIODevice>
5+#include <QAudioFormat>
6+
7+namespace stand
8+{
9+namespace io
10+{
11+namespace audio
12+{
13+
14+class StreamDevice : public QIODevice
15+{
16+ Q_OBJECT
17+public:
18+ explicit StreamDevice(const QAudioFormat &format, qint64 length, QObject *parent = 0);
19+ ~StreamDevice();
20+
21+ qint64 readData(char *data, qint64 maxlen);
22+ qint64 writeData(const char *data, qint64 len);
23+ qint64 bytesAvailable();
24+
25+ const QAudioFormat &format()
26+ {
27+ return _format;
28+ }
29+
30+ void start();
31+ void stop();
32+
33+signals:
34+ void requireBuffer(qint64);
35+
36+public slots:
37+
38+private:
39+ void _create(const QAudioFormat &format, qint64 length);
40+ void _destroy();
41+
42+ qint16 *_buffer;
43+ qint64 _length;
44+
45+ qint64 _pos;
46+ qint64 _bytesAvailable;
47+ QAudioFormat _format;
48+
49+ const static int MINIMUM_LENGTH;
50+};
51+
52+}
53+}
54+}
55+
56+#endif // STREAMDEVICE_H
--- vConnect/trunk/stand2.0/StandConverter/io/audio/RawWaveTrack.cpp (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/io/audio/RawWaveTrack.cpp (revision 1986)
@@ -0,0 +1,63 @@
1+#include "RawWaveTrack.h"
2+
3+#include "../WaveFile.h"
4+
5+using namespace stand::io::audio;
6+
7+RawWaveTrack::RawWaveTrack(const stand::io::WaveFile *w, const QAudioFormat &format, QObject *parent) :
8+ AudioTrack(format, parent)
9+{
10+ _wave = w;
11+}
12+
13+RawWaveTrack::~RawWaveTrack()
14+{
15+}
16+
17+void RawWaveTrack::generateBuffer(double msPos, double *buffer, qint64 &length)
18+{
19+ qint64 samplePos = msPos / 1000.0 * format.sampleRate();
20+ generateBuffer(samplePos, buffer, length);
21+}
22+
23+void RawWaveTrack::generateBuffer(qint64 samplePos, double *buffer, qint64 &length)
24+{
25+ qint64 bufferPos = 0;
26+ samplePos = samplePos * _wave->header()->samplesPerSecond / format.sampleRate();
27+ if(_wave->header()->samplesPerSecond == format.sampleRate())
28+ {
29+ qint64 endIndex = samplePos + length;
30+ if(endIndex > _wave->length())
31+ {
32+ endIndex = _wave->length();
33+ length = _wave->length() - samplePos;
34+ }
35+ for(int index = samplePos; index < endIndex; index++)
36+ {
37+ for(int i = 0; i < format.channels(); i++)
38+ {
39+ buffer[bufferPos] = _wave->data()[index];
40+ bufferPos++;
41+ }
42+ }
43+ }
44+ // ToDo:: Sampling 周波数変換をマシな式に変えるのは今後の課題.
45+ else
46+ {
47+ qint64 endIndex = samplePos + length * _wave->header()->samplesPerSecond / format.sampleRate();
48+ if(endIndex > _wave->length())
49+ {
50+ endIndex = _wave->length();
51+ length = (_wave->length() - samplePos) * format.sampleRate() / _wave->header()->samplesPerSecond;
52+ }
53+ for(int i = 0; i < length; i++)
54+ {
55+ int index = samplePos + i * _wave->header()->samplesPerSecond / format.sampleRate();
56+ for(int j = 0; j < format.channels(); j++)
57+ {
58+ buffer[bufferPos] = _wave->data()[index];
59+ bufferPos++;
60+ }
61+ }
62+ }
63+}
--- vConnect/trunk/stand2.0/StandConverter/io/audio/AudioTrack.cpp (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/io/audio/AudioTrack.cpp (revision 1986)
@@ -0,0 +1,18 @@
1+#include "AudioTrack.h"
2+
3+using namespace stand::io::audio;
4+
5+AudioTrack::AudioTrack(const QAudioFormat &format, QObject *parent) :
6+ QObject(parent)
7+{
8+ setFormat(format);
9+}
10+
11+AudioTrack::~AudioTrack()
12+{
13+}
14+
15+void AudioTrack::setFormat(const QAudioFormat &format)
16+{
17+ this->format = format;
18+}
--- vConnect/trunk/stand2.0/StandConverter/io/audio/RawWaveTrack.h (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/io/audio/RawWaveTrack.h (revision 1986)
@@ -0,0 +1,33 @@
1+#ifndef RAWWAVETRACK_H
2+#define RAWWAVETRACK_H
3+
4+#include "AudioTrack.h"
5+
6+namespace stand
7+{
8+namespace io
9+{
10+class WaveFile;
11+namespace audio
12+{
13+
14+class RawWaveTrack : public AudioTrack
15+{
16+ Q_OBJECT
17+public:
18+ explicit RawWaveTrack(const stand::io::WaveFile *w, const QAudioFormat &format, QObject *parent);
19+ ~RawWaveTrack();
20+
21+public slots:
22+ void generateBuffer(double msPos, double *buffer, qint64 &length);
23+ void generateBuffer(qint64 samplePos, double *buffer, qint64 &length);
24+
25+private:
26+ const stand::io::WaveFile *_wave;
27+};
28+
29+}
30+}
31+}
32+
33+#endif // RAWWAVETRACK_H
--- vConnect/trunk/stand2.0/StandConverter/io/audio/AudioMixer.cpp (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/io/audio/AudioMixer.cpp (revision 1986)
@@ -0,0 +1,152 @@
1+#include "AudioMixer.h"
2+
3+using namespace stand::io::audio;
4+
5+AudioMixer::AudioMixer(const QAudioFormat &format, QObject *parent)
6+ : QObject(parent)
7+{
8+ _output = NULL;
9+ _device = NULL;
10+ _pos = 0;
11+ setFormat(format);
12+}
13+
14+AudioMixer::~AudioMixer()
15+{
16+ _destroy();
17+}
18+
19+void AudioMixer::_destroy()
20+{
21+ if(_output)
22+ {
23+ _output->disconnect();
24+ }
25+ if(_device)
26+ {
27+ _device->disconnect();
28+ }
29+ delete _device;
30+ delete _output;
31+ _device = NULL;
32+ _output = NULL;
33+ _pos = 0;
34+}
35+
36+void AudioMixer::setFormat(const QAudioFormat &format)
37+{
38+ QAudioDeviceInfo deviceInfo(QAudioDeviceInfo::defaultOutputDevice());
39+ if(!deviceInfo.isFormatSupported(format))
40+ {
41+ qWarning("AudioMixer::setFormat(); // Format not supported.");
42+ this->_format = deviceInfo.nearestFormat(format);
43+ }
44+ else
45+ {
46+ this->_format = format;
47+ }
48+ _destroy();
49+ _output = new QAudioOutput(this->_format, this);
50+ _device = new StreamDevice(this->_format, this->_format.sampleRate(), this);
51+ _device->connect(_device, SIGNAL(requireBuffer(qint64)), this, SLOT(mixTracks(qint64)));
52+ qDebug("AudioMixer::setFormat();");
53+ qDebug(" Format::sampleRate = %d [Hz]", _format.sampleRate());
54+ qDebug(" Format::sampleSize = %d [bits]", _format.sampleSize());
55+ qDebug(" Format::channels = %d", _format.channels());
56+}
57+
58+void AudioMixer::start()
59+{
60+ if(_device && _output)
61+ {
62+ _device->start();
63+ _output->start(_device);
64+ }
65+}
66+
67+void AudioMixer::stop()
68+{
69+ if(_device && _output)
70+ {
71+ _output->stop();
72+ _device->stop();
73+ }
74+ _pos = 0;
75+}
76+
77+void AudioMixer::addTrack(AudioTrack *t, int volume, int pan)
78+{
79+ t->setFormat(_format);
80+ Track track = {t, volume, pan};
81+ _tracks.push_back(track);
82+ // ToDo::connect SIGNAL and SLOT
83+}
84+
85+void AudioMixer::removeTrack(AudioTrack *t)
86+{
87+ for(int i = 0; i < _tracks.size(); i++)
88+ {
89+ if(t == _tracks[i].t)
90+ {
91+ _tracks.remove(i);
92+ return;
93+ }
94+ }
95+}
96+
97+void AudioMixer::mixTracks(qint64 length)
98+{
99+ qint64 bufferLength = length * 8 / _format.sampleSize();
100+ double *readBuffer = new double[bufferLength];
101+ double *mixedBuffer = new double[bufferLength];
102+ char *writeBuffer = new char[length];
103+ for(int i = 0; i < bufferLength; i++)
104+ {
105+ mixedBuffer[i] = 0.0;
106+ }
107+ for(int i = 0; i < _tracks.size(); i++)
108+ {
109+ qint64 sampleLength = bufferLength / _format.channels();
110+ _tracks[i].t->generateBuffer(_pos, readBuffer, sampleLength);
111+ for(int j = 0; j < sampleLength; j++)
112+ {
113+ // 後でボリューム付け足す.
114+ double vol = 1.0;
115+ int index = j * _format.channels();
116+ for(int k = 0; k < _format.channels(); k++, index++)
117+ {
118+ mixedBuffer[index] += readBuffer[index] * vol;
119+ }
120+ }
121+ }
122+ for(qint64 i = 0; i < bufferLength; i++)
123+ {
124+ int index = i * _format.sampleSize() / 8;
125+ if(mixedBuffer[i] < -1.0)
126+ {
127+ mixedBuffer[i] = -1.0;
128+ }
129+ if(mixedBuffer[i] > 1.0)
130+ {
131+ mixedBuffer[i] = 1.0;
132+ }
133+ switch(_format.sampleSize())
134+ {
135+ case 8:
136+ writeBuffer[index] = 127 * mixedBuffer[i];
137+ break;
138+ case 16:
139+ qint16 val = mixedBuffer[i] * ((1 << 15) - 1);
140+ qint8 *p = (qint8 *)(&val);
141+ writeBuffer[index] = p[0];
142+ writeBuffer[index + 1] = p[1];
143+ break;
144+ }
145+ }
146+ // 時間を進める
147+ quint64 writeLength = _device->write(writeBuffer, length);
148+ _pos += writeLength * 8 / _format.sampleSize() / _format.channels();
149+ delete[] readBuffer;
150+ delete[] mixedBuffer;
151+ delete[] writeBuffer;
152+}
--- vConnect/trunk/stand2.0/StandConverter/io/audio/AudioTrack.h (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/io/audio/AudioTrack.h (revision 1986)
@@ -0,0 +1,34 @@
1+#ifndef AUDIOTRACK_H
2+#define AUDIOTRACK_H
3+
4+#include "StreamDevice.h"
5+
6+namespace stand
7+{
8+namespace io
9+{
10+namespace audio
11+{
12+
13+class AudioTrack : public QObject
14+{
15+ Q_OBJECT
16+public:
17+ explicit AudioTrack(const QAudioFormat &format, QObject *parent = 0);
18+ virtual ~AudioTrack();
19+
20+public slots:
21+ virtual void generateBuffer(double msPos, double *buffer, qint64 &length) = 0;
22+ virtual void generateBuffer(qint64 samplePos, double *buffer, qint64 &length) = 0;
23+
24+ void setFormat(const QAudioFormat &format);
25+
26+protected:
27+ QAudioFormat format;
28+};
29+
30+}
31+}
32+}
33+
34+#endif // AUDIOTRACK_H
--- vConnect/trunk/stand2.0/StandConverter/io/audio/StreamDevice.cpp (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/io/audio/StreamDevice.cpp (revision 1986)
@@ -0,0 +1,104 @@
1+#include "StreamDevice.h"
2+
3+using namespace stand::io::audio;
4+
5+// 最小のバッファ長.短いかも知らん.
6+const int StreamDevice::MINIMUM_LENGTH = 4096;
7+
8+StreamDevice::StreamDevice(const QAudioFormat &format, qint64 length, QObject *parent) :
9+ QIODevice(parent)
10+{
11+ if(length < MINIMUM_LENGTH)
12+ {
13+ length = MINIMUM_LENGTH;
14+ }
15+ _buffer = NULL;
16+ _create(format, length);
17+}
18+
19+StreamDevice::~StreamDevice()
20+{
21+ _destroy();
22+}
23+
24+void StreamDevice::_destroy()
25+{
26+ delete[] _buffer;
27+ _length = 0;
28+ _bytesAvailable = 0;
29+ _pos = 0;
30+}
31+
32+void StreamDevice::_create(const QAudioFormat &format, qint64 length)
33+{
34+ if(length <= 0)
35+ {
36+ return;
37+ }
38+ _destroy();
39+ _length = length * format.channels() * format.sampleSize() / 8;
40+ _buffer = new qint16[_length];
41+ _pos = 0;
42+ for(int i = 0; i < _length; i++)
43+ {
44+ _buffer[i] = 0;
45+ }
46+ _format = format;
47+}
48+
49+void StreamDevice::start()
50+{
51+ open(QIODevice::ReadWrite);
52+}
53+
54+void StreamDevice::stop()
55+{
56+ close();
57+ _pos = 0;
58+ _bytesAvailable = 0;
59+}
60+
61+qint64 StreamDevice::readData(char *data, qint64 maxlen)
62+{
63+ if(_bytesAvailable <= _length / 4)
64+ {
65+ emit requireBuffer(_length - _bytesAvailable);
66+ }
67+ int blockSize = _format.sampleSize() / 8 * _format.channels();
68+ maxlen = (maxlen / blockSize) * blockSize;
69+ if(maxlen > _bytesAvailable)
70+ {
71+ maxlen = _bytesAvailable;
72+ }
73+ for(int i = 0; i < maxlen; i++)
74+ {
75+ data[i] = _buffer[(_pos + i) % _length];
76+ }
77+
78+ _pos = (_pos + maxlen) % _length;
79+ _bytesAvailable -= maxlen;
80+
81+ return maxlen;
82+}
83+
84+qint64 StreamDevice::writeData(const char *data, qint64 len)
85+{
86+ int blockSize = _format.sampleSize() / 8 * _format.channels();
87+ len = (len / blockSize) * blockSize;
88+ if(len > (_length - _bytesAvailable))
89+ {
90+ len = (_length - _bytesAvailable);
91+ }
92+ int startAt = _pos + _bytesAvailable;
93+ for(int i = 0; i < len; i++)
94+ {
95+ _buffer[(startAt+ i) % _length] = data[i];
96+ }
97+ _bytesAvailable += len;
98+ return len;
99+}
100+
101+qint64 StreamDevice::bytesAvailable()
102+{
103+ return _bytesAvailable;
104+}
--- vConnect/trunk/stand2.0/StandConverter/io/audio/AudioMixer.h (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/io/audio/AudioMixer.h (revision 1986)
@@ -0,0 +1,60 @@
1+#ifndef AUDIOMIXER_H
2+#define AUDIOMIXER_H
3+
4+#include <QObject>
5+#include <QAudioOutput>
6+#include <QVector>
7+
8+#include "StreamDevice.h"
9+#include "AudioTrack.h"
10+
11+namespace stand
12+{
13+namespace io
14+{
15+namespace audio
16+{
17+
18+class AudioMixer : public QObject
19+{
20+ Q_OBJECT
21+public:
22+ explicit AudioMixer(const QAudioFormat &format, QObject *parent = 0);
23+ ~AudioMixer();
24+
25+ void addTrack(AudioTrack *t, int volume, int pan);
26+ void removeTrack(AudioTrack *t);
27+
28+ void clear();
29+
30+ void setFormat(const QAudioFormat &format);
31+ struct Track
32+ {
33+ AudioTrack *t;
34+ int volume;
35+ int pan;
36+ };
37+
38+signals:
39+ void errorEmpty();
40+
41+
42+public slots:
43+ void start();
44+ void stop();
45+ void mixTracks(qint64 length);
46+
47+private:
48+ void _destroy();
49+ qint64 _pos;
50+ QAudioFormat _format;
51+ QVector<Track> _tracks;
52+ QAudioOutput *_output;
53+ StreamDevice *_device;
54+};
55+
56+}
57+}
58+}
59+
60+#endif // AUDIOMIXER_H
--- vConnect/trunk/stand2.0/StandConverter/math/LPCSet.h (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/math/LPCSet.h (revision 1986)
@@ -0,0 +1,44 @@
1+/*!
2+ * @file LPCSet.h
3+ * @brief LPCSet supports LPC analysis,
4+ * and keeps data as specgram.
5+ * These functions are redistribution of SPTK.
6+ * Original source codes are below.
7+ * http://sp-tk.sourceforge.net/
8+ * @author HAL@shurabaP
9+ */
10+#ifndef LPCSET_H
11+#define LPCSET_H
12+
13+#include "SpecgramSet.h"
14+#include "FFTSet.h"
15+
16+namespace stand
17+{
18+namespace math
19+{
20+
21+class LPCSet : public SpecgramSet
22+{
23+public:
24+ explicit LPCSet(const SpecgramSetting *s = &SPECGRAM_DEFAULT_SETTING);
25+ ~LPCSet();
26+
27+ void compute(const double *x, int xLen, const SpecgramSetting *s = NULL);
28+
29+ int dimension();
30+ void setDimension(int d);
31+
32+ static void lpcToCepstrum(fftw_complex *c, int cLen, const double *a, int aLen);
33+ static void lpc(double *a, int aLen, const double *y, int yLen);
34+private:
35+ int _dim;
36+
37+ const static double EPSILON;
38+ const static int DEFAULT_DIMENSION;
39+};
40+
41+}
42+}
43+
44+#endif // LPCSET_H
--- vConnect/trunk/stand2.0/StandConverter/math/FFTSet.h (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/math/FFTSet.h (revision 1986)
@@ -16,7 +16,13 @@
1616 #define FFTSET_H
1717
1818 #include <QMutex>
19+#include "../stand.h"
20+
21+#ifdef USE_FFTW
1922 #include <fftw3.h>
23+#else
24+typedef double fftw_complex[2];
25+#endif
2026
2127 namespace stand
2228 {
@@ -45,6 +51,7 @@
4551
4652 void setFFT(unsigned int length, FFTtype type);
4753
54+
4855 unsigned int length() const
4956 {
5057 return _length;
@@ -62,20 +69,33 @@
6269
6370 void execute()
6471 {
72+#ifdef USE_FFTW
6573 fftw_execute(_plan);
74+#else
75+ _func((double *)_in, (double *)_out, _length);
76+#endif
6677 }
6778
6879 private:
6980 void _destroy();
7081
71- static QMutex _mutex;
72-
7382 FFTtype _type;
7483 void *_in;
7584 void *_out;
7685 unsigned int _length;
7786
87+#ifdef USE_FFTW
7888 fftw_plan _plan;
89+ static QMutex _mutex;
90+#else
91+ int (*_func)(double *, double *, int);
92+ static int sptk_fft(double *x, double *y, int m);
93+ static int sptk_fftr(double *x, double *y, int m);
94+ static int sptk_ifft(double *x, double *y, int m);
95+ static int sptk_ifftr(double *x, double *y, int m);
96+ double *_sineTable;
97+ int _sineTableSize;
98+#endif
7999 };
80100
81101 }
--- vConnect/trunk/stand2.0/StandConverter/math/WorldSet.cpp (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/math/WorldSet.cpp (revision 1986)
@@ -52,19 +52,18 @@
5252 {
5353 return;
5454 }
55- int tLen = samplesForDio(s->fs, xLen, s->framePeriod);
56- int fftl = FFTLengthForStar(s->fs);
57- _create(tLen, fftl);
5855
59- if(!s)
56+ if(s)
6057 {
61- s = &SPECGRAM_DEFAULT_SETTING;
58+ _setting = *s;
6259 }
63- _setting = *s;
60+ int tLen = samplesForDio(_setting.fs, xLen, _setting.framePeriod);
61+ int fftl = FFTLengthForStar(_setting.fs);
62+ _create(tLen, fftl);
6463
65- dio(x, xLen, s->fs, s->framePeriod, _t, _f0);
66- star(x, xLen, s->fs, _t, _f0, _specgram);
67- platinum(x, xLen, s->fs, _t, _f0, _specgram, _residual);
64+ dio(x, xLen, _setting.fs, _setting.framePeriod, _t, _f0);
65+ star(x, xLen, _setting.fs, _t, _f0, _specgram);
66+ platinum(x, xLen, _setting.fs, _t, _f0, _specgram, _residual);
6867 }
6968
7069 double *WorldSet::spectrumAt(double t)
--- vConnect/trunk/stand2.0/StandConverter/math/MathSet.cpp (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/math/MathSet.cpp (revision 1986)
@@ -17,3 +17,15 @@
1717 double r = x - (double)t;
1818 return ( p[t] * ( 1.0 - r ) + p[t+1] * r );
1919 }
20+
21+void stand::math::autoCorrelation(double *a, int aLen, const double *y, int yLen)
22+{
23+ for(int i = 0; i < aLen; i++)
24+ {
25+ a[i] = 0;
26+ for(int j = 0; j < yLen -i; j++)
27+ {
28+ a[i] += y[j] * y[j + i];
29+ }
30+ }
31+}
--- vConnect/trunk/stand2.0/StandConverter/math/WorldSet.h (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/math/WorldSet.h (revision 1986)
@@ -38,7 +38,7 @@
3838
3939 ~WorldSet();
4040
41- void compute(const double *x, int xLen, const SpecgramSet::SpecgramSetting *s = &SPECGRAM_DEFAULT_SETTING);
41+ void compute(const double *x, int xLen, const SpecgramSet::SpecgramSetting *s = NULL);
4242
4343
4444 double *spectrumAt(int i);
--- vConnect/trunk/stand2.0/StandConverter/math/MathSet.h (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/math/MathSet.h (revision 1986)
@@ -29,6 +29,15 @@
2929 /// <returns>配列の中間値を返します.</returns>
3030 double interpolateArray(double x, const double *p);
3131
32+/*!
33+ * @brief 自己相関関数を計算する.
34+ * @param[out] a 計算結果.
35+ * @param[in] aLen 自己相関関数の長さ
36+ * @param[in] y 信号
37+ * @param[in] yLen 信号長
38+ */
39+void autoCorrelation(double *a, int aLen, const double *y, int yLen);
40+
3241 }
3342 }
3443
--- vConnect/trunk/stand2.0/StandConverter/math/SpecgramSet.cpp (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/math/SpecgramSet.cpp (revision 1986)
@@ -92,7 +92,7 @@
9292 {
9393 _setting = *s;
9494 }
95- int tLen = (double)xLen / (double)s->fs * 1000.0 / s->framePeriod + 1;
95+ int tLen = (double)xLen / (double)_setting.fs * 1000.0 / _setting.framePeriod + 1;
9696 _destroySpecgram();
9797 _createSpecgram(tLen, 2048);
9898
@@ -102,7 +102,7 @@
102102
103103 for(int i = 0; i < tLen; i++)
104104 {
105- int begin = i * s->framePeriod / 1000.0 * (double)s->fs - _fftl / 2;
105+ int begin = i * _setting.framePeriod / 1000.0 * (double)_setting.fs - _fftl / 2;
106106 // 時刻 t の前後 1024 点ずつを取り出す
107107 for(int j = begin, k = 0; k < _fftl; j++, k++)
108108 {
--- vConnect/trunk/stand2.0/StandConverter/math/SpecgramSet.h (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/math/SpecgramSet.h (revision 1986)
@@ -15,6 +15,10 @@
1515 #ifndef SPECGRAMSET_H
1616 #define SPECGRAMSET_H
1717
18+#ifndef NULL
19+#define NULL 0
20+#endif
21+
1822 namespace stand
1923 {
2024 namespace math
@@ -35,7 +39,7 @@
3539 explicit SpecgramSet(int tLen, int fftl, const SpecgramSetting *s = & SPECGRAM_DEFAULT_SETTING);
3640 virtual ~SpecgramSet();
3741
38- virtual void compute(const double *x, int xLen, const SpecgramSetting *s = &SPECGRAM_DEFAULT_SETTING);
42+ virtual void compute(const double *x, int xLen, const SpecgramSetting *s = NULL);
3943 double *spectrumAt(int i);
4044
4145 double **specgram()
--- vConnect/trunk/stand2.0/StandConverter/math/LPCSet.cpp (nonexistent)
+++ vConnect/trunk/stand2.0/StandConverter/math/LPCSet.cpp (revision 1986)
@@ -0,0 +1,174 @@
1+/*!
2+ * @file LPCSet.cpp
3+ * @brief LPCSet supports LPC analysis,
4+ * and keeps data as specgram.
5+ * These functions are redistribution of SPTK.
6+ * Original source codes are below.
7+ * http://sp-tk.sourceforge.net/
8+ * @author HAL@shurabaP
9+ */
10+#include "LPCSet.h"
11+#include "MathSet.h"
12+#include "FFTSet.h"
13+
14+#include <math.h>
15+#include <float.h>
16+
17+using namespace stand::math;
18+
19+#ifdef WIN32
20+#define isnan(x) _isnan(x)
21+#endif
22+
23+const double LPCSet::EPSILON = 1.0e-6;
24+const int LPCSet::DEFAULT_DIMENSION = 64;
25+
26+LPCSet::LPCSet(const SpecgramSetting *s) :
27+ SpecgramSet(s)
28+{
29+ _dim = DEFAULT_DIMENSION;
30+}
31+
32+LPCSet::~LPCSet()
33+{
34+}
35+
36+void LPCSet::compute(const double *x, int xLen, const SpecgramSetting *s)
37+{
38+ int aLen = 32;
39+ if(!x || xLen <= 0)
40+ {
41+ return;
42+ }
43+ if(s)
44+ {
45+ _setting = *s;
46+ }
47+
48+ _tLen = (double)xLen / _setting.fs * 1000.0 / _setting.framePeriod + 1;
49+ _fftl = 2048;
50+ _createSpecgram(_tLen, _fftl);
51+
52+ FFTSet inverse(_fftl, FFTSet::FFTW_C2R);
53+ fftw_complex *in = (fftw_complex *)inverse.in();
54+ double *out = (double *)inverse.out();
55+ double *a = new double[aLen];
56+
57+ for(int t = 0; t < _tLen; t++)
58+ {
59+ int begin = t * _setting.framePeriod / 1000.0 * _setting.fs - _fftl / 2;
60+ for(int j = 0; j < _fftl; j++)
61+ {
62+ int index = begin + j;
63+ if(index < 0)
64+ {
65+ index = 0;
66+ }
67+ else if(index >= xLen)
68+ {
69+ index = xLen - 1;
70+ }
71+ out[j] = x[index] * sin(PI * j / (double)_fftl);
72+ }
73+ lpc(a, aLen, out, _fftl);
74+ lpcToCepstrum(in, _fftl / 2 + 1, a, aLen);
75+ inverse.execute();
76+ for(int j = 0; j < _fftl / 2 + 1; j++)
77+ {
78+ _specgram[t][j] = exp(out[j]);
79+ }
80+ }
81+ delete[] a;
82+}
83+
84+int LPCSet::dimension()
85+{
86+ return _dim;
87+}
88+
89+void LPCSet::setDimension(int d)
90+{
91+ if(d <= 0)
92+ {
93+ return;
94+ }
95+ _dim = d;
96+}
97+
98+void LPCSet::lpc(double *a, int aLen, const double *y, int yLen)
99+{
100+ double *r = new double[aLen + 1];
101+ double *c = new double[aLen + 1];
102+
103+ // 自己相関関数を計算する
104+ autoCorrelation(r, aLen + 1, y, yLen);
105+
106+ // LPC 係数を求める.
107+ double mue;
108+ double rmd = r[0];
109+ for(int i = 0; i < aLen; i++)
110+ {
111+ c[i] = 0;
112+ }
113+ a[0] = 0.0;
114+ for(int i = 1; i < aLen; i++)
115+ {
116+ mue = -r[i];
117+ for(int j = 1; j < i; j++)
118+ {
119+ mue -= c[j] * r[i - j];
120+ }
121+ mue = mue / rmd;
122+
123+ for(int j = 1; j < i; j++)
124+ {
125+ a[j] = c[j] + mue * c[i - j];
126+ }
127+ a[i] = mue;
128+ rmd = (1.0 - mue * mue) * rmd;
129+
130+ if(fabs(rmd) < EPSILON || isnan(rmd))
131+ {
132+ qDebug("LPCSet::lpc(); // Abnormal signal");
133+ for(int j = 0; j < aLen; i++)
134+ {
135+ a[i] = 1.0;
136+ return;
137+ }
138+ }
139+ if(fabs(mue) >= 1.0)
140+ {
141+ qDebug("LPCSet::lpc(); // Unstable lpc");
142+ }
143+ for(int j = 0; j <= i; j++)
144+ {
145+ c[j] = a[j];
146+ }
147+ }
148+ a[0] = sqrt(rmd);
149+
150+ delete[] c;
151+ delete[] r;
152+}
153+
154+void LPCSet::lpcToCepstrum(fftw_complex *c, int cLen, const double *a, int aLen)
155+{
156+ c[0][0] = log(a[0]);
157+ c[1][0] = -a[1];
158+ c[0][1] = c[1][1] = 0.0;
159+ for(int k = 2; k < cLen; k++)
160+ {
161+ int upper = (k > cLen) ? cLen + 1 : k;
162+ double d = 0;
163+ for(int i = (k > aLen) ? k - aLen : 1; i < upper; i++)
164+ {
165+ d += i * c[i][0] * a[k - i];
166+ }
167+ c[k][0] = -d / k;
168+ c[k][1] = 0.0;
169+ if(k <= aLen)
170+ {
171+ c[k][0] -= a[k];
172+ }
173+ }
174+}
--- vConnect/trunk/stand2.0/StandConverter/math/FFTSet.cpp (revision 1985)
+++ vConnect/trunk/stand2.0/StandConverter/math/FFTSet.cpp (revision 1986)
@@ -13,17 +13,26 @@
1313 * @author HAL@shurabaP
1414 */
1515 #include "FFTSet.h"
16+#include "World.h"
1617
1718 using namespace stand::math;
1819
20+#ifdef USE_FFTW
1921 QMutex FFTSet::_mutex;
22+#endif
2023
2124 FFTSet::FFTSet(unsigned int l, FFTtype type)
2225 {
2326 _length = 0;
2427 _in = _out = NULL;
28+#ifdef USE_FFTW
2529 _plan = NULL;
2630 setFFT(l, type);
31+#else
32+ _sineTable = NULL;
33+ _sineTableSize = 0;
34+ setFFT(l, type);
35+#endif
2736 }
2837
2938 FFTSet::~FFTSet()
@@ -37,6 +46,8 @@
3746 delete[] _out;
3847 _in = _out = NULL;
3948 _length = 0;
49+
50+#ifdef USE_FFTW
4051 if(_plan)
4152 {
4253 _mutex.lock();
@@ -44,8 +55,14 @@
4455 _mutex.unlock();
4556 }
4657 _plan = NULL;
58+#else
59+ delete[] _sineTable;
60+ _sineTable = NULL;
61+ _sineTableSize = 0;
62+#endif
4763 }
4864
65+#ifdef USE_FFTW
4966 void FFTSet::setFFT(unsigned int l, FFTtype type)
5067 {
5168 _destroy();
@@ -100,3 +117,125 @@
100117 break;
101118 }
102119 }
120+#else
121+
122+int stand::math::sptkCheckm(int m)
123+{
124+ int k;
125+
126+ for (k = 4; k <= m; k <<= 1) {
127+ if (k == m)
128+ return (0);
129+ }
130+
131+ return (-1);
132+}
133+
134+void FFTSet::setFFT(unsigned int length, FFTtype type)
135+{
136+ _destroy();
137+ if(length == 0)
138+ {
139+ return;
140+ }
141+ _length = length;
142+ switch(_type = type)
143+ {
144+ case FFTW_R2C:
145+ _in = (void *)(new double[length]);
146+ _out = (void *)(new fftw_complex[length]);
147+ _func = FFTSet::sptk_fftr;
148+ break;
149+ case FFTW_C2R:
150+ _in = (void *)(new fftw_complex[length]);
151+ _out = (void *)(new double[length]);
152+ _func = FFTSet::sptk_fft;
153+ break;
154+ case FFTW_C2C_FORWARD:
155+ _in = (void *)(new fftw_complex[length]);
156+ _out = (void *)(new fftw_complex[length]);
157+ _func = FFTSet::sptk_fft;
158+ break;
159+ case FFTW_C2C_BACKWARD:
160+ _in = (void *)(new fftw_complex[length]);
161+ _out = (void *)(new fftw_complex[length]);
162+ _func = FFTSet::sptk_ifft;
163+ break;
164+ }
165+
166+}
167+
168+int FFTSet::sptk_ifft(double *x, double *y, int m)
169+{
170+ int retval = sptk_fft(x, y, m);
171+
172+ if(retval == -1)
173+ {
174+ return retval;
175+ }
176+ for(int i = 0; i < m; i++)
177+ {
178+ x[i] /= m;
179+ y[i] /= m;
180+ }
181+ return 0;
182+}
183+
184+int FFTSet::sptk_ifftr(double *x, double *y, int m)
185+{
186+ int retval = sptk_fftr(x, y, m);
187+ if(retval == -1)
188+ {
189+ return retval;
190+ }
191+ for(int i = 0; i < m; i++)
192+ {
193+
194+ }
195+}
196+
197+int FFTSet::sptk_fftr(double *x, double *y, int m)
198+{
199+ if(sptk_fft(x, y, m / 2) == -1)
200+ {
201+ return -1;
202+ }
203+ int i, j;
204+ int maxfftsize = m;
205+ int mv2 = m / 2;
206+ int n = maxfftsize / m;
207+ double *sinp = _sineTable;
208+ double *cosp = _sineTable + maxfftsize / 4;
209+
210+ double *xp = x;
211+ double *yp = y;
212+ double *xq = xp + m;
213+ double *yq = yp + m;
214+ *(xp + mv2) = *xp - *yp;
215+ *xp = *xp + *yp;
216+ *(yp + mv2) = *yp = 0;
217+
218+ for (i = mv2, j = mv2 - 2; --i; j -= 2) {
219+ ++xp;
220+ ++yp;
221+ sinp += n;
222+ cosp += n;
223+ yt = *yp + *(yp + j);
224+ xt = *xp - *(xp + j);
225+ *(--xq) = (*xp + *(xp + j) + *cosp * yt - *sinp * xt) * 0.5;
226+ *(--yq) = (*(yp + j) - *yp + *sinp * yt + *cosp * xt) * 0.5;
227+ }
228+
229+ xp = x + 1;
230+ yp = y + 1;
231+ xq = x + m;
232+ yq = y + m;
233+
234+ for (i = mv2; --i;) {
235+ *xp++ = *(--xq);
236+ *yp++ = -(*(--yq));
237+ }
238+ return 0;
239+}
240+
241+#endif
旧リポジトリブラウザで表示