qt 频谱 音乐播放器

先看效果

录制_2022_08_11_14_37_25_628

在网上找了一圈, 好多人写的资料敝竹自珍,还要收费真是无语。还有些需要用第三方库,真是没有必要。qt可以直接实现这些功能

音乐播放器的实现我就不贴了, 网上好多例子,我主要写下频谱的实现。

1. 获取波形数据

    // 音频获取
    probe = new QAudioProbe(this);
    connect(probe, &QAudioProbe::audioBufferProbed, this,&MainWindow::processBuffer);
    probe->setSource(music_player); // 传入音乐播放器



void MainWindow::processBuffer(const QAudioBuffer &buffer)
{
  if(buffer.sampleCount() / 2 > 0)
      ui->label_boxingtu->drawAudioPxm(buffer);
}

2.  主界面上增加Qlabel 控件,新增一个类MyQLabel , 继承QLabel,做控件提升。

3. 在 MyQLabel 类中, 重写 paintEvent 。

MyQLabel::MyQLabel(QWidget *parent):QLabel(parent)
{
    graphicStyle = GraphicStyle::PingPu;
}

void MyQLabel::drawAudioPxm(const QAudioBuffer &buffer)
{
   m_buffer = buffer;

   update();
}

void MyQLabel::paintEvent(QPaintEvent *ev)
{
    int count = m_buffer.sampleCount() / 2;
    if(count <= 0)
        return;

    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing);  // 抗锯齿

    if(graphicStyle == GraphicStyle::PingPu )
        drawWaveformFigure(painter);
    else if (graphicStyle == GraphicStyle::ZhuZhuangTu)
        drawHistogram(painter);
    else if (graphicStyle == GraphicStyle::ZhengTi)
        drawOverallVolatility(painter);
}

// 频谱效果
void MyQLabel::drawWaveformFigure(QPainter &painter)
{
    const qint32 *data = m_buffer.constData<qint32>();
    int count = m_buffer.sampleCount() / 2;

    QPen pen = painter.pen();
    pen.setWidth(1);
    pen.setColor(Qt::blue);
    painter.setPen(pen);

    float xScale = (float)this->width() / count;
    float center = (float)this->height() / 2;
    for(int i = 1; i < count; i++)
    {
        painter.drawLine(
                    (i - 1) * xScale,
                    center + ((float)(data[i-1]) / INT_MAX * center),
                    i * xScale,
                    center + ((float)(data[i]) / INT_MAX * center) );

    }
}

//  柱状图效果
void MyQLabel::drawHistogram(QPainter &painter)
{
     const qint32 *data = m_buffer.constData<qint32>();
     int count = m_buffer.sampleCount() / 2;

     int step = count / 50;
     QVector <qreal> vecData;
     for(int i = 0; i < 51; i++)
     {
         int number = 0;
         qreal sum = 0;
         for (int j = 0; j < step; j++)
         {
             if(i * 50 + j >= count)
                 break;

             qreal value = (qreal)(data[i * 50 + j]) / INT_MAX * this->height();

             if(value > 0)
             {
                 sum += value;
                 number++;
             }
         }

         if(number > 0)
             vecData.push_back(sum / number);
         else
             vecData.push_back(0);
     }

     qreal rectangleWidth = (qreal)this->width() / vecData.count();   // 图形加间隙的宽度
     qreal clearanceWidth = rectangleWidth / 4;    // 间隙宽度
     qreal shapeWidth = rectangleWidth - clearanceWidth; // 图形宽度

     QPen pen = painter.pen();
     pen.setWidth(shapeWidth);
     pen.setColor(Qt::red);
     painter.setPen(pen);

     for(int i = 0; i < vecData.count(); i++)
     {
         painter.drawLine(
                     i * rectangleWidth + rectangleWidth* 0.5,
                     this->height() - vecData[i],
                     i * rectangleWidth + rectangleWidth* 0.5,
                     this->height());

     }
}

