Permalink
Browse files

-Added WaveformCache class, g_statestore keeps all caches in a vector…

…, offlineworker analyses loaded buffers, and then stores the waveformCache in the vector. OfflineWorker analysis isn't providing the right samples.
  • Loading branch information...
harryhaaren committed Feb 4, 2012
1 parent 8440d82 commit e763ec91f94aa3f874b674d2ef337e90348c0c95
Showing with 238 additions and 12 deletions.
  1. +22 −1 src/g_statestore.cpp
  2. +7 −1 src/g_statestore.hpp
  3. +28 −10 src/g_waveview.cpp
  4. +53 −0 src/offlineworker.cpp
  5. +2 −0 src/offlineworker.hpp
  6. +68 −0 src/waveformcache.cpp
  7. +57 −0 src/waveformcache.hpp
  8. +1 −0 wscript
View
@@ -41,7 +41,7 @@ AudioBuffer* GuiStateStore::getNewAudioBuffer()
return audioBufferVector.back().get();
}
-AudioBuffer* GuiStateStore::getWaveformCache(int ID)
+AudioBuffer* GuiStateStore::getAudioBufferPointer(int ID)
{
if ( ID >= 0 && ID < audioBufferVector.size() )
{
@@ -52,6 +52,27 @@ AudioBuffer* GuiStateStore::getWaveformCache(int ID)
return 0;
}
+WaveformCache* GuiStateStore::getNewWaveformCache()
+{
+ waveformCacheVector.push_back( std::make_shared<WaveformCache>() );
+
+ return waveformCacheVector.back().get();
+}
+
+WaveformCache* GuiStateStore::getWaveformCache(int ID)
+{
+ // check if we have a generated waveform of the buffer here
+ for ( int i = 0; i < waveformCacheVector.size(); i++ )
+ {
+ if ( ID == waveformCacheVector.at(i)->getID() )
+ {
+ return waveformCacheVector.at(i).get();
+ }
+ }
+
+ return 0;
+}
+
void GuiStateStore::addTrack()
{
//std::cout << "GuiStateStore::addTrack()" << std::endl;
View
@@ -28,6 +28,7 @@
#include <memory>
#include "audiobuffer.hpp"
+#include "waveformcache.hpp"
#include "effectstate.hpp"
#include "g_equalizerstate.hpp"
@@ -45,7 +46,10 @@ class GuiStateStore
void addTrack();
AudioBuffer* getNewAudioBuffer();
- AudioBuffer* getWaveformCache(int ID);
+ AudioBuffer* getAudioBufferPointer(int ID);
+
+ WaveformCache* getNewWaveformCache();
+ WaveformCache* getWaveformCache(int ID);
void addAudioBufferName(int ID, std::string name);
@@ -70,6 +74,8 @@ class GuiStateStore
std::string lastUsedDir;
+ std::vector< std::shared_ptr<WaveformCache> > waveformCacheVector;
+
std::vector< std::shared_ptr<AudioBuffer> > audioBufferVector;
};
View
@@ -27,6 +27,7 @@
#include "top.hpp"
#include "g_statestore.hpp"
+using namespace std;
using namespace Luppp; // for COLOUR_*
GWaveView::GWaveView(Top* t)
@@ -36,6 +37,9 @@ GWaveView::GWaveView(Top* t)
// initial size for the waveview
waveviewSize = 11050;
+ // initial sample to start editing
+ sampleID = 0;
+
// Gives Exposure & Button presses to the widget.
add_events(Gdk::EXPOSURE_MASK);
add_events(Gdk::BUTTON_PRESS_MASK );
@@ -140,17 +144,31 @@ bool GWaveView::on_expose_event(GdkEventExpose* event)
dashes[0] = 2.0;
dashes[1] = 2.0;
cr->set_dash (dashes, 0.0);
- cr->set_line_width(1.0);
- cr->set_source_rgb (0.4,0.4,0.4);
+ cr->set_line_width(1.5);
+ cr->set_source_rgb (0.7,0.7,0.7);
+
+ // horizontal lines
+ for ( int i = 0; i < 2; i++ )
+ {
+ cr->move_to( x , y + ((ySize / 2.f)*i) );
+ cr->line_to( x +xSize, y + ((ySize / 2.f)*i) );
+ }
+
+ // vertical lines
for ( int i = 0; i < 4; i++ )
{
cr->move_to( x + ((xSize / 4.f)*i), y );
cr->line_to( x + ((xSize / 4.f)*i), y + ySize );
}
- for ( int i = 0; i < 4; i++ )
+ cr->stroke();
+
+ // 8th lines
+ cr->set_line_width(1.0);
+ cr->set_source_rgb (0.2,0.2,0.2);
+ for ( int i = 0; i < 8; i++ )
{
- cr->move_to( x , y + ((ySize / 4.f)*i) );
- cr->line_to( x +xSize, y + ((ySize / 4.f)*i) );
+ cr->move_to( x + ((xSize / 8.f)*i), y );
+ cr->line_to( x + ((xSize / 8.f)*i), y + ySize );
}
cr->stroke();
cr->unset_dash();
@@ -164,18 +182,18 @@ bool GWaveView::on_expose_event(GdkEventExpose* event)
int sampleCountForDrawing = 25;
-
- AudioBuffer* waveviewCache = top->guiState->getWaveformCache(0);
+ WaveformCache* waveviewCache = top->guiState->getWaveformCache(sampleID);
if ( waveviewCache == 0 )
{
// no cache generated for this waveform yet!
+ std::cout << "No waveview cache exists for ID " << sampleID << endl;
return;
}
- // get the ID of the AudioBuffer, and check if we have a cahce of
- //int audioBufferID = tmpAudioBuffer->getID();
- //sample = *(tmpAudioBuffer->getPointer() );
+ sample = *( waveviewCache->getPointer() );
+
+ cout << "Got waveviewCache for ID " << sampleID << " sample size = " << sample.size() << endl;
// loop for drawing each Point on the widget.
for (long index=0; index <(long)sample.size(); index++ )
View
@@ -27,6 +27,7 @@
#include "ladspahost.hpp"
#include "audiotrack.hpp"
#include "audiobuffer.hpp"
+#include "waveformcache.hpp"
#include "g_statestore.hpp"
@@ -305,6 +306,58 @@ int OfflineWorker::loadAudioBuffer( int ID, int block, std::string name)
x->looperLoad( ID, block, buffer->getID() );
top->toEngineQueue.push(x);
+ // analyse the loaded sample, and write a "waveform cache" audioBuffer.
+ analyseBuffer( buffer->getID() );
+
return 0;
}
+
+void OfflineWorker::analyseBuffer(int ID)
+{
+ cout << "OfflineWorker::analyseBuffer() ID = " << ID << endl;
+
+ // get the relevant AudioBuffer and vector pointer
+ AudioBuffer* buffer = top->guiState->getAudioBufferPointer(ID);
+ if ( buffer == 0 ) {
+ cout << "OfflineWorker::analyseBuffer() ID not valid!" << endl;
+ return;
+ }
+ std::vector<float>* bufferPointer = buffer->getPointer();
+
+ // get a new ( or existing ) WaveformCache
+ WaveformCache* waveformCache = top->guiState->getWaveformCache(ID);
+ if ( waveformCache == 0 ) {
+ cout << "Creating new WaveformCache with id " << ID << endl;
+ waveformCache = top->guiState->getNewWaveformCache();
+ waveformCache->setID(ID);
+ }
+
+ float currentMax = 0.f;
+ bool aboveZero = false;
+
+ for (long index=0; index <(long)bufferPointer->size(); index++ )
+ {
+ float currentSample = bufferPointer->at(index);
+
+ if ( currentSample > 0 && currentMax < currentSample ) // top
+ {
+ currentMax = currentSample;
+ aboveZero = true;
+ }
+
+ // if we cross to below 0, we push back the previous MAX
+ if ( currentSample < 0.f && aboveZero == true )
+ {
+ waveformCache->getPointer()->push_back( currentMax );
+ aboveZero = false;
+ }
+
+ }
+
+
+}
+
+
+
+
View
@@ -38,6 +38,8 @@ class OfflineWorker
int addTrack(int);
int setTrackSource( int, AudioSourceType type );
+ void analyseBuffer( int ID );
+
int loadAudioBuffer( int, int, std::string name);
int createNewEffect( int, int, /*EffectType*/ int type );
View
@@ -0,0 +1,68 @@
+
+/*
+ This file is part of Luppp.
+ Copyright 2012, Harry van Haaren
+
+ Luppp is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Luppp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Luppp. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "waveformcache.hpp"
+
+// static ID counter
+int WaveformCache::privateId = 0;
+
+WaveformCache::WaveformCache()
+{
+ std::cout << "WaveformCache::WaveformCache() Setting numBeats to default" << std::endl;
+ // Set ID
+ ID = privateId++;
+
+ numBeats = 4;
+}
+
+int WaveformCache::getID()
+{
+ return ID;
+}
+void WaveformCache::setID(int i)
+{
+ ID = i;
+}
+
+void WaveformCache::setBeats(int beats)
+{
+ if ( beats < 1 )
+ beats = 1;
+
+ numBeats = beats;
+
+ std::cout << "WaveformCache::setBeats(" << beats << ")" << std::endl;
+}
+
+int WaveformCache::getBeats()
+{
+ return numBeats;
+}
+
+std::vector<float>* WaveformCache::getPointer()
+{
+ //std::cout << "WaveformCache::getPointer() ID: " << ID << " size = " << buffer.size() << std::endl;
+ return &buffer;
+}
+
+WaveformCache::~WaveformCache()
+{
+ std::cout << "WaveformCache::~WaveformCache() Destroyed!" << std::endl;
+}
+
View
@@ -0,0 +1,57 @@
+
+/*
+ This file is part of Luppp.
+ Copyright 2012, Harry van Haaren
+
+ Luppp is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Luppp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Luppp. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef LUPPP_WAVEFORMCACHE
+#define LUPPP_WAVEFORMCACHE
+
+#include <iostream>
+#include <vector>
+#include <glibmm.h>
+
+// essentailly a waveform cache is just a vector of points, equidistant
+// (roughly anway), and it can be plotted on the GUI without sample accurate
+// reading, so its much faster.
+
+class WaveformCache
+{
+ public:
+
+ WaveformCache();
+ ~WaveformCache();
+
+ int getID();
+ void setID(int);
+
+ int getBeats();
+ void setBeats(int);
+
+ std::vector<float>* getPointer();
+
+ protected:
+
+ static int privateId;
+ int ID;
+
+ int numBeats;
+
+ std::vector<float> buffer;
+};
+
+#endif
+
View
@@ -68,6 +68,7 @@ def build(ctx):
guiList = [ 'src/g_window.cpp',
'src/g_track.cpp',
'src/g_buffersource.cpp',
+ 'src/waveformcache.cpp',
'src/g_widgets.cpp',
'src/g_waveview.cpp',
'src/g_masterprogress.cpp',

0 comments on commit e763ec9

Please sign in to comment.