diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f5b8ab..7953936 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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/") diff --git a/src/Audio/AudioPlayer.cpp b/src/Audio/AudioPlayer.cpp index 7f50ff6..ed0862a 100644 --- a/src/Audio/AudioPlayer.cpp +++ b/src/Audio/AudioPlayer.cpp @@ -1,8 +1,6 @@ #include "AudioPlayer.h" #include "WavSource.h" -#include -#include #include 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 callback) { +void AudioPlayer::setStreamListener(StreamListenerType callback) { _streamListener = callback; } -void AudioPlayer::setStreamFinishedListener(std::function callback) { +void AudioPlayer::setStreamFinishedListener(StreamFinishedType callback) { _streamFinishedLitener = callback; } diff --git a/src/Audio/AudioPlayer.h b/src/Audio/AudioPlayer.h index f12bb0c..5a43e8e 100644 --- a/src/Audio/AudioPlayer.h +++ b/src/Audio/AudioPlayer.h @@ -10,16 +10,20 @@ class AudioPlayer { private: ISndSource* _sndSource; PaStream* _stream; - std::function _streamListener; - std::function _streamFinishedLitener; + + typedef std::function StreamListenerType; + typedef std::function StreamFinishedType; + + StreamListenerType _streamListener; + StreamFinishedType _streamFinishedLitener; public: AudioPlayer(std::string path); ~AudioPlayer(); void play(); void stop(); - void setStreamListener(std::function callback); - void setStreamFinishedListener(std::function callback); + void setStreamListener(StreamListenerType callback); + void setStreamFinishedListener(StreamFinishedType callback); int streamCallback(const void* input, void* output, unsigned long framesPerBuffer, diff --git a/src/Audio/ISndSource.h b/src/Audio/ISndSource.h index b9a4e68..207abc0 100644 --- a/src/Audio/ISndSource.h +++ b/src/Audio/ISndSource.h @@ -1,9 +1,12 @@ #ifndef GLTEST_ISNDSOURCE_H #define GLTEST_ISNDSOURCE_H +#include + 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() {} }; diff --git a/src/Audio/WavSource.cpp b/src/Audio/WavSource.cpp index 250b9de..a45b959 100644 --- a/src/Audio/WavSource.cpp +++ b/src/Audio/WavSource.cpp @@ -2,7 +2,10 @@ #include #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); } diff --git a/src/Audio/WavSource.h b/src/Audio/WavSource.h index 0c9323a..a98cd82 100644 --- a/src/Audio/WavSource.h +++ b/src/Audio/WavSource.h @@ -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; }; diff --git a/src/GLObjects/Mesh.cpp b/src/GLObjects/Mesh.cpp index 03f46dd..df1eb07 100644 --- a/src/GLObjects/Mesh.cpp +++ b/src/GLObjects/Mesh.cpp @@ -1,8 +1,7 @@ #include "Mesh.h" - #include -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 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; - float y=(float)j/(float)v-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; retVal[j*u+i].coords[2] = heightMapFunc(j, i, x, y); diff --git a/src/GLObjects/Mesh.h b/src/GLObjects/Mesh.h index 29ea614..fce9b26 100644 --- a/src/GLObjects/Mesh.h +++ b/src/GLObjects/Mesh.h @@ -18,8 +18,8 @@ public: Mesh(ShaderProgram* shader, std::size_t size); virtual ~Mesh(); -private: - std::tuple generateVertices() const override final; +protected: + std::tuple generateVertices() const override; std::tuple generateIndices() const override final; protected: diff --git a/src/GLObjects/SpectralMesh.cpp b/src/GLObjects/SpectralMesh.cpp index 3b52b36..db7bf44 100644 --- a/src/GLObjects/SpectralMesh.cpp +++ b/src/GLObjects/SpectralMesh.cpp @@ -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)); diff --git a/src/GLObjects/SpectralMesh.h b/src/GLObjects/SpectralMesh.h index dd571d8..b6d3bcd 100644 --- a/src/GLObjects/SpectralMesh.h +++ b/src/GLObjects/SpectralMesh.h @@ -1,7 +1,6 @@ #ifndef GLTEST_SPECTRALMESH_H #define GLTEST_SPECTRALMESH_H - #include "Mesh.h" #include @@ -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; diff --git a/src/main.cpp b/src/main.cpp index 372e08b..a62a4f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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; }