经过一个多月的努力,插件的开发终于完成,等待以后测试上线,激动٩(๑>◡<๑)۶。这里,写一下利用OpenGL进行音乐可视化即音乐频谱图的绘制大致流程。

(1)音频解析

对音频解析前,一定要懂得音频的几个重要参数:采样频率,采样位数,通道数等。不懂得小伙伴可以看下面这个博客:https://blog.csdn.net/caoshangpa/article/details/51218597

这里提供一下我在进行音频解析时的代码:

//
//  main.cpp
//  PCM3.0    解码效率低 卡顿十分严重
//
//  Created by boone on 2018/8/9.
//  Copyright © 2018年 boone. All rights reserved.
//#include <iostream>
#include <fstream>
#include <iomanip>using namespace std;struct wav_struct
{unsigned long file_size;        //文件大小unsigned short channel;            //通道数unsigned long frequency;        //采样频率unsigned long Bps;                //Byte率unsigned short sample_num_bit;    //一个样本的位数unsigned long data_size;        //数据大小unsigned char *data;            //音频数据
};int main(int argc, char **argv)
{fstream fs;wav_struct WAV;fs.open("/Users/boone/Desktop/Music/Seve.wav", ios::binary | ios::in);fs.seekg(0, ios::end);        //用c++常用方法获得文件大小WAV.file_size = fs.tellg();fs.seekg(0x14);fs.read((char*)&WAV.channel, sizeof(WAV.channel));fs.seekg(0x18);fs.read((char*)&WAV.frequency, sizeof(WAV.frequency));fs.seekg(0x1c);fs.read((char*)&WAV.Bps, sizeof(WAV.Bps));fs.seekg(0x22);fs.read((char*)&WAV.sample_num_bit, sizeof(WAV.sample_num_bit));fs.seekg(0x28);fs.read((char*)&WAV.data_size, sizeof(WAV.data_size));WAV.data = new unsigned char[WAV.data_size];fs.seekg(0x2c);fs.read((char *)WAV.data, sizeof(char)*WAV.data_size);cout << "文件大小为  :" << WAV.file_size << endl;cout << "音频通道数  :" << WAV.channel << endl;cout << "采样频率    :" << WAV.frequency << endl;cout << "Byte率      :" << WAV.Bps << endl;cout << "样本位数    :" << WAV.sample_num_bit << endl;cout << "音频数据大小:" << WAV.data_size << endl;cout << "最后10个数据:" << endl;for (unsigned long i =0; i<WAV.data_size; i = i + 2){//右边为大端unsigned long data_low = WAV.data[i];unsigned long data_high = WAV.data[i + 1];double data_true = data_high * 256 + data_low;long data_complement = 0;//取大端的最高位(符号位)int my_sign = (int)(data_high / 128);if (my_sign == 1){data_complement = data_true - 65536;}else{data_complement = data_true;}setprecision(4);double float_data = (double)(data_complement/(double)32768);printf("%f ", float_data);}fs.close();delete[] WAV.data;system("pause");}

(2)傅里叶变换(FFTW)

音频解析出的数据我们并不能直接拿来绘制频谱图,解析出的数据我们称之为时域序列,利用该序列进行绘制得到的是波形图,一定要注意波形图和频谱图的区别,我们若想绘制频谱图,需要将时域序列转换为频域序列,然后利用OpenGL进行绘制。【这一段话看不懂的可以去百度或者Google补一下傅里叶变换的知识】。傅里叶变换的目的就是将音频解析出的时域序列转换为绘制频谱所需的频域序列。

网上存有大量的FFT【以下都用FFT来代替傅里叶变换】代码,GitHub上也有大量的开源FFT代码,有兴趣的可以去仔细研究一下FFT算法的实现。这里我采用的是FFTW【被誉为世界上最快的FFT】,所以如果你不是用汇编语言来实现FFT算法的话,我觉得效率都不会有FFTW高,所以推荐使用FFTW【当时我可是走了好长一段弯路来着o(╥﹏╥)o】。

    //FFTWfftw_complex *in,*out;fftw_plan p;in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*n);out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*n);if (in==NULL||out==NULL) {cout<<"ERROR: Fail to memory allocation"<<endl;}else{int  i=0;for(vector<float>::iterator it = vertices.begin(); it != vertices.end(); it+=2 ){in[i][0]=*it;in[i][1]=0.0;i++;}}p = fftw_plan_dft_1d(n, in, out, FFTW_BACKWARD, FFTW_ESTIMATE);fftw_execute(p);fftw_destroy_plan(p);fftw_cleanup();

(3)OpenGL绘制

音频数据我们已经成功提取,并经过FFT后转为了我们需要的频域序列。我这里将数据存入数组中,一次性传入CPU进行计算,防止在绘制过程中出现卡顿的情况,CPU计算完毕后传递给GPU进行渲染。

根据数据设置坐标,存入数组,设置顶点数组缓冲对象,顶点数组对象,绑定纹理,循环绘制。

代码比较多,这里贴出数据的存入以及循环绘制的代码【其他的都是OpenGL绘图的基础代码】:

float temp =sqrt(out[j][0]*out[j][0]+out[j][1]*out[j][1])/30000;j++;arr[i++]=xstart;arr[i++]=0.0f;arr[i++]=0.0f;arr[i++]=xstart;arr[i++]=temp;arr[i++]=0.0f;xstart=xstart+0.002;if (xstart>1.0) {xstart=-1.0;}
//绘制频谱
void drawLine()
{//颜色随机设置float redValue = 0.0f;float blueValue = 1.0f;for (int i=istart; i<2000+istart; i+=2) {glUniform4f(0, redValue, 1.0f, blueValue, 1.0f);if (i<=1000+istart) {redValue=redValue+0.002;blueValue=blueValue-0.002;}else{redValue=redValue-0.002;blueValue=blueValue+0.002;}glDrawArrays(GL_LINES, i, 2);}istart+=2000;
}

(4)实时渲染

频谱绘制出来之后难免会有些丑,所以这个时候就需要我们为频谱图化化妆了。

我对频谱的处理是同时绘制三种频谱,并分别为每种频谱绑定属于自己的着色器,在绘制线的同时改变颜色变量,实现频谱的颜色变化。在片段着色器中进行RGB颜色模型--》HSV颜色模型的转换,从而实现频谱图色相,饱和度以及亮度的控制。简单几步就将频谱图变得美美的。

片段着色器代码:

#version 330 coreout vec4 FragColor;uniform vec4 ourColor;uniform float u_hue=0.0;
uniform float u_saturation=1.0;
uniform float u_value=1.0;
uniform float u_contrast=0.0;vec3 rgbtohsv(vec3 rgb)
{//过长省略......return hsv;
}
vec3 hsvtorgb(vec3 hsv)
{//过长省略.......return vec3(R, G, B);
}
void main()
{vec4 pixColor = ourColor;vec3 hsv;hsv.xyz = rgbtohsv(pixColor.rgb);hsv.x += u_hue;hsv.x = mod(hsv.x, 360.0);hsv.y *= u_saturation;hsv.z *= u_value;vec3 f_color = hsvtorgb(hsv);f_color = ((f_color - 0.5) * max(u_contrast+1.0, 0.0)) + 0.5;FragColor = vec4(f_color, pixColor.a);//FragColor = ourColor*vec4(1.0,1.0,1.0,0.5);
}

至此,音乐频谱图的绘制正式结束,经历了两个月,该插件经历了十几个版本的变迁,下面是目前开发版本的最终版:

【C++】基于OpenGL的音乐可视化(六): 最终版本相关推荐

  1. 【C++】基于OpenGL的音乐可视化(二):波形的绘制

    在上一篇博客中,我已经介绍了怎么去解析PCM文件获取音量数据,这次我们根据获取的音量数据绘制出我们的波形图,即简单的实现了音乐的初步可视化. 我们利用GLFW这个库来实现OpenGL绘图,相关环境的配 ...

  2. 【C++】基于OpenGL的音乐可视化(一):PCM音频数据的解析

    PCM的数据解析出音量信息首先要知道的一些基础常识: 采样频率,指每秒钟取得声音样本的次数,采样频率越高,包含的声音信息自然就越多,声音也就越好,频率越高,保存需要的空间也会高. 采样位宽,即采样值, ...

  3. Unity 中的音乐可视化

    Unity 中的音乐可视化 本帖最后由 204有个大坑 于 2017-5-31 17:33 编辑 1738music-visulization-in-unity.jpg (32.33 KB, 下载次数 ...

  4. 计算机可视化仿真技术opengl,基于OpenGL的三维场景可视化仿真

    摘要: 随着计算机可视化技术的发展,计算机可视化应用的领域不断地拓宽,广泛地应用在科学计算.人工智能仿真.三维图形的制作方面等领域.可视化是计算机技术应用的热门领域,而这个热门领域的核心都集中在三维真 ...

  5. matlab画波动图像,【基于Matlab的波动方程的可视化实现最终版材料】

    基于Matlab的波动方程的可视化实现(最终版) <基于Matlab的波动方程的可视化实现.doc>由会员分享,可免费在线阅读全文,更多与<基于Matlab的波动方程的可视化实现(最 ...

  6. 基于opengl的3d漫游游戏 - 古堡危机之丧尸围城

    作品名称: <古堡危机> 小组团队名称: 拾荒三人组 日期:2018年12月 目录 第一章 简介 3 前言 3 项目的创意设想.游戏类型.实现的功能.项目意义 3 Opengl 4 作品代 ...

  7. 基于OpenGL的Android系统视频转换功能实现

          第1章OpenGL ES 3D图形编程首先OpenGL.OpenGL的英文全称是OpenGL Graphics Library,中午名称是开发式图形库.OpenGL为程序开发人员定义了一个 ...

  8. 基于OpenGL的地形建模技术的研究与实现

    毕业论文 基于OpenGL的地形建模技术的研究与实现 诚信声明 本人郑重声明:本设计(论文)及其研究工作是本人在指导教师的指导下独立完成的,在完成设计(论文)时所利用的一切资料均已在参考文献中列出. ...

  9. (音乐可视化项目)Light-Dancer为音乐而生

    序言: 这是以我为项目组长所做的一个训练项目,项目结题之后笔者决定拿出来跟诸位分享,希望对你对我都有所帮助 一.成果简单介绍: (1)Reading-LED(作品) (2)Listening-LED( ...

最新文章

  1. COCO KeyPoints关键点数据集准备
  2. SpringBoot静态获取 bean的三种方式,你学会了吗?
  3. linux 支持的字体命令,Linux设置显示中文和字体
  4. ios重签名iReSign
  5. 揭秘:高盛交易员赚取10亿美元利润的神秘“利器”终于公开了
  6. 22为什么有些人更愿意帮助别人
  7. linux安装自带mysql吗_Linux下安装mysql
  8. MySQL工具名字_MySQL客户端工具及SQL讲解
  9. C语言 全局变量 - C语言零基础入门教程
  10. DevExpress控件使用小结
  11. java 数学_Java数学课
  12. 1500802035王叔文
  13. 让模拟器也支持GPS定位(模拟实现)
  14. jsp:setProperty的用法
  15. 地图做显示定位蓝点时遇到的问题
  16. python打造excel神器_将Excel与Python完美组合的神器
  17. 身份证提取生日和性别
  18. MinGW安装包下载及下载失败解决
  19. ESP8266-002 ESP8266EX简介
  20. 数字孪生风机设备,智慧风电 3D 可视化智能运维

热门文章

  1. 小土堆pytorch教程学习笔记P8P9
  2. 职业教育计算机教育美育,中职计算机职业素质教育
  3. 五次面试,程序员的悲催轮回
  4. 20、spring源码系列总结
  5. 浅谈text段、data段和bss段
  6. 测试ResNet在ImageNet验证集上的准确率
  7. 写给数据分析入门者:一种通用的数据分析思路
  8. C语言简明教程,C语言简明教程
  9. 吐血整理 | 据说这里有一份关于BAT的 “宝藏级” 面试记录终于可以看了!
  10. 机器学习中算法与模型的区别