// 整体效果
void MyQLabel::drawOverallVolatility(QPainter &painter)
{
    const qint32 *data = m_buffer.constData<qint32>();
    int count = m_buffer.sampleCount() / 2;

    qreal maxValue = 0;  // 取最大值
    for(int i = 1; i < count; i++)
    {
        qreal value = (qreal)(data[i]) / INT_MAX * this->height();
        maxValue = qMax(value,maxValue);
    }

    qreal rectangleWidth = (qreal)this->width() / 10;   // 图形加间隙的宽度
    qreal clearanceWidth = rectangleWidth / 4;    // 间隙宽度
    qreal shapeWidth = rectangleWidth - clearanceWidth; // 图形宽度

    for(int i = 0; i < 10; i++)
    {
        QRect rect(i * rectangleWidth + clearanceWidth*0.5, 0, shapeWidth, this->height());

        QLinearGradient gradient(rect.x(), rect.y(),rect.x(), rect.y() + rect.height());
        gradient.setColorAt(0.0, Qt::red);
        gradient.setColorAt(0.3, Qt::green);
        gradient.setColorAt(0.6, Qt::yellow);
        gradient.setColorAt(1.0, Qt::blue);

        painter.setPen(Qt::NoPen);
        gradient.setSpread(QGradient::ReflectSpread);
        painter.setBrush(gradient); // QBrush(const QGradient &gradient)
        painter.drawRect(rect);
        
        // 去掉顶部
        QBrush brush = painter.brush();
        brush.setStyle(Qt::SolidPattern);
        brush.setColor(Qt::white);
        painter.setBrush(brush);

        painter.drawRect(i * rectangleWidth + clearanceWidth*0.5, 0, shapeWidth, this->height() - maxValue);
    }
}

void MyQLabel::setGraphicStyle(const GraphicStyle &value)
{
    graphicStyle = value;
}

最近好多人照着我这个写完后运行报错,我在网上也查了下,应该是QT版本的兼容问题,下面是我用的 QT 版本信息, 上面的代码以及发的源码都是我自己写的,运行后没问题才发出来。

需要源码的,把邮箱留下,我看到后会给你发的。

 

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 40
    评论
QT是一种跨平台的应用程序开发框架,用于创建高质量的图形用户界面和功能强大的应用程序。一个频谱音乐播放器可以利用QT框架来实现。 频谱指的是音乐的声波频谱图,显示了不同频率的声音强度。在一个频谱音乐播放器中,音乐可以通过QT播放器的功能进行播放,并且配合频谱图实时展示音乐的频谱变化。 首先,这个音乐播放器需要一个用户界面,可以使用QT框架提供的UI组件来创建一个美观且易于操作的界面。这包括播放/暂停按钮、调整音量的滑块、进度条和显示当前播放状态的标签。 其次,需要一个音乐播放器功能,使用QT的多媒体模块来实现。该功能包括播放、暂停、停止、调整音量等基本音乐控制功能,并且可以加载、播放各种音频格式文件。 最核心的部分是频谱图的实时展示。构建一个频谱音乐播放器需要对音频进行实时分析,提取音频的频域信息,并将其转换为频谱图。可以使用QT的绘图模块和信号处理库来实现频谱图的绘制和频谱数据的处理。 在播放音乐的同时,通过不断地对音频数据进行采样和分析,获取音频信号的频域分布,并将其转换为频谱图。然后,使用QT的图形绘制功能,将频谱图绘制在界面上的相应位置。 这样,当音乐播放时,用户可以实时看到频谱图的变化,从而更直观地感受音乐的节奏和音质特点。 总而言之,利用QT框架可以创建一个频谱音乐播放器,通过QT的UI组件、多媒体模块和图形绘制功能,实现音乐的播放和频谱图的实时展示。这样的音乐播放器不仅可以提供优秀的用户体验,还能让用户更好地感受和欣赏音乐。
评论 40
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值