QT 快速傅里叶绘制QMediaPlayer频谱
时间: 2023-10-14 09:11:27 浏览: 184
Qt绘制频谱
4星 · 用户满意度95%
在Qt中,可以通过QMediaPlayer和QAudioProbe来获取音频数据,并使用快速傅里叶变换(FFT)算法将其转换为频谱数据。下面是一个简单的示例代码,用于绘制QMediaPlayer的频谱图:
```cpp
#include <QApplication>
#include <QMainWindow>
#include <QMediaPlayer>
#include <QAudioProbe>
#include <QAudioBuffer>
#include <QPainter>
#include <QTimer>
class SpectrogramWidget : public QWidget
{
public:
SpectrogramWidget(QWidget *parent = nullptr)
: QWidget(parent)
, m_audioProbe(new QAudioProbe(this))
{
connect(m_audioProbe, &QAudioProbe::audioBufferProbed,
this, &SpectrogramWidget::processBuffer);
m_audioProbe->setSource(nullptr);
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout,
this, &SpectrogramWidget::update);
timer->start(50); // 更新频率为 20Hz
}
protected:
void paintEvent(QPaintEvent *event) override
{
QPainter painter(this);
// 绘制背景
painter.fillRect(event->rect(), Qt::black);
// 绘制频谱
painter.setPen(Qt::green);
for (int i = 0; i < m_spectrum.size(); ++i) {
int x = i * width() / m_spectrum.size();
int y = height() - m_spectrum[i] * height();
painter.drawLine(x, height(), x, y);
}
}
private:
void processBuffer(const QAudioBuffer &buffer)
{
if (buffer.format().channelCount() != 1)
return;
const qint16 *data = buffer.constData<qint16>();
int sampleCount = buffer.frameCount();
// 计算FFT
QVector<double> spectrum(sampleCount);
for (int i = 0; i < sampleCount; ++i) {
spectrum[i] = data[i] / 32768.0;
}
fft(spectrum);
// 转换为频谱
QVector<double> freqs(sampleCount / 2);
for (int i = 0; i < sampleCount / 2; ++i) {
double re = spectrum[2 * i];
double im = spectrum[2 * i + 1];
freqs[i] = sqrt(re * re + im * im);
}
m_spectrum = freqs;
}
void fft(QVector<double> &data)
{
int n = data.size();
if (n <= 1)
return;
QVector<double> even(n / 2);
QVector<double> odd(n / 2);
for (int i = 0; i < n / 2; ++i) {
even[i] = data[2 * i];
odd[i] = data[2 * i + 1];
}
fft(even);
fft(odd);
for (int i = 0; i < n / 2; ++i) {
double re = even[i];
double im = odd[i] * exp(-2 * M_PI * i / n * I);
data[i] = re + im;
data[i + n / 2] = re - im;
}
}
QAudioProbe *m_audioProbe;
QVector<double> m_spectrum;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
SpectrogramWidget *widget = new SpectrogramWidget(&window);
window.setCentralWidget(widget);
window.show();
QMediaPlayer *player = new QMediaPlayer(&window);
player->setMedia(QUrl::fromLocalFile("music.mp3"));
player->setVolume(50);
player->play();
widget->m_audioProbe->setSource(player);
return app.exec();
}
```
在上面的代码中,SpectrogramWidget继承自QWidget,并使用QAudioProbe来获取音频数据。在paintEvent函数中,使用QPainter绘制背景和频谱图。在processBuffer函数中,实现FFT算法并将其应用于音频数据。在fft函数中,实现递归FFT算法。update函数用于更新频谱图的显示。最后,在main函数中,创建一个QMediaPlayer对象并将其与QAudioProbe和SpectrogramWidget相关联。
阅读全文