Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Showing
with 2354 additions and 0 deletions
//
// RapidMixThread/h
// This implementation of rapidMix trains in a different thread and has a synchronized
// update process with your main thread, which triggers a ( sync ) callback on doneTraining.
// Allows you to train one model and keep using it while the next one trains, the new
// model will be swapped in sync with the thread the update is called in once it's done.
// Created by James on 19/11/2017.
//
//
#ifndef RapidMixThread_h
#define RapidMixThread_h
#include <algorithm>
#include <functional>
#include <unistd.h> // usleep
#include "ThreadedProcess.h"
#include "rapidmix.h"
typedef rapidmix::staticRegression selectedTraining;
class RapidMixThread : public ThreadedProcess
{
public:
std::function< void ( void ) > doneTrainingCallback = nullptr;
selectedTraining* model = nullptr; // The model to be accessed from outside this thread
RapidMixThread ( void ) : ThreadedProcess ( )
{
training.store( false );
doneTraining.store( false );
}
~RapidMixThread ( void )
{
stopThread( );
if ( newModel )
delete newModel;
if ( model )
delete model;
printf ( "Stop rapidmixthread\n" );
}
void setup ( void )
{
model = createModel( );
startThread( 100000 ); // start training thread with sleep time of 100 ms
}
bool train ( rapidmix::trainingData& data )
{
if ( !training.load( ) )
{
this->trainingData = data;
training.store( true );
return true;
}
return false;
}
bool isTraining ( void ) const
{
return training.load( );
}
void update ( void )
{ // To be called in your main loop
if ( doneTraining.load( ) )
{
if ( newModel )
{
std::swap( model, newModel );
} else
throw std::runtime_error( "New model was not created successfully" );
if ( doneTrainingCallback )
doneTrainingCallback( );
//printf( "Done training\n" );
doneTraining.store( false );
}
}
protected:
selectedTraining* createModel ( void )
{
// Doing this to prevent repetitive stuff when testing different models
selectedTraining* t = new selectedTraining( );
t->setNumHiddenNodes( 18 );
return t;
}
void mainThreadCallback ( void )
{ // Training thread
if ( isTraining( ) )
{
if ( newModel )
delete newModel;
newModel = createModel( );
//printf( "Started training in thread... \n" );
if ( !trainingData.trainingSet.empty( ) && trainingData.trainingSet[0].elements.size( ) > 1 )
if ( !newModel->train( trainingData ) )
throw std::runtime_error( "Training failed" );;
training.store( false );
doneTraining.store( true );
}
}
std::atomic< bool > training;
std::atomic< bool > doneTraining;
selectedTraining* newModel = nullptr;
rapidmix::trainingData trainingData;
private:
};
#endif /* RapidMixThread_h */
/*
* RingBuffer.hpp
*/
#ifndef RINGBUFFER_HPP
#define RINGBUFFER_HPP
#include <iostream>
#include <atomic>
#include <string>
#include <unistd.h>
#include <string.h> // memcpy
#include <cstring>
template <class T>
class RingBuffer
{
public:
RingBuffer();
RingBuffer(unsigned long size);
~RingBuffer();
void setup(unsigned long size);
unsigned long push(const T* data, unsigned long n);
unsigned long pop(T* data, unsigned long n);
unsigned long getWithoutPop(T* data, unsigned long n);
unsigned long items_available_for_write() const;
unsigned long items_available_for_read() const;
bool isLockFree() const;
void pushMayBlock(bool block);
void popMayBlock(bool block);
void setBlockingNap(unsigned long blockingNap);
void setSize(unsigned long size);
void reset();
private:
unsigned long array_size;
T* buffer = nullptr;
long type_size; // also depends on #channels
std::atomic<unsigned long> tail_index; // write pointer
std::atomic<unsigned long> head_index; // read pointer
bool blockingPush;
bool blockingPop;
useconds_t blockingNap = 500;
}; // RingBuffer{}
template <class T>
RingBuffer<T>::RingBuffer()
{
tail_index = 0;
head_index = 0;
blockingPush = false;
blockingPop = false;
} // RingBuffer()
template <class T>
RingBuffer<T>::RingBuffer(unsigned long array_size)
{
tail_index = 0;
head_index = 0;
blockingPush = false;
blockingPop = false;
setup(array_size);
} // RingBuffer()
template <class T>
RingBuffer<T>::~RingBuffer()
{
if (buffer)
delete [] buffer;
} // ~RingBuffer()
template <class T>
void RingBuffer<T>::setup(unsigned long array_size)
{
if (buffer)
delete [] buffer;
this->array_size = array_size;
buffer = new T [array_size](); // allocate storage
type_size = sizeof(T);
}
template <class T>
unsigned long RingBuffer<T>::items_available_for_write() const
{
long pointerspace = head_index.load()-tail_index.load(); // signed
if(pointerspace > 0) return pointerspace; // NB: > 0 so NOT including 0
else return pointerspace + array_size;
} // items_available_for_write()
template <class T>
unsigned long RingBuffer<T>::items_available_for_read() const
{
long pointerspace = tail_index.load() - head_index.load(); // signed
if(pointerspace >= 0) return pointerspace; // NB: >= 0 so including 0
else return pointerspace + array_size;
} // items_available_for_read()
template <class T>
void RingBuffer<T>::pushMayBlock(bool block)
{
this->blockingPush = block;
} // pushMayBlock()
template <class T>
void RingBuffer<T>::popMayBlock(bool block)
{
this->blockingPop = block;
} // popMayBlock()
template <class T>
void RingBuffer<T>::setBlockingNap(unsigned long blockingNap)
{
this->blockingNap = blockingNap;
} // setBlockingNap()
/*
* Try to write as many items as possible and return the number actually written
*/
template <class T>
unsigned long RingBuffer<T>::push(const T* data, unsigned long n)
{
unsigned long space = array_size, n_to_write, memory_to_write, first_chunk, second_chunk, current_tail;
//space = items_available_for_write();
if(blockingPush)
{
while((space = items_available_for_write()) < n)
{ // blocking
usleep(blockingNap);
} // while, possibly use a system level sleep operation with CVAR?
} // if
n_to_write = (n <= space) ? n : space; // limit
current_tail = tail_index.load();
if(current_tail + n_to_write <= array_size)
{ // chunk fits without wrapping
memory_to_write = n_to_write * type_size;
memcpy(buffer+current_tail, data, memory_to_write);
tail_index.store(current_tail + n_to_write);
}
else { // chunk has to wrap
first_chunk = array_size - current_tail;
memory_to_write = first_chunk * type_size;
memcpy(buffer + current_tail, data, memory_to_write);
second_chunk = n_to_write - first_chunk;
memory_to_write = second_chunk * type_size;
memcpy(buffer, data + first_chunk, memory_to_write);
tail_index.store(second_chunk);
}
return n_to_write;
} // push()
/*
* Try to read as many items as possible and return the number actually read
*/
template <class T>
unsigned long RingBuffer<T>::pop(T* data, unsigned long n)
{
unsigned long space = array_size, n_to_read, memory_to_read, first_chunk, second_chunk, current_head;
//space = items_available_for_read(); //if checking outside of thread, not necessary?
if(blockingPop)
{
while((space = items_available_for_read()) < n)
{ // blocking
usleep(blockingNap);
} // while
} // if
if(space == 0)
return 0;
n_to_read = (n <= space) ? n : space; // limit
current_head = head_index.load();
if(current_head + n_to_read <= array_size)
{ // no wrapping necessary
memory_to_read = n_to_read * type_size;
memcpy(data, buffer + current_head, memory_to_read);
head_index.store(current_head + n_to_read);
}
else { // read has to wrap
first_chunk = array_size - current_head;
memory_to_read = first_chunk * type_size;
memcpy(data, buffer + current_head, memory_to_read);
second_chunk = n_to_read - first_chunk;
memory_to_read = second_chunk * type_size;
memcpy(data + first_chunk, buffer, memory_to_read);
head_index.store(second_chunk);
}
return n_to_read;
} // pop()
/*
* Try to read as many items as possible and return the number actually read
*/
template <class T>
unsigned long RingBuffer<T>::getWithoutPop(T* data, unsigned long n)
{
unsigned long space = array_size, n_to_read, memory_to_read, first_chunk, second_chunk, current_head;
//space = items_available_for_read(); //if checking outside of thread, not necessary?
if(blockingPop)
{
while((space = items_available_for_read()) < n)
{ // blocking
usleep(blockingNap);
} // while
} // if
if(space == 0)
return 0;
n_to_read = (n <= space) ? n : space; // limit
current_head = head_index.load();
if(current_head + n_to_read <= array_size)
{ // no wrapping necessary
memory_to_read = n_to_read * type_size;
memcpy(data, buffer + current_head, memory_to_read);
//head_index.store(current_head + n_to_read);
}
else { // read has to wrap
first_chunk = array_size - current_head;
memory_to_read = first_chunk * type_size;
memcpy(data, buffer + current_head, memory_to_read);
second_chunk = n_to_read - first_chunk;
memory_to_read = second_chunk * type_size;
memcpy(data + first_chunk, buffer, memory_to_read);
//head_index.store(second_chunk);
}
return n_to_read;
} // getWithoutPop()
template <class T>
bool RingBuffer<T>::isLockFree() const
{
return (tail_index.is_lock_free() && head_index.is_lock_free());
} // isLockFree()
template <class T>
void RingBuffer<T>::setSize(unsigned long size)
{
if (buffer)
delete [] buffer;
this->array_size = array_size;
buffer = new T [array_size](); // allocate storage
type_size = sizeof(T);
tail_index.store(0);
head_index.store(0);
}
template <class T>
void RingBuffer<T>::reset()
{
tail_index.store(0);
head_index.store(0);
} // isLockFree()
#endif
This diff is collapsed.
This diff is collapsed.
//
// SigTools.cpp
//
//
// Created by James on 08/01/17.
//
//
#include "SigTools.hpp"
double MTOF ( unsigned char midi ) {
return pow( 2, static_cast< double >( midi-69 ) / 12.0 ) * 440.0;
}
double FTOM ( double freq ) {
return 12.0 * log2( freq / 440.0 ) + 69;
}
//
// SigTools.hpp
//
//
// Created by James on 08/01/17.
//
//
#ifndef SigTools_hpp
#define SigTools_hpp
#include <stdio.h>
#include <math.h>
double MTOF ( unsigned char midi );
double FTOM ( double freq );
#endif /* SigTools_hpp */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#include "ofApp.h"
#include "ofAppGlutWindow.h"
//========================================================================
int main( ){
ofAppGlutWindow window;
ofSetupOpenGL( &window, 1024, 768, OF_WINDOW ); // <-------- setup the GL context
ofRunApp( new ofApp( ) );
}
This diff is collapsed.
This diff is collapsed.
File added
This diff is collapsed.
This diff is collapsed.