Now I assume that you have installed all the requirements needed for the visualizer. If not read Part 1.
We are using the graph from OpenGL Programming/Scientific OpenGL Tutorial 02 for plotting the spectrum. Full source code for the graph is available here.
Lets create a file draw.cpp
and add a main
function. We pass .wav
file as an argument.
int main(int argc, char *argv[])
{
if (argc < 2)
{
std::cout << "Usage: wave_iteration <FILENAME>" << std::endl;
return 1;
}
To play the music we are using SFML. So lets write code for that.
Before that we need to create an object sf::Music music;
. Add it to the global part.
//sfm play music
if (!music.openFromFile(fileName))
return -1;
// find the total music duration
totalMusicDuration = music.getDuration ();
Initializing the OpenGL. See this tutorial for better understanding the graph used here.
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(640, 480);
glutCreateWindow("My Graph");
GLenum glew_status = glewInit();
if (GLEW_OK != glew_status) {
fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status));
return 1;
}
if (!GLEW_VERSION_2_0) {
fprintf(stderr, "No support for OpenGL 2.0 found\n");
return 1;
}
GLint max_units;
glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_units);
if (max_units < 1) {
fprintf(stderr, "Your GPU does not have any vertex texture image units\n");
return 1;
}
GLfloat range[2];
glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
if (range[1] < 5.0)
fprintf(stderr, "WARNING: point sprite range (%f, %f) too small\n", range[0], range[1]);
Now we need to get the points to plot. getData()
is the function we fetch to get N/2
points in to the array. music.play()
plays the music been loaded.
getData();
music.play();
Now lets call some OpenGL function to plot the spectrum.
if (init_resources()) {
glutDisplayFunc(display);
glutSpecialFunc(special);
glutIdleFunc(moveWav);
glutKeyboardFunc(key);
glutMainLoop();
}
free_resources();
return 0;
}
Create a file visualizer.hpp
and add the following codes.
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include "common/shader_utils.h"
#include <SFML/Audio.hpp>
#include "aquila/source/WaveFile.h"
#include <iostream>
#include <functional>
#include <memory>
#include <chrono>
#include <thread>
#include <string.h>
#include <sys/time.h>
//kissFFT
#include "kiss_fft130/kiss_fft.h"
#ifndef M_PI
#define M_PI 3.14159265358979324
#endif
This completes the main
function. Here is the complete code for the function.
#include "visualizer.hpp"
#define N 10000
typedef unsigned long long timestamp_t;
static timestamp_t
get_timestamp ()
{
struct timeval now;
gettimeofday (&now, NULL);
return now.tv_usec + (timestamp_t)now.tv_sec * 1000000;
}
GLuint program;
GLint attribute_coord1d;
GLint uniform_offset_x;
GLint uniform_scale_x;
GLuint texture_id;
GLint uniform_mytexture;
float offset_x = 0.0;
float scale_x =1.0;
bool interpolate = false;
bool clamp = false;
bool showpoints = true;
GLuint vbo;
int graph[N/2];
int framePointer = 0;
char fileName[50];
bool calledFromInit = true;
bool dataEnd = false;
bool playFlag = true;
bool muteFlag = false;
sf::Time totalMusicDuration;
sf::Time timePlay;
sf::Music music;
sf::Time timePlay;
kiss_fft_cpx in[N],out[N];
timestamp_t tmain;
void getData();
void display();
int main(int argc, char *argv[])
{
if (argc < 2)
{
std::cout << "Usage: wave_iteration <FILENAME>" << std::endl;
return 1;
}
strcpy(fileName, argv[1]);
tmain = get_timestamp();
//sfm play music
if (!music.openFromFile(fileName))
return -1;
totalMusicDuration = music.getDuration ();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(640, 480);
glutCreateWindow("My Graph");
GLenum glew_status = glewInit();
if (GLEW_OK != glew_status) {
fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status));
return 1;
}
if (!GLEW_VERSION_2_0) {
fprintf(stderr, "No support for OpenGL 2.0 found\n");
return 1;
}
GLint max_units;
glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_units);
if (max_units < 1) {
fprintf(stderr, "Your GPU does not have any vertex texture image units\n");
return 1;
}
GLfloat range[2];
glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
if (range[1] < 5.0)
fprintf(stderr, "WARNING: point sprite range (%f, %f) too small\n", range[0], range[1]);
printf("------------------------------------------------------\n\n");
printf("Use left/right to move horizontally.And seek audio by +/-5 sec\n");
printf("Use up/down to change the horizontal scale.\n");
printf("Press home to reset the position and scale.\n");
printf("Press F7 to toggle interpolation.\n");
printf("Press F8 to toggle clamping.\n");
printf("Press F9 to toggle drawing points.\n");
printf("Press q to exit.\n");
printf("Press p to toggle Play/Pause audio.\n");
printf("Press r to reload and play audio.\n");
printf("------------------------------------------------------\n\n");
getData();
music.play();
if (init_resources()) {
glutDisplayFunc(display);
glutSpecialFunc(special);
glutIdleFunc(moveWav);
glutKeyboardFunc(key);
glutMainLoop();
}
free_resources();
return 0;
}