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
    评论
敬告:该系列的课程在抓紧录制更新中,敬请大家关注。敬告: 该系列的课程涉及:FFmpeg,WebRTC,SRS,Nginx,Darwin,Live555,等。包括:音视频、流媒体、直播、Android、视频监控28181、等。  我将领大家一起来学习:Qt麦克风数据探测、FFmpeg解码音频数据、音频波形图、音频播放器。具体内容包括:1.Qt采集麦克风并探测数据,生成动态矩形图。2.FFMpeg解码音频数据,生成PCM数据,并绘制波形图。3.音频播放器实战。 音视频与流媒体是一门很复杂的技术,涉及的概念、原理、理论非常多,很多初学者不学 基础理论,而是直接做项目,往往会看到c/c++的代码时一头雾水,不知道代码到底是什么意思,这是为什么呢? 因为没有学习音视频和流媒体的基础理论,就比如学习英语,不学习基本单词,而是天天听英语新闻,总也听不懂。所以呢,一定要认真学习基础理论,然后再学习播放器、转码器、非编、流媒体直播、视频监控、等等。 梅老师从事音视频与流媒体行业18年;曾在永新视博、中科大洋、百度、美国Harris广播事业部等公司就职,经验丰富;曾亲手主导广电直播全套项目,精通h.264/h.265/aac,曾亲自参与百度app上的网页播放器等实战产品。目前全身心自主创业,主要聚焦音视频+流媒体行业,精通音视频加密、流媒体在线转码快编等热门产品。
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、付费专栏及课程。

余额充值