logarithmic scale on spectral mesh, some refactoring

This commit is contained in:
Selim Mustafaev 2015-08-08 18:46:07 +03:00
parent 4d0cb4cefe
commit b948115840
11 changed files with 71 additions and 33 deletions

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.2)
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_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")

View File

@ -1,8 +1,6 @@
#include "AudioPlayer.h"
#include "WavSource.h"
#include <stdexcept>
#include <functional>
#include <iostream>
int streamCallback(const void* input,
@ -43,7 +41,7 @@ AudioPlayer::AudioPlayer(std::string path) {
outParam.hostApiSpecificStreamInfo = nullptr;
err = Pa_OpenStream(&_stream, NULL, &outParam, _sndSource->getSampleRate(),
/*paFramesPerBufferUnspecified*/1024, paClipOff,
/*paFramesPerBufferUnspecified*/1024*_sndSource->getChannelCount(), paClipOff,
::streamCallback, this);
PA_CHECK_ERROR(err);
@ -88,7 +86,7 @@ int AudioPlayer::streamCallback(const void* input,
_sndSource->readData(framesPerBuffer, output);
if(_streamListener) {
_streamListener((float*)output, framesPerBuffer);
_streamListener((float*)output, framesPerBuffer, _sndSource->getSampleDepth(), _sndSource->getChannelCount());
}
return paContinue;
@ -110,10 +108,10 @@ void AudioPlayer::stop() {
PA_CHECK_ERROR(err);
}
void AudioPlayer::setStreamListener(std::function<void(float*,std::size_t)> callback) {
void AudioPlayer::setStreamListener(StreamListenerType callback) {
_streamListener = callback;
}
void AudioPlayer::setStreamFinishedListener(std::function<void()> callback) {
void AudioPlayer::setStreamFinishedListener(StreamFinishedType callback) {
_streamFinishedLitener = callback;
}

View File

@ -10,16 +10,20 @@ class AudioPlayer {
private:
ISndSource* _sndSource;
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:
AudioPlayer(std::string path);
~AudioPlayer();
void play();
void stop();
void setStreamListener(std::function<void(float*,std::size_t)> callback);
void setStreamFinishedListener(std::function<void()> callback);
void setStreamListener(StreamListenerType callback);
void setStreamFinishedListener(StreamFinishedType callback);
int streamCallback(const void* input,
void* output,
unsigned long framesPerBuffer,

View File

@ -1,9 +1,12 @@
#ifndef GLTEST_ISNDSOURCE_H
#define GLTEST_ISNDSOURCE_H
#include <cstdint>
struct ISndSource {
virtual int getChannelCount() 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 ~ISndSource() {}
};

View File

@ -2,7 +2,10 @@
#include <stdexcept>
#include "WavSource.h"
#define FORMAT_DEPTH_MASK 0xFFFF
WavSource::WavSource(std::string path) {
_info.format = 0;
_file = sf_open(path.c_str(), SFM_READ, &_info);
if(!_file) {
throw std::runtime_error(sf_strerror(nullptr));
@ -28,6 +31,23 @@ int WavSource::getSampleRate() const {
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 {
sf_read_float(_file, (float*)output, frameCount*_info.channels);
}

View File

@ -17,6 +17,7 @@ public:
public:
int getChannelCount() 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;
};

View File

@ -1,8 +1,7 @@
#include "Mesh.h"
#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,11 +12,13 @@ Mesh::~Mesh() {
std::tuple<Vertex *, std::size_t> Mesh::generateVertices() const {
std::size_t u = _size, v = _size;
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 j = 0; j < v; j++)
{
Vertex vertex;
float x=(float)i/(float)u-0.5f;
// Vertex vertex;
float x = /*(float)i/(float)u*/ logf(i*step + 1)/4.0f - 0.5f;
float y = (float)j/(float)v - 0.5f;
retVal[j*u+i].coords[0] = x*3;
retVal[j*u+i].coords[1] = y*3;

View File

@ -18,8 +18,8 @@ public:
Mesh(ShaderProgram* shader, std::size_t size);
virtual ~Mesh();
private:
std::tuple<Vertex*, std::size_t> generateVertices() const override final;
protected:
std::tuple<Vertex*, std::size_t> generateVertices() const override;
std::tuple<GLuint*, std::size_t> generateIndices() const override final;
protected:

View File

@ -18,22 +18,24 @@ float SpectralMesh::heightMapFunc(std::size_t nx, std::size_t ny, float fx, floa
return *(_data + _size*nx + ny);
}
void SpectralMesh::addLine(float *line) {
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);
void SpectralMesh::addLine(float *line, std::size_t depth) {
fftwf_plan plan = fftwf_plan_dft_r2c_1d(2*_size, line, _spectrLineComplex, FFTW_ESTIMATE);
fftwf_execute(plan);
for(std::size_t i = 0; i < _size; ++i) {
float real = _spectrLineComplex[i][0], imag = _spectrLineComplex[i][1];
_spectrLine[i] = 0.3f*log10f(sqrtf(real*real + imag*imag)) + 0.1f;
if(_spectrLine[i] < 0) {
_spectrLine[i] = 0;
_spectrLine[i] = sqrtf(real*real + imag*imag);
}
// 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));
memcpy(_data, _spectrLine, _size*sizeof(float));

View File

@ -1,7 +1,6 @@
#ifndef GLTEST_SPECTRALMESH_H
#define GLTEST_SPECTRALMESH_H
#include "Mesh.h"
#include <fftw3.h>
@ -14,7 +13,7 @@ private:
public:
SpectralMesh(ShaderProgram* shader, std::size_t size);
virtual ~SpectralMesh();
void addLine(float* line);
void addLine(float* line, std::size_t depth = 0);
private:
float heightMapFunc(std::size_t nx, std::size_t ny, float fx, float fy) const override final;

View File

@ -13,19 +13,29 @@ int main() {
ShaderProgram program("../shaders/vertex.glsl", "../shaders/fragment.glsl");
OGL::instance()->setCurShaderProgram(&program);
SpectralMesh mesh(&program, 256);
SpectralMesh mesh(&program, 512);
mesh.create();
OGL::instance()->addObject(&mesh);
Camera::instance()->init();
AudioPlayer player(/*"/Users/selim/Dropbox/euphoria.wav"*/ "/home/selim/dl/euphoria.wav");
player.setStreamListener([&mesh](float *data, std::size_t framesCount) {
mesh.addLine(data);
float* line = new float[1024];
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();
OGL::instance()->run();
delete[] line;
} catch (std::exception& ex) {
std::cout << "exception: " << ex.what() << std::endl;
}