logarithmic scale on spectral mesh, some refactoring
This commit is contained in:
parent
4d0cb4cefe
commit
b948115840
@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.2)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
project(glTest)
|
project(glTest)
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O0 -g")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O0 -g -Wall")
|
||||||
set(CMAKE_BUILD_TYPE DEBUG)
|
set(CMAKE_BUILD_TYPE DEBUG)
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
#include "AudioPlayer.h"
|
#include "AudioPlayer.h"
|
||||||
#include "WavSource.h"
|
#include "WavSource.h"
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <functional>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int streamCallback(const void* input,
|
int streamCallback(const void* input,
|
||||||
@ -43,7 +41,7 @@ AudioPlayer::AudioPlayer(std::string path) {
|
|||||||
outParam.hostApiSpecificStreamInfo = nullptr;
|
outParam.hostApiSpecificStreamInfo = nullptr;
|
||||||
|
|
||||||
err = Pa_OpenStream(&_stream, NULL, &outParam, _sndSource->getSampleRate(),
|
err = Pa_OpenStream(&_stream, NULL, &outParam, _sndSource->getSampleRate(),
|
||||||
/*paFramesPerBufferUnspecified*/1024, paClipOff,
|
/*paFramesPerBufferUnspecified*/1024*_sndSource->getChannelCount(), paClipOff,
|
||||||
::streamCallback, this);
|
::streamCallback, this);
|
||||||
PA_CHECK_ERROR(err);
|
PA_CHECK_ERROR(err);
|
||||||
|
|
||||||
@ -88,7 +86,7 @@ int AudioPlayer::streamCallback(const void* input,
|
|||||||
_sndSource->readData(framesPerBuffer, output);
|
_sndSource->readData(framesPerBuffer, output);
|
||||||
|
|
||||||
if(_streamListener) {
|
if(_streamListener) {
|
||||||
_streamListener((float*)output, framesPerBuffer);
|
_streamListener((float*)output, framesPerBuffer, _sndSource->getSampleDepth(), _sndSource->getChannelCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
return paContinue;
|
return paContinue;
|
||||||
@ -110,10 +108,10 @@ void AudioPlayer::stop() {
|
|||||||
PA_CHECK_ERROR(err);
|
PA_CHECK_ERROR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::setStreamListener(std::function<void(float*,std::size_t)> callback) {
|
void AudioPlayer::setStreamListener(StreamListenerType callback) {
|
||||||
_streamListener = callback;
|
_streamListener = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::setStreamFinishedListener(std::function<void()> callback) {
|
void AudioPlayer::setStreamFinishedListener(StreamFinishedType callback) {
|
||||||
_streamFinishedLitener = callback;
|
_streamFinishedLitener = callback;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,16 +10,20 @@ class AudioPlayer {
|
|||||||
private:
|
private:
|
||||||
ISndSource* _sndSource;
|
ISndSource* _sndSource;
|
||||||
PaStream* _stream;
|
PaStream* _stream;
|
||||||
std::function<void(float*,std::size_t)> _streamListener;
|
|
||||||
std::function<void()> _streamFinishedLitener;
|
typedef std::function<void(float*,std::size_t,std::size_t,std::size_t)> StreamListenerType;
|
||||||
|
typedef std::function<void()> StreamFinishedType;
|
||||||
|
|
||||||
|
StreamListenerType _streamListener;
|
||||||
|
StreamFinishedType _streamFinishedLitener;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AudioPlayer(std::string path);
|
AudioPlayer(std::string path);
|
||||||
~AudioPlayer();
|
~AudioPlayer();
|
||||||
void play();
|
void play();
|
||||||
void stop();
|
void stop();
|
||||||
void setStreamListener(std::function<void(float*,std::size_t)> callback);
|
void setStreamListener(StreamListenerType callback);
|
||||||
void setStreamFinishedListener(std::function<void()> callback);
|
void setStreamFinishedListener(StreamFinishedType callback);
|
||||||
int streamCallback(const void* input,
|
int streamCallback(const void* input,
|
||||||
void* output,
|
void* output,
|
||||||
unsigned long framesPerBuffer,
|
unsigned long framesPerBuffer,
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
#ifndef GLTEST_ISNDSOURCE_H
|
#ifndef GLTEST_ISNDSOURCE_H
|
||||||
#define GLTEST_ISNDSOURCE_H
|
#define GLTEST_ISNDSOURCE_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
struct ISndSource {
|
struct ISndSource {
|
||||||
virtual int getChannelCount() const = 0;
|
virtual int getChannelCount() const = 0;
|
||||||
virtual int getSampleRate() const = 0;
|
virtual int getSampleRate() const = 0;
|
||||||
|
virtual std::size_t getSampleDepth() const = 0;
|
||||||
virtual void readData(unsigned long frameCount, void* output) const = 0;
|
virtual void readData(unsigned long frameCount, void* output) const = 0;
|
||||||
virtual ~ISndSource() {}
|
virtual ~ISndSource() {}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,10 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "WavSource.h"
|
#include "WavSource.h"
|
||||||
|
|
||||||
|
#define FORMAT_DEPTH_MASK 0xFFFF
|
||||||
|
|
||||||
WavSource::WavSource(std::string path) {
|
WavSource::WavSource(std::string path) {
|
||||||
|
_info.format = 0;
|
||||||
_file = sf_open(path.c_str(), SFM_READ, &_info);
|
_file = sf_open(path.c_str(), SFM_READ, &_info);
|
||||||
if(!_file) {
|
if(!_file) {
|
||||||
throw std::runtime_error(sf_strerror(nullptr));
|
throw std::runtime_error(sf_strerror(nullptr));
|
||||||
@ -28,6 +31,23 @@ int WavSource::getSampleRate() const {
|
|||||||
return _info.samplerate;
|
return _info.samplerate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t WavSource::getSampleDepth() const {
|
||||||
|
switch(_info.format & FORMAT_DEPTH_MASK) {
|
||||||
|
case SF_FORMAT_PCM_S8:
|
||||||
|
case SF_FORMAT_PCM_U8:
|
||||||
|
return 8;
|
||||||
|
case SF_FORMAT_PCM_16:
|
||||||
|
return 16;
|
||||||
|
case SF_FORMAT_PCM_24:
|
||||||
|
return 24;
|
||||||
|
case SF_FORMAT_PCM_32:
|
||||||
|
return 32;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("unknown sample depth");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void WavSource::readData(unsigned long frameCount, void *output) const {
|
void WavSource::readData(unsigned long frameCount, void *output) const {
|
||||||
sf_read_float(_file, (float*)output, frameCount*_info.channels);
|
sf_read_float(_file, (float*)output, frameCount*_info.channels);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
int getChannelCount() const override final;
|
int getChannelCount() const override final;
|
||||||
int getSampleRate() const override final;
|
int getSampleRate() const override final;
|
||||||
|
std::size_t getSampleDepth() const override final;
|
||||||
void readData(unsigned long frameCount, void* output) const override final;
|
void readData(unsigned long frameCount, void* output) const override final;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
Mesh::Mesh(ShaderProgram* shader, std::size_t size) : _size(size), GLObject(shader) {
|
Mesh::Mesh(ShaderProgram* shader, std::size_t size) : GLObject(shader), _size(size) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,12 +12,14 @@ Mesh::~Mesh() {
|
|||||||
std::tuple<Vertex *, std::size_t> Mesh::generateVertices() const {
|
std::tuple<Vertex *, std::size_t> Mesh::generateVertices() const {
|
||||||
std::size_t u = _size, v = _size;
|
std::size_t u = _size, v = _size;
|
||||||
Vertex* retVal = new Vertex[u*v];
|
Vertex* retVal = new Vertex[u*v];
|
||||||
|
const float step = (exp(4) - 1)/_size;
|
||||||
|
|
||||||
for (std::size_t i = 0; i < u; i++)
|
for (std::size_t i = 0; i < u; i++)
|
||||||
for (std::size_t j = 0; j < v; j++)
|
for (std::size_t j = 0; j < v; j++)
|
||||||
{
|
{
|
||||||
Vertex vertex;
|
// Vertex vertex;
|
||||||
float x=(float)i/(float)u-0.5f;
|
float x = /*(float)i/(float)u*/ logf(i*step + 1)/4.0f - 0.5f;
|
||||||
float y=(float)j/(float)v-0.5f;
|
float y = (float)j/(float)v - 0.5f;
|
||||||
retVal[j*u+i].coords[0] = x*3;
|
retVal[j*u+i].coords[0] = x*3;
|
||||||
retVal[j*u+i].coords[1] = y*3;
|
retVal[j*u+i].coords[1] = y*3;
|
||||||
retVal[j*u+i].coords[2] = heightMapFunc(j, i, x, y);
|
retVal[j*u+i].coords[2] = heightMapFunc(j, i, x, y);
|
||||||
|
|||||||
@ -18,8 +18,8 @@ public:
|
|||||||
Mesh(ShaderProgram* shader, std::size_t size);
|
Mesh(ShaderProgram* shader, std::size_t size);
|
||||||
virtual ~Mesh();
|
virtual ~Mesh();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
std::tuple<Vertex*, std::size_t> generateVertices() const override final;
|
std::tuple<Vertex*, std::size_t> generateVertices() const override;
|
||||||
std::tuple<GLuint*, std::size_t> generateIndices() const override final;
|
std::tuple<GLuint*, std::size_t> generateIndices() const override final;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@ -18,22 +18,24 @@ float SpectralMesh::heightMapFunc(std::size_t nx, std::size_t ny, float fx, floa
|
|||||||
return *(_data + _size*nx + ny);
|
return *(_data + _size*nx + ny);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpectralMesh::addLine(float *line) {
|
void SpectralMesh::addLine(float *line, std::size_t depth) {
|
||||||
|
fftwf_plan plan = fftwf_plan_dft_r2c_1d(2*_size, line, _spectrLineComplex, FFTW_ESTIMATE);
|
||||||
for(std::size_t i = 0; i < 2*_size; ++i) {
|
|
||||||
_spectrLine[i] = line[2*i];
|
|
||||||
}
|
|
||||||
|
|
||||||
fftwf_plan plan = fftwf_plan_dft_r2c_1d(2*_size, _spectrLine, _spectrLineComplex, FFTW_ESTIMATE);
|
|
||||||
fftwf_execute(plan);
|
fftwf_execute(plan);
|
||||||
|
|
||||||
for(std::size_t i = 0; i < _size; ++i) {
|
for(std::size_t i = 0; i < _size; ++i) {
|
||||||
float real = _spectrLineComplex[i][0], imag = _spectrLineComplex[i][1];
|
float real = _spectrLineComplex[i][0], imag = _spectrLineComplex[i][1];
|
||||||
_spectrLine[i] = 0.3f*log10f(sqrtf(real*real + imag*imag)) + 0.1f;
|
_spectrLine[i] = sqrtf(real*real + imag*imag);
|
||||||
if(_spectrLine[i] < 0) {
|
}
|
||||||
_spectrLine[i] = 0;
|
|
||||||
|
// normalizeArray(_spectrLine, _size);
|
||||||
|
float dbDepth = fabsf(20.0f*log10f(1.0f/powf(2.0f, depth)));
|
||||||
|
for (std::size_t j = 0; j < _size; ++j) {
|
||||||
|
_spectrLine[j] = (20.0f*log10f(_spectrLine[j]) + dbDepth - 80)/dbDepth;
|
||||||
|
if(_spectrLine[j] < 0) {
|
||||||
|
_spectrLine[j] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//normalizeArray(_spectrLine, _size);
|
||||||
|
|
||||||
memmove(_data + _size, _data, _size*(_size - 1)*sizeof(float));
|
memmove(_data + _size, _data, _size*(_size - 1)*sizeof(float));
|
||||||
memcpy(_data, _spectrLine, _size*sizeof(float));
|
memcpy(_data, _spectrLine, _size*sizeof(float));
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
#ifndef GLTEST_SPECTRALMESH_H
|
#ifndef GLTEST_SPECTRALMESH_H
|
||||||
#define GLTEST_SPECTRALMESH_H
|
#define GLTEST_SPECTRALMESH_H
|
||||||
|
|
||||||
|
|
||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
#include <fftw3.h>
|
#include <fftw3.h>
|
||||||
|
|
||||||
@ -14,7 +13,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
SpectralMesh(ShaderProgram* shader, std::size_t size);
|
SpectralMesh(ShaderProgram* shader, std::size_t size);
|
||||||
virtual ~SpectralMesh();
|
virtual ~SpectralMesh();
|
||||||
void addLine(float* line);
|
void addLine(float* line, std::size_t depth = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float heightMapFunc(std::size_t nx, std::size_t ny, float fx, float fy) const override final;
|
float heightMapFunc(std::size_t nx, std::size_t ny, float fx, float fy) const override final;
|
||||||
|
|||||||
16
src/main.cpp
16
src/main.cpp
@ -13,19 +13,29 @@ int main() {
|
|||||||
ShaderProgram program("../shaders/vertex.glsl", "../shaders/fragment.glsl");
|
ShaderProgram program("../shaders/vertex.glsl", "../shaders/fragment.glsl");
|
||||||
OGL::instance()->setCurShaderProgram(&program);
|
OGL::instance()->setCurShaderProgram(&program);
|
||||||
|
|
||||||
SpectralMesh mesh(&program, 256);
|
SpectralMesh mesh(&program, 512);
|
||||||
mesh.create();
|
mesh.create();
|
||||||
OGL::instance()->addObject(&mesh);
|
OGL::instance()->addObject(&mesh);
|
||||||
|
|
||||||
Camera::instance()->init();
|
Camera::instance()->init();
|
||||||
|
|
||||||
AudioPlayer player(/*"/Users/selim/Dropbox/euphoria.wav"*/ "/home/selim/dl/euphoria.wav");
|
AudioPlayer player(/*"/Users/selim/Dropbox/euphoria.wav"*/ "/home/selim/dl/euphoria.wav");
|
||||||
player.setStreamListener([&mesh](float *data, std::size_t framesCount) {
|
float* line = new float[1024];
|
||||||
mesh.addLine(data);
|
player.setStreamListener([&mesh, line](float *data, std::size_t framesCount, std::size_t depth, std::size_t channels) {
|
||||||
|
// if we have more than one channel, take the first
|
||||||
|
if(channels > 1) {
|
||||||
|
for(std::size_t i = 0, j = 0; i < framesCount; i += channels, ++j) {
|
||||||
|
line[j] = data[i];
|
||||||
|
}
|
||||||
|
mesh.addLine(line, depth);
|
||||||
|
} else {
|
||||||
|
mesh.addLine(data, depth);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
player.play();
|
player.play();
|
||||||
|
|
||||||
OGL::instance()->run();
|
OGL::instance()->run();
|
||||||
|
delete[] line;
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
std::cout << "exception: " << ex.what() << std::endl;
|
std::cout << "exception: " << ex.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user