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
Commits on Source (88)
Showing
with 2569 additions and 834 deletions
cmake_minimum_required(VERSION 2.8.9)
project (rapidmix)
# The version number.
set (rapidmix_VERSION_MAJOR 2)
set (rapidmix_VERSION_MINOR 2)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
# Compiler Flags
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -fPIC")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -DJSON_DEBUG -fPIC")
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Release")
set(CMAKE_BUILD_TYPE "Release")
endif()
# Main lib
include_directories(${PROJECT_SOURCE_DIR}/src)
# RAPID-MIX dependencies
include_directories(dependencies/RapidLib/src)
include_directories(dependencies/xmm/src)
include_directories(dependencies/GVF)
include_directories(dependencies/Maximilian)
include_directories(dependencies/Maximilian/libs)
include_directories(dependencies/pipo/sdk/src)
include_directories(dependencies/pipo/sdk/src/host)
include_directories(dependencies/pipo/modules)
include_directories(dependencies/pipo/modules/collection)
include_directories(dependencies/pipo/modules/bayesfilter/src)
include_directories(dependencies/pipo/modules/finitedifferences)
include_directories(dependencies/pipo/modules/rta/src)
include_directories(dependencies/pipo/modules/rta/src/util)
include_directories(dependencies/pipo/modules/rta/src/statistics)
include_directories(dependencies/pipo/modules/rta/src/signal)
include_directories(dependencies/pipo/modules/rta/bindings/lib)
# Third party dependencies
include_directories(dependencies/third_party/json)
# Source Files
file(GLOB_RECURSE RAPIDMIX_SRC "${PROJECT_SOURCE_DIR}/src/*.cpp")
file(GLOB GVF_SRC "${PROJECT_SOURCE_DIR}/dependencies/GVF/GVF.cpp")
# Maximilian
file(GLOB MAXI_SRC "${PROJECT_SOURCE_DIR}/dependencies/Maximilian/maximilian.cpp")
file(GLOB MAXI_SRC ${MAXI_SRC} "${PROJECT_SOURCE_DIR}/dependencies/Maximilian/libs/maxiFFT.cpp")
file(GLOB MAXI_SRC ${MAXI_SRC} "${PROJECT_SOURCE_DIR}/dependencies/Maximilian/libs/fft.cpp")
#PiPo
file(GLOB_RECURSE PIPO_SRC "${PROJECT_SOURCE_DIR}/dependencies/pipo/sdk/src/*")
file(GLOB_RECURSE PIPO_SRC ${PIPO_SRC} "${PROJECT_SOURCE_DIR}/dependencies/pipo/modules/bayesfilter/src/*")
file(GLOB_RECURSE PIPO_SRC ${PIPO_SRC} "${PROJECT_SOURCE_DIR}/dependencies/pipo/modules/collection/*")
file(GLOB_RECURSE PIPO_SRC ${PIPO_SRC} "${PROJECT_SOURCE_DIR}/dependencies/pipo/modules/finitedifferences/*")
file(GLOB_RECURSE PIPO_SRC ${PIPO_SRC} "${PROJECT_SOURCE_DIR}/dependencies/pipo/modules/rta/src/util/*")
file(GLOB_RECURSE PIPO_SRC ${PIPO_SRC} "${PROJECT_SOURCE_DIR}/dependencies/pipo/modules/rta/src/signal/*")
file(GLOB_RECURSE PIPO_SRC ${PIPO_SRC} "${PROJECT_SOURCE_DIR}/dependencies/pipo/modules/rta/src/statistics/*")
list(REMOVE_ITEM PIPO_SRC "${PROJECT_SOURCE_DIR}/dependencies/pipo/modules/rta/src/signal/rta_onepole.c")
list(REMOVE_ITEM PIPO_SRC "${PROJECT_SOURCE_DIR}/dependencies/pipo/modules/rta/src/signal/rta_resample.c")
list(REMOVE_ITEM PIPO_SRC "${PROJECT_SOURCE_DIR}/dependencies/pipo/modules/rta/src/statistics/rta_cca.c")
# RapidLib
file(GLOB RAPIDLIB_SRC "${PROJECT_SOURCE_DIR}/dependencies/RapidLib/src/*.cpp")
file(GLOB RAPIDLIB_DEP "${PROJECT_SOURCE_DIR}/dependencies/RapidLib/dependencies/libsvm/libsvm.cpp")
# XMM
file(GLOB_RECURSE XMM_SRC "${PROJECT_SOURCE_DIR}/dependencies/xmm/src/*")
file(GLOB JSON_SRC "${PROJECT_SOURCE_DIR}/dependencies/third_party/jsoncpp.cpp")
# Set the source for the main library, using the groups defined above
set(RAPIDMIX_FULL_SRC ${RAPIDMIX_SRC}
${GVF_SRC}
${MAXI_SRC}
${PIPO_SRC}
${RAPIDLIB_SRC}
${RAPIDLIB_DEP}
${XMM_SRC}
${JSON_SRC}
)
add_library(RAPID-MIX_API SHARED ${RAPIDMIX_FULL_SRC})
add_executable(rapidmixTest tests/rapidMixTest.cpp )
add_executable(helloRapidMix ${PROJECT_SOURCE_DIR}/examples/HelloRapidMix/HelloRapidMix/main.cpp)
if (APPLE)
find_library(ACCELERATE Accelerate)
if (NOT ACCELERATE)
message(FATAL_ERROR "Accelearate not found")
endif()
target_link_libraries(RAPID-MIX_API ${ACCELERATE})
endif()
target_link_libraries(rapidmixTest RAPID-MIX_API)
target_link_libraries(helloRapidMix RAPID-MIX_API)
......@@ -3,11 +3,27 @@
It has been built with RAPID-MIX technologies, that make it easy to combine sensor data, machine learning algorithms and interactive audio. They provide a full set of functionalities for cross-device and cross-platform development, modular components, and cloud-based services and multimodal data storage.
## Dependencies
Use `git submodule init` followed by `git submodule update` to pull the following library dependencies.
Use `git submodule update --init --recursive` to pull the following library dependencies.
1. RapidLib
2. XMM
3. GVF
4. RepoVizz2 Client
1. XMM
1. PiPo
1. GVF
1. RepoVizz2 Client
## Documentation
Full documentation at http://www.rapidmixapi.com/
## Testing
We are using Catch for C++ testing. Look at the test fixtures in the /tests/test_projetc/test_project.xcodeproj for an example of how to implement them.
\ No newline at end of file
We are using Catch for C++ testing. Look at the test fixtures in the /tests/test_projetc/test_project.xcodeproj for an example of how to implement them.
## Building with CMake
Navigate to /RAPID-MIX_API and run this in a terminal:
`mkdir build
cd build
cmake ..
make
`
Or run the shell script: `./rmix_build_test.sh`
\ No newline at end of file
......@@ -192,7 +192,7 @@ void GVF::addGestureTemplate(GVFGesture & gestureTemplate)
config.inputDimensions = inputDimension;
gestureTemplates.push_back(gestureTemplate);
activeGestures.push_back(gestureTemplates.size());
activeGestures.push_back(int(gestureTemplates.size()));
if(minRange.size() == 0){
minRange.resize(inputDimension);
......
......@@ -225,7 +225,7 @@ template <typename T>
inline vector<T> multiplyMat(vector< vector<T> > & M1, vector< T> & Vect){
assert(Vect.size() == M1[0].size()); // columns in M1 == rows in Vect
vector<T> multiply;
initVec(multiply, Vect.size());
initVec(multiply, int(Vect.size()));
for (int i=0; i<M1.size(); i++){
multiply[i] = 0.0f;
for (int j=0; j<M1[i].size(); j++){
......@@ -269,7 +269,7 @@ inline vector<vector<float> > getRotationMatrix3d(T phi, T theta, T psi)
template <typename T>
float distance_weightedEuclidean(vector<T> x, vector<T> y, vector<T> w)
{
int count = x.size();
int count = int(x.size());
if (count <= 0) return 0;
float dist = 0.0;
for(int k = 0; k < count; k++) dist += w[k] * pow((x[k] - y[k]), 2);
......
Subproject commit 1162c2a6e89b5adaea2685b3ff2b844aa9cacff4
Subproject commit 22c4e36d58eb7f2aecf03fb8da7a07211b76432f
RapidLib @ ab5950e8
Subproject commit 337e093e00a8ed4aebd6b33bbd390aff6d1458b5
Subproject commit ab5950e8ff4c20b1c9e1ec9b8f369fcadbabdca6
Subproject commit 0643ed47778d5a4e2b95151a2836f50f382915f7
Subproject commit 9029d999f5d381645cf82ae478b3b875ec19800f
......@@ -38,7 +38,7 @@ PROJECT_NAME = "Rapid-Mix API"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "v2.0.0"
PROJECT_NUMBER = "v2.2.0"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "self:HelloRapidMix.xcodeproj">
location = "self:">
</FileRef>
</Workspace>
......@@ -16,26 +16,26 @@ int main(int argc, const char * argv[]) {
rapidmix::trainingData myData; //Create a place to hold training Data
//Setting up the first element of training data
std::vector<double> input = { 48 };
std::vector<double> output = { 130.81 };
myData.addElement(input, output);
std::vector<double> input { 48 };
std::vector<double> output { 130.81 };
myData.recordSingleElement(input, output);
//More elements
input = { 54 };
output = { 185.00 };
myData.addElement(input, output);
myData.recordSingleElement(input, output);
input = { 60 };
output = { 261.63 };
myData.addElement(input, output);
myData.recordSingleElement(input, output);
input = { 66 };
output = { 369.994 };
myData.addElement(input, output);
myData.recordSingleElement(input, output);
input = { 72 };
output = { 523.25 };
myData.addElement(input, output);
myData.recordSingleElement(input, output);
//Train the machine learning model with the data
mtofRegression.train(myData);
......
Copyright (c) 2016, Goldsmiths Creative Computing (UK, London)
All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
Neither the name of Goldsmiths nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
/*
==============================================================================
This file was auto-generated!
It contains the basic startup code for a Juce application.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
Component* createMainContentComponent();
//==============================================================================
class RAPID_JUCEApplication : public JUCEApplication
{
public:
//==============================================================================
RAPID_JUCEApplication() {}
const String getApplicationName() override { return ProjectInfo::projectName; }
const String getApplicationVersion() override { return ProjectInfo::versionString; }
bool moreThanOneInstanceAllowed() override { return true; }
//==============================================================================
void initialise (const String& commandLine) override
{
// This method is where you should put your application's initialisation code..
mainWindow = new MainWindow (getApplicationName());
}
void shutdown() override
{
// Add your application's shutdown code here..
mainWindow = nullptr; // (deletes our window)
}
//==============================================================================
void systemRequestedQuit() override
{
// This is called when the app is being asked to quit: you can ignore this
// request and let the app carry on running, or call quit() to allow the app to close.
quit();
}
void anotherInstanceStarted (const String& commandLine) override
{
// When another instance of the app is launched while this one is running,
// this method is invoked, and the commandLine parameter tells you what
// the other instance's command-line arguments were.
}
//==============================================================================
/*
This class implements the desktop window that contains an instance of
our MainContentComponent class.
*/
class MainWindow : public DocumentWindow
{
public:
MainWindow (String name) : DocumentWindow (name,
Colours::lightgrey,
DocumentWindow::allButtons)
{
setUsingNativeTitleBar (true);
setContentOwned (createMainContentComponent(), true);
setResizable (true, true);
centreWithSize (getWidth(), getHeight());
setVisible (true);
}
void closeButtonPressed() override
{
// This is called when the user tries to close this window. Here, we'll just
// ask the app to quit when this happens, but you can change this to do
// whatever you need.
JUCEApplication::getInstance()->systemRequestedQuit();
}
/* Note: Be careful if you override any DocumentWindow methods - the base
class uses a lot of them, so by overriding you might break its functionality.
It's best to do all your work in your content component instead, but if
you really have to override any DocumentWindow methods, make sure your
subclass also calls the superclass's method.
*/
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
};
private:
ScopedPointer<MainWindow> mainWindow;
};
//==============================================================================
// This macro generates the main() routine that launches the app.
START_JUCE_APPLICATION (RAPID_JUCEApplication)
/*
==============================================================================
This file was auto-generated!
==============================================================================
*/
#ifndef MAINCOMPONENT_H_INCLUDED
#define MAINCOMPONENT_H_INCLUDED
// It's important to call any headers that might
// include apple libs / headers before Juce's
// to prevent ambigious classes
#include "../../../../dependencies/Maximilian/maximilian.h"
#include "../../../../dependencies/RapidLib/src/regression.h"
#include <random>
#include <array>
#include "../JuceLibraryCode/JuceHeader.h"
class MainContentComponent;
//==============================================================================
class Oscilloscope : public Component,
private Timer
{
public:
Oscilloscope(MainContentComponent* _p) : parent(_p),
writePosition(0),
bufferSize(16384),
paintSize(256)
{
startTimer(40);
}
void pushBuffer(const float* _sampleData, int _numSamples)
{
for (int i = 0; i < _numSamples; ++i)
{
size_t pos = ++writePosition % buffer.size();
oldBuffer[pos] = buffer[pos];
buffer[pos] = _sampleData[i];
}
}
void paint(Graphics& _g) override
{
boundary = getLocalBounds();
_g.fillAll(juce::Colour(0xff000000));
Path path;
path.startNewSubPath(0, .5 * boundary.getHeight());
const float bufferYScale = .3f;
int paintPos = 2;
while (paintPos < buffer.size())
{
if (isZeroCrossing(paintPos))
{
break;
}
++paintPos;
}
const int posOffset = paintPos;
while (paintPos < buffer.size())
{
float bufferPoint = buffer[paintPos];//0.5 * std::abs(buffer[paintPos] - oldBuffer[paintPos]);
Point<float> point((paintPos - posOffset) * boundary.getWidth() / paintSize,
0.5 * ((bufferYScale * bufferPoint) + 1) * boundary.getHeight());
path.lineTo(point);
++paintPos;
}
_g.setColour(juce::Colour(0xff00ff00));
_g.strokePath(path, PathStrokeType(2.0f));
}
void mouseDrag(const MouseEvent& _event) override;
private:
//==========================================================================
void timerCallback() override
{
repaint();
}
bool isZeroCrossing(int i) const noexcept
{
jassert(i > 0);
return buffer[i] > buffer[i - 1] && buffer[i] > 0 && buffer[i - 1] < 0;
}
//==========================================================================
juce::Rectangle<int> boundary;
std::array<float, int((float)44100 / 83)> buffer;
std::array<float, int((float)44100 / 83)> oldBuffer;
std::size_t writePosition;
const int bufferSize;
const int paintSize;
MainContentComponent* const parent;
};
//==============================================================================
class MainContentComponent : public AudioAppComponent,
public Slider::Listener,
public Button::Listener
{
public:
//==========================================================================
/* Setup */
MainContentComponent():
modulationFrequency(4.1),
modulationDepth(.2),
centreFrequency(512),
resonance(2),
targetModulationFrequency(4.1),
targetModulationDepth(.2),
targetCentreFrequency(512),
targetResonance(2),
trained(false),
oscilloscope(this)
{
header.setColour(TextButton::buttonColourId, Colours::wheat);
header.setColour(TextButton::textColourOffId, Colours::white);
header.setEnabled(false);
header.setButtonText("RAPID-MIX API Example");
addAndMakeVisible(header);
sidebar.setColour(TextButton::buttonColourId, Colours::white);
sidebar.setColour(TextButton::textColourOffId, Colours::white);
sidebar.setEnabled(false);
addAndMakeVisible(sidebar);
train.setColour(TextButton::buttonColourId, Colours::wheat);
train.setColour(TextButton::textColourOffId, Colours::white);
train.setButtonText("Train");
train.addListener(this);
addAndMakeVisible(train);
randomise.setColour(TextButton::buttonColourId, Colours::wheat);
randomise.setColour(TextButton::textColourOffId, Colours::white);
randomise.setButtonText("Randomise!");
randomise.addListener(this);
addAndMakeVisible(randomise);
footer.setColour(TextButton::buttonColourId, Colours::wheat);
footer.setColour(TextButton::textColourOffId, Colours::white);
footer.setEnabled(false);
footer.setButtonText("Select the synth parameters you like, then move the mouse to an area and hold space to associate that space with that sound. Repeat with a few sounds");
addAndMakeVisible(footer);
modulationFrequencySlider.setRange(0, 4096);
modulationFrequencySlider.setSkewFactorFromMidPoint (500.0);
modulationFrequencySlider.setValue(modulationFrequency, dontSendNotification);
modulationFrequencySlider.addListener(this);
addAndMakeVisible(modulationFrequencySlider);
modulationFrequencyLabel.setText("Mod Frequency", dontSendNotification);
modulationFrequencyLabel.setColour(Label::ColourIds::textColourId, Colours::white);
modulationFrequencyLabel.attachToComponent(&modulationFrequencySlider, false);
addAndMakeVisible(modulationFrequencyLabel);
modulationIndexSlider.setRange(0., 1.);
modulationIndexSlider.setValue(modulationDepth, dontSendNotification);
modulationIndexSlider.addListener(this);
addAndMakeVisible(modulationIndexSlider);
modulationIndexLabel.setText("Mod Index", dontSendNotification);
modulationFrequencyLabel.setColour(Label::ColourIds::textColourId, Colours::white);
modulationIndexLabel.attachToComponent(&modulationIndexSlider, false);
addAndMakeVisible(modulationIndexLabel);
filterFrequencySlider.setRange(0.00001, 4096);
filterFrequencySlider.setColour(Label::ColourIds::textColourId, Colours::white);
filterFrequencySlider.setSkewFactorFromMidPoint (500.0);
filterFrequencySlider.setValue(centreFrequency, dontSendNotification);
filterFrequencySlider.addListener(this);
addAndMakeVisible(filterFrequencySlider);
filterFrequencyLabel.setText("Filter Frequency", dontSendNotification);
filterFrequencyLabel.setColour(Label::ColourIds::textColourId, Colours::white);
filterFrequencyLabel.attachToComponent(&filterFrequencySlider, false);
addAndMakeVisible(filterFrequencyLabel);
filterResonanceSlider.setRange(0.00001, 40);
filterResonanceSlider.setValue(resonance, dontSendNotification);
filterResonanceSlider.addListener(this);
addAndMakeVisible(filterResonanceSlider);
filterResonanceLabel.setText("Filter Resonance", dontSendNotification);
filterResonanceLabel.setColour(Label::ColourIds::textColourId, Colours::white);
filterResonanceLabel.attachToComponent(&filterResonanceSlider, false);
addAndMakeVisible(filterResonanceLabel);
addAndMakeVisible(oscilloscope);
setSize (800, 600);
// No inputs, two outputs
setAudioChannels (0, 2);
}
~MainContentComponent()
{
shutdownAudio();
}
//==========================================================================
/* Audio Methods */
void prepareToPlay (int _samplesPerBlockExpected, double _sampleRate) override
{
// Remember this is part of the audio callback so we must be careful
// not to do anything silly like allocating memory or dare I say wait
// for locks!
maxiSettings::setup(std::round(_sampleRate), 2, _samplesPerBlockExpected);
}
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
{
int periodLength = int(maxiSettings::sampleRate / 83);
// Get the buffers for both output channels
float* const bufferL = bufferToFill.buffer->getWritePointer(0, bufferToFill.startSample);
float* const bufferR = bufferToFill.buffer->getWritePointer(1, bufferToFill.startSample);
const double localTargetModulationFrequency = targetModulationFrequency;
const double localTargetModulationDepth = targetModulationDepth;
const double localTargetCentreFrequency = targetCentreFrequency;
const double localTargetResonance = targetResonance;
const double modulationFrequencyDelta = (localTargetModulationFrequency != modulationFrequency) ? (targetModulationFrequency - modulationFrequency) / bufferToFill.numSamples : 0;
const double modulationDepthDelta = (localTargetModulationDepth != modulationDepth) ? (targetModulationDepth - modulationDepth) / bufferToFill.numSamples : 0;
const double centreFrequencyDelta = (localTargetCentreFrequency != centreFrequency) ? (targetCentreFrequency - centreFrequency) / bufferToFill.numSamples : 0;
const double resonanceDelta = (localTargetResonance != resonance) ? (targetResonance - resonance) / bufferToFill.numSamples : 0;
// Create our PWM Maximilian noises and send the mixed output to the channels
for (int sample = 0; sample < bufferToFill.numSamples; ++sample)
{
modulationFrequency += modulationFrequencyDelta;
modulationDepth += modulationDepthDelta;
centreFrequency += centreFrequencyDelta;
resonance += resonanceDelta;
const double modulatorFrame = (modulator.sinewave(modulationFrequency) + 1.0) / 2.0 * modulationDepth + (1 - modulationDepth);
const double carrierFrame = carrier.pulse(83, modulatorFrame);
const double filteredFrame = filter.lores(carrierFrame, centreFrequency, resonance);
mixer.stereo(filteredFrame, outputs, .5);
bufferL[sample] = float(outputs[0]);
bufferR[sample] = float(outputs[1]);
}
modulationFrequency = localTargetModulationFrequency;
modulationDepth = localTargetModulationDepth;
centreFrequency = localTargetCentreFrequency;
resonance = localTargetResonance;
oscilloscope.pushBuffer(bufferL, bufferToFill.numSamples);
}
void releaseResources() override {}
//==========================================================================
/* Graphics, GUI */
void paint (Graphics& _g) override
{
// (Our component is opaque, so we must completely fill the background with a solid colour)
_g.fillAll (Colour::fromRGB(40, 40, 40));
}
// This is called once at startup and then everytime the window is resized
// Essentially all the code here just subdivides the available window space
void resized() override
{
juce::Rectangle<int> area(getLocalBounds());
const int headerFooterHeight = 36;
header.setBounds(area.removeFromTop(headerFooterHeight));
footer.setBounds(area.removeFromBottom(headerFooterHeight));
const int sidebarWidth = jmax(100, area.getWidth() / 4);
juce::Rectangle<int> sidebarArea(area.removeFromLeft(sidebarWidth));
sidebar.setBounds(sidebarArea);
const int drawingWidth = area.getWidth();
drawingArea = area.removeFromRight(drawingWidth);
oscilloscope.setBounds(drawingArea.reduced(int(sidebarWidth / 4.0)));
const int sideItemHeight = 40;
const int sideItemMargin = 5;
train.setBounds(sidebarArea.removeFromTop(sideItemHeight).reduced(sideItemMargin));
randomise.setBounds(sidebarArea.removeFromBottom(sideItemHeight).reduced(sideItemMargin));
filterResonanceSlider.setBounds(sidebarArea.removeFromBottom(sideItemHeight).reduced(2.5*sideItemMargin));
filterFrequencySlider.setBounds(sidebarArea.removeFromBottom(sideItemHeight).reduced(2.5*sideItemMargin));
modulationIndexSlider.setBounds(sidebarArea.removeFromBottom(sideItemHeight).reduced(2.5*sideItemMargin));
modulationFrequencySlider.setBounds(sidebarArea.removeFromBottom(sideItemHeight).reduced(2.5*sideItemMargin));
}
//==========================================================================
/* Interaction events via mouse and keyboard */
void mouseDrag(const MouseEvent& _event) override
{
if (trained)
{
std::vector<double> input = normaliseMouseSpace(_event.position.roundToInt(), drawingArea);
std::vector<double> output = rapidRegression.run(input);
targetModulationFrequency = output[0];
targetModulationDepth = output[1];
targetCentreFrequency = output[2];
targetResonance = output[3];
modulationFrequencySlider.setValue(targetModulationFrequency, dontSendNotification);
modulationIndexSlider.setValue(targetModulationDepth, dontSendNotification);
filterFrequencySlider.setValue(targetCentreFrequency, dontSendNotification);
filterResonanceSlider.setValue(targetResonance, dontSendNotification);
}
else
{
AlertWindow::showMessageBoxAsync(AlertWindow::AlertIconType::WarningIcon, "Error", "Please train the model before trying to run it!", "ok");
}
}
void mouseMove(const MouseEvent& _event) override
{
if (KeyPress::isKeyCurrentlyDown(KeyPress::spaceKey))
{
std::vector<double> input = normaliseMouseSpace(_event.position.roundToInt(), drawingArea);
trainingExample example;
example.input = { input[0], input[1] };
example.output = { modulationFrequency, modulationDepth, centreFrequency, resonance };
trainingSet.push_back(example);
// only do once...
if (input.size() > 0)
{
footer.setButtonText("When you have finished recorded the sounds you want, press train!");
}
}
}
std::vector<double> normaliseMouseSpace(const juce::Point<int>& _position, const juce::Rectangle<int>& _area)
{
juce::Point<int> pos = _area.getConstrainedPoint(_position);
std::vector<double> temp;
temp.resize(2);
temp[0] = double(double(pos.getX() - _area.getX()) / _area.getWidth());
temp[1] = double(double(pos.getY() - _area.getY()) / _area.getHeight());
return temp;
}
void sliderValueChanged(Slider* _slider) override
{
if (_slider == &modulationFrequencySlider)
targetModulationFrequency = modulationFrequencySlider.getValue();
else if (_slider == &modulationIndexSlider)
targetModulationDepth = modulationIndexSlider.getValue();
else if (_slider == &filterFrequencySlider)
targetCentreFrequency = filterFrequencySlider.getValue();
else if (_slider == &filterResonanceSlider)
targetResonance = filterResonanceSlider.getValue();
}
void buttonClicked(Button* _button) override
{
if (_button == &train)
{
if (trainingSet.size() > 2)
{
trained = rapidRegression.train(trainingSet);
footer.setButtonText("Now just drag the mouse to play!");
}
else
{
AlertWindow::showMessageBoxAsync(AlertWindow::AlertIconType::WarningIcon, "Error", "Please record more audio and mouse coordinate examples before training!\n\nYou can add examples by choosing mouse coordinates with the current sound and holding space whilst wiggling the mouse", "ok");
}
}
else if (_button == &randomise)
{
std::random_device random;
std::default_random_engine generator(random());
std::uniform_real_distribution<double> distribution(0.0, 1.0);
targetModulationFrequency = 4096 * distribution(generator);
targetModulationDepth = distribution(generator);
targetCentreFrequency = 4096 * distribution(generator);
targetResonance = 40 * distribution(generator);
modulationFrequencySlider.setValue(targetModulationFrequency, dontSendNotification);
modulationIndexSlider.setValue(targetModulationDepth, dontSendNotification);
filterFrequencySlider.setValue(targetCentreFrequency, dontSendNotification);
filterResonanceSlider.setValue(targetResonance, dontSendNotification);
}
}
private:
//==========================================================================
/*** AUDIO ***/
// FM Synthesis private parameters
double modulationFrequency;
double modulationDepth;
double centreFrequency;
double resonance;
double targetModulationFrequency;
double targetModulationDepth;
double targetCentreFrequency;
double targetResonance;
double outputs[2];
// Maximilian objects
maxiOsc carrier;
maxiOsc modulator;
maxiFilter filter;
maxiMix mixer;
//==========================================================================
/*** MACHINE LEARNING ***/
// Rapid regression
regression rapidRegression;
std::vector<trainingExample> trainingSet;
// Program state
bool trained;
//==========================================================================
/*** GUI ***/
// Layout
TextButton header;
TextButton sidebar;
TextButton footer;
juce::Rectangle<int> drawingArea;
// Rapidmix
TextButton train;
// Maximilian
Slider modulationFrequencySlider;
Label modulationFrequencyLabel;
Slider modulationIndexSlider;
Label modulationIndexLabel;
Slider filterFrequencySlider;
Label filterFrequencyLabel;
Slider filterResonanceSlider;
Label filterResonanceLabel;
TextButton randomise;
//==========================================================================
/*** GRAPHICS ***/
Oscilloscope oscilloscope;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};
void Oscilloscope::mouseDrag(const MouseEvent& _event)
{
parent->mouseDrag(_event);
}
// (This function is called by the app startup code to create our main component)
Component* createMainContentComponent() { return new MainContentComponent(); }
#endif // MAINCOMPONENT_H_INCLUDED
<?xml version="1.0" encoding="UTF-8"?>
<JUCERPROJECT id="Zh7kpS" name="regression_synth" projectType="guiapp" version="1.0.0"
bundleIdentifier="com.goldsmiths.rapidmix" includeBinaryInAppConfig="1"
jucerVersion="5.2.0" displaySplashScreen="1" reportAppUsage="1"
splashScreenColour="Dark" cppLanguageStandard="11" companyWebsite="rapidmixapi.com"
companyCopyright="">
<MAINGROUP id="g6MNSM" name="regression_synth">
<GROUP id="{EEA5B7C1-BCCC-64B0-259E-056090611E46}" name="Maximilian">
<GROUP id="{E20267E7-DDC5-EF6E-1EAE-C4B745764568}" name="libs">
<FILE id="h0SFJ1" name="fft.cpp" compile="1" resource="0" file="../../../dependencies/Maximilian/libs/fft.cpp"/>
<FILE id="pYguvb" name="fft.h" compile="0" resource="0" file="../../../dependencies/Maximilian/libs/fft.h"/>
<FILE id="QKNTAJ" name="maxiAtoms.cpp" compile="1" resource="0" file="../../../dependencies/Maximilian/libs/maxiAtoms.cpp"/>
<FILE id="FFoUBX" name="maxiAtoms.h" compile="0" resource="0" file="../../../dependencies/Maximilian/libs/maxiAtoms.h"/>
<FILE id="iwzAfI" name="maxiBark.cpp" compile="1" resource="0" file="../../../dependencies/Maximilian/libs/maxiBark.cpp"/>
<FILE id="yMdl88" name="maxiBark.h" compile="0" resource="0" file="../../../dependencies/Maximilian/libs/maxiBark.h"/>
<FILE id="xngR2q" name="maxiFFT.cpp" compile="1" resource="0" file="../../../dependencies/Maximilian/libs/maxiFFT.cpp"/>
<FILE id="A78B6e" name="maxiFFT.h" compile="0" resource="0" file="../../../dependencies/Maximilian/libs/maxiFFT.h"/>
<FILE id="I4uKZC" name="maxiGrains.cpp" compile="1" resource="0" file="../../../dependencies/Maximilian/libs/maxiGrains.cpp"/>
<FILE id="iWeaAV" name="maxiGrains.h" compile="0" resource="0" file="../../../dependencies/Maximilian/libs/maxiGrains.h"/>
<FILE id="Zhejq6" name="maxim.h" compile="0" resource="0" file="../../../dependencies/Maximilian/libs/maxim.h"/>
<FILE id="sYsKW9" name="maxiMFCC.cpp" compile="1" resource="0" file="../../../dependencies/Maximilian/libs/maxiMFCC.cpp"/>
<FILE id="mCQV3j" name="maxiMFCC.h" compile="0" resource="0" file="../../../dependencies/Maximilian/libs/maxiMFCC.h"/>
<FILE id="u3TFe0" name="sineTable.h" compile="0" resource="0" file="../../../dependencies/Maximilian/libs/sineTable.h"/>
</GROUP>
<FILE id="m2Fbmi" name="maximilian.h" compile="0" resource="0" file="../../../dependencies/Maximilian/maximilian.h"/>
<FILE id="R5ZjoZ" name="maximilian.cpp" compile="1" resource="0" file="../../../dependencies/Maximilian/maximilian.cpp"/>
</GROUP>
<GROUP id="{D5573091-5DD2-23C2-72F7-033E80306961}" name="RapidLib">
<GROUP id="{9F227387-ED1A-B17B-AAF3-0B2D43546269}" name="src">
<GROUP id="{A3EB9FB3-AE6F-6CA1-169C-0FF061BD4B0C}" name="emscripten">
<FILE id="o0rrsi" name="classificationEmbindings.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/src/emscripten/classificationEmbindings.h"/>
<FILE id="K95sXr" name="knnEmbindings.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/emscripten/knnEmbindings.h"/>
<FILE id="BMqYkg" name="modelSetEmbindings.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/src/emscripten/modelSetEmbindings.h"/>
<FILE id="jEjfUj" name="nnEmbindings.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/emscripten/nnEmbindings.h"/>
<FILE id="gjnhIh" name="nodeEnv.js" compile="0" resource="1" file="../../../dependencies/RapidLib/src/emscripten/nodeEnv.js"/>
<FILE id="iRFc6d" name="rapidLibPost.js" compile="0" resource="1" file="../../../dependencies/RapidLib/src/emscripten/rapidLibPost.js"/>
<FILE id="PzNivx" name="rapidStreamEmbindings.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/src/emscripten/rapidStreamEmbindings.h"/>
<FILE id="GHQaRa" name="regressionEmbindings.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/src/emscripten/regressionEmbindings.h"/>
<FILE id="PivhZh" name="seriesClassificationEmbindings.h" compile="0"
resource="0" file="../../../dependencies/RapidLib/src/emscripten/seriesClassificationEmbindings.h"/>
<FILE id="Q4hJHG" name="svmEmbindings.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/emscripten/svmEmbindings.h"/>
</GROUP>
<FILE id="VDnAfe" name="baseModel.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/baseModel.h"/>
<FILE id="x2NkmO" name="classification.cpp" compile="1" resource="1"
file="../../../dependencies/RapidLib/src/classification.cpp"/>
<FILE id="iQdC88" name="classification.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/src/classification.h"/>
<FILE id="otvyPe" name="dtw.cpp" compile="1" resource="0" file="../../../dependencies/RapidLib/src/dtw.cpp"/>
<FILE id="zh6JH2" name="dtw.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/dtw.h"/>
<FILE id="gg80D5" name="fastDTW.cpp" compile="1" resource="0" file="../../../dependencies/RapidLib/src/fastDTW.cpp"/>
<FILE id="Ga8ett" name="fastDTW.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/fastDTW.h"/>
<FILE id="d3LgeL" name="knnClassification.cpp" compile="1" resource="0"
file="../../../dependencies/RapidLib/src/knnClassification.cpp"/>
<FILE id="G5zqzw" name="knnClassification.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/src/knnClassification.h"/>
<FILE id="eEEUwv" name="modelSet.cpp" compile="1" resource="0" file="../../../dependencies/RapidLib/src/modelSet.cpp"/>
<FILE id="ieo9qs" name="modelSet.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/modelSet.h"/>
<FILE id="BLEyMT" name="neuralNetwork.cpp" compile="1" resource="0"
file="../../../dependencies/RapidLib/src/neuralNetwork.cpp"/>
<FILE id="MEILfO" name="neuralNetwork.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/neuralNetwork.h"/>
<FILE id="x3ZMq1" name="rapidStream.cpp" compile="1" resource="0" file="../../../dependencies/RapidLib/src/rapidStream.cpp"/>
<FILE id="C7Nz0H" name="rapidStream.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/rapidStream.h"/>
<FILE id="wJpnuO" name="regression.cpp" compile="1" resource="0" file="../../../dependencies/RapidLib/src/regression.cpp"/>
<FILE id="ny9hho" name="regression.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/regression.h"/>
<FILE id="QwAPCf" name="searchWindow.cpp" compile="1" resource="0"
file="../../../dependencies/RapidLib/src/searchWindow.cpp"/>
<FILE id="hRP4uS" name="searchWindow.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/searchWindow.h"/>
<FILE id="INKhcY" name="seriesClassification.cpp" compile="1" resource="0"
file="../../../dependencies/RapidLib/src/seriesClassification.cpp"/>
<FILE id="B0c8F3" name="seriesClassification.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/src/seriesClassification.h"/>
<FILE id="T74lKl" name="svmClassification.cpp" compile="1" resource="0"
file="../../../dependencies/RapidLib/src/svmClassification.cpp"/>
<FILE id="cVqdZA" name="svmClassification.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/src/svmClassification.h"/>
<FILE id="lKTpTj" name="trainingExample.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/src/trainingExample.h"/>
<FILE id="DtjqOn" name="warpPath.cpp" compile="1" resource="0" file="../../../dependencies/RapidLib/src/warpPath.cpp"/>
<FILE id="JjHvke" name="warpPath.h" compile="0" resource="0" file="../../../dependencies/RapidLib/src/warpPath.h"/>
</GROUP>
<GROUP id="{C5C7E07C-213F-8ECA-B1B6-B6BE04D35EAF}" name="dependencies">
<GROUP id="{E2AB2F69-E9EC-0A7F-8492-228002C6DB3D}" name="json">
<FILE id="vuXt8e" name="json-forwards.h" compile="0" resource="0" file="../../../dependencies/RapidLib/dependencies/json/json-forwards.h"/>
<FILE id="pVNxcf" name="json.h" compile="0" resource="0" file="../../../dependencies/RapidLib/dependencies/json/json.h"/>
</GROUP>
<GROUP id="{5C2C9ACC-885E-978B-0183-576F0DD3DA61}" name="libsvm">
<FILE id="Hh1DiU" name="libsvm.cpp" compile="1" resource="0" file="../../../dependencies/RapidLib/dependencies/libsvm/libsvm.cpp"/>
<FILE id="f5D4KB" name="libsvm.h" compile="0" resource="0" file="../../../dependencies/RapidLib/dependencies/libsvm/libsvm.h"/>
</GROUP>
<GROUP id="{655D6BCB-6FC6-1A2E-B6D7-C9170D46D415}" name="src">
<FILE id="YiXjKj" name="BayesianFilter.cpp" compile="1" resource="0"
file="../../../dependencies/RapidLib/dependencies/bayesfilter/src/BayesianFilter.cpp"/>
<FILE id="Y6sxtQ" name="BayesianFilter.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/dependencies/bayesfilter/src/BayesianFilter.h"/>
<FILE id="z3J9mx" name="filter_utilities.cpp" compile="1" resource="0"
file="../../../dependencies/RapidLib/dependencies/bayesfilter/src/filter_utilities.cpp"/>
<FILE id="GT07wW" name="filter_utilities.h" compile="0" resource="0"
file="../../../dependencies/RapidLib/dependencies/bayesfilter/src/filter_utilities.h"/>
</GROUP>
<FILE id="ibbler" name="jsoncpp.cpp" compile="1" resource="0" file="../../../dependencies/RapidLib/dependencies/jsoncpp.cpp"/>
</GROUP>
</GROUP>
<GROUP id="{24ED27E9-EF99-2FF0-3FAC-40EF82C0F046}" name="Source">
<FILE id="KK8sNt" name="MainComponent.cpp" compile="1" resource="0"
file="Source/MainComponent.cpp"/>
<FILE id="vn82oj" name="Main.cpp" compile="1" resource="0" file="Source/Main.cpp"/>
</GROUP>
</MAINGROUP>
<EXPORTFORMATS>
<VS2015 targetFolder="Builds/VisualStudio2015">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit"
isDebug="1" optimisation="1" targetName="regression_synth" headerPath="../../../../dependencies/Maximilian/"
debugInformationFormat="ProgramDatabase" enablePluginBinaryCopyStep="0"/>
<CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit"
isDebug="0" optimisation="3" targetName="regression_synth" headerPath="../../../../dependencies/Maximilian"
debugInformationFormat="ProgramDatabase" enablePluginBinaryCopyStep="0"
linkTimeOptimisation="1"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_core" path="../JUCE/modules"/>
<MODULEPATH id="juce_events" path="../JUCE/modules"/>
<MODULEPATH id="juce_graphics" path="../JUCE/modules"/>
<MODULEPATH id="juce_data_structures" path="../JUCE/modules"/>
<MODULEPATH id="juce_gui_basics" path="../JUCE/modules"/>
<MODULEPATH id="juce_gui_extra" path="../JUCE/modules"/>
<MODULEPATH id="juce_cryptography" path="../JUCE/modules"/>
<MODULEPATH id="juce_video" path="../JUCE/modules"/>
<MODULEPATH id="juce_opengl" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_basics" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_devices" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_formats" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_processors" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_utils" path="../JUCE/modules"/>
</MODULEPATHS>
</VS2015>
<XCODE_MAC targetFolder="Builds/MacOSX">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="regression_synth"
headerPath="../../../../dependencies/Maximilian" enablePluginBinaryCopyStep="1"/>
<CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="regression_synth"
headerPath="../../../../dependencies/Maximilian" enablePluginBinaryCopyStep="1"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_video" path="../JUCE/modules"/>
<MODULEPATH id="juce_opengl" path="../JUCE/modules"/>
<MODULEPATH id="juce_gui_extra" path="../JUCE/modules"/>
<MODULEPATH id="juce_gui_basics" path="../JUCE/modules"/>
<MODULEPATH id="juce_graphics" path="../JUCE/modules"/>
<MODULEPATH id="juce_events" path="../JUCE/modules"/>
<MODULEPATH id="juce_data_structures" path="../JUCE/modules"/>
<MODULEPATH id="juce_cryptography" path="../JUCE/modules"/>
<MODULEPATH id="juce_core" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_utils" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_processors" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_formats" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_devices" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_basics" path="../JUCE/modules"/>
</MODULEPATHS>
</XCODE_MAC>
<LINUX_MAKE targetFolder="Builds/LinuxMakefile">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="regression_synth"/>
<CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="regression_synth"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_video" path="../JUCE/modules"/>
<MODULEPATH id="juce_opengl" path="../JUCE/modules"/>
<MODULEPATH id="juce_gui_extra" path="../JUCE/modules"/>
<MODULEPATH id="juce_gui_basics" path="../JUCE/modules"/>
<MODULEPATH id="juce_graphics" path="../JUCE/modules"/>
<MODULEPATH id="juce_events" path="../JUCE/modules"/>
<MODULEPATH id="juce_data_structures" path="../JUCE/modules"/>
<MODULEPATH id="juce_cryptography" path="../JUCE/modules"/>
<MODULEPATH id="juce_core" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_utils" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_processors" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_formats" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_devices" path="../JUCE/modules"/>
<MODULEPATH id="juce_audio_basics" path="../JUCE/modules"/>
</MODULEPATHS>
</LINUX_MAKE>
</EXPORTFORMATS>
<MODULES>
<MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_audio_processors" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_audio_utils" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_core" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_cryptography" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_events" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_gui_extra" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_opengl" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_video" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
</MODULES>
<JUCEOPTIONS/>
<LIVE_SETTINGS>
<WINDOWS/>
</LIVE_SETTINGS>
</JUCERPROJECT>
# BitalinoRapidMix
Implementation of Bitalino EMG and a regression model powered by RapidMix in openframeworks with maximillian for audio for interesting synthesizer control / ( recursive ) mapping.
You can find the machine learning parts in `BITSequencerThread.cpp` and `RapidMixThread.h`
//
// BarChart.hpp
// RapidVisualizerOSC
//
// Created by James on 09/11/2017.
//
//
#ifndef BarChart_hpp
#define BarChart_hpp
#include <stdio.h>
#include "RealTimeGraph.hpp"
class BarChart : public RealTimeGraph
{
public:
BarChart ( GraphState* state ) : RealTimeGraph (state)
{
//
}
~BarChart ( void )
{
//
}
void updateRep ( void )
{
//
}
void drawSubGraph ( std::string subLabel, DataContainer<std::vector<double>>& data, ofRectangle subLabelRect )
{
double
minIn = 0,
minOut = 0,
maxOut = -subLabelRect.height,
startPosY = subLabelRect.height,
barSize = subLabelRect.width/data.labelData.size(),
separation = barSize/16,
halfSeparation = separation/2;
bool drawZeroSep = false;
if (data.minValue < 0)
{ // Add negative part
startPosY = subLabelRect.height/2;
minIn = -data.maxValue;
minOut = subLabelRect.height/2;
maxOut /= 2;
drawZeroSep = true;
}
for (uint32_t i = 0; i < data.labelData.size(); ++i)
{
double output = mapVals(data.labelData[i], minIn, data.maxValue, minOut, maxOut );
ofSetColor (graphColor);
ofFill();
ofDrawRectangle(subLabelRect.x + barSize * i + halfSeparation, subLabelRect.y + startPosY, barSize - separation, output );
}
if (drawZeroSep)
{
ofSetLineWidth(1.25);
ofSetColor (175,150,150);
ofDrawLine(subLabelRect.x, subLabelRect.y + startPosY,
subLabelRect.x + subLabelRect.width, subLabelRect.y + startPosY);
}
}
void update ( void )
{
//
}
};
#endif /* BarChart_hpp */
//
// Graph.hpp
// RapidVisualizerOSC
//
// Created by James on 09/11/2017.
//
//
#ifndef Graph_h
#define Graph_h
#include <string>
#include <vector>
#include <list>
#include "ofMain.h"
#include "ofxGui.h"
// TODO: add namespace, move funcs and struct to other header(s)
enum class TextAlignment {
LEFT,
CENTER,
RIGHT
};
static inline void drawTextLabel ( std::string label, ofVec2f position, ofColor labelBackgroundColor, ofColor stringColor, TextAlignment alignment, bool drawAbove )
{
uint32_t strLenPix = label.length()*8;
switch (alignment) {
case TextAlignment::LEFT:
// No exception
break;
case TextAlignment::CENTER:
position.x -= strLenPix / 2;
break;
case TextAlignment::RIGHT:
position.x -= strLenPix;
break;
default:
break;
}
ofSetColor (labelBackgroundColor);
ofRectangle bmpStringRect(position.x - 2,
position.y + ((drawAbove) ? -4 : 12) + 2,
strLenPix + 4, -12);
ofDrawRectangle(bmpStringRect);
ofSetColor (stringColor);
ofDrawBitmapString(label, position.x, position.y + ((drawAbove) ? -4 : 12));
}
static inline double mapVals ( double x, double in_min, double in_max, double out_min, double out_max )
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
template <typename T>
struct DataContainer {
T labelData;
double minValue = 0.0;
double maxValue = 1.0;
uint32_t iteratorPos = 0;
//ofColor graphColor;
void updateMinMax ( void )
{
auto mm = std::minmax_element(labelData.begin(), labelData.end());
double min = labelData[std::distance(labelData.begin(), mm.first)];
double max = labelData[std::distance(labelData.begin(), mm.second)];
if (min < minValue)
minValue = min;
if (max > maxValue)
maxValue = max;
if (fabs(min) > maxValue)
maxValue = fabs(min);
}
};
class Graph {
public:
enum graphLayout {
GRAPHS_STACKED,
GRAPHS_VERTICAL
};
struct GraphState {
std::string label;
graphLayout layout = graphLayout::GRAPHS_STACKED;
bool hasHistory = false;
ofRectangle positionAndSize;
uint32_t historySize;
};
Graph ( GraphState* state )
: state(state)
{
graphColor = ofColor(24, 219, 92);
textColor = ofColor(255, 157, 117);
}
virtual ~Graph ( void )
{
}
virtual void updateRep ( void ) = 0; // update representation
virtual void addData ( std::string subLabel, std::vector<double>& data ) = 0;
virtual void reset ( void ) = 0;
virtual void update ( void ) = 0;
virtual void draw ( void ) = 0;
virtual uint32_t getNumSubGraphs ( void ) const = 0;
protected:
GraphState *state = nullptr;
ofColor graphColor;
ofColor textColor;
};
#endif /* Graph_h */
//
// HistoryGraph.hpp
// RapidVisualizerOSC
//
// Created by James on 09/11/2017.
//
//
#ifndef HistoryGraph_h
#define HistoryGraph_h
#include "Graph.hpp"
#include <list>
class HistoryGraph : public Graph
{
public:
HistoryGraph ( GraphState* state )
: Graph(state)
{
}
~HistoryGraph ( void )
{
}
virtual void updateRep ( void ) = 0; // update representation
virtual void drawSubGraph ( std::string subLabel, DataContainer<std::list<double>>& data, ofRectangle subLabelrect ) = 0;
virtual void update ( void ) = 0;
void addData ( std::string subLabel, std::vector<double>& data )
{
if (data.size() < state->historySize)
{
//FIXME: can be sped up by using the result of this search instead of accessing by[] again
if ( subLabelData.find(subLabel) == subLabelData.end() ) {
// not found
DataContainer<std::list<double>> container;
container.labelData.resize(state->historySize);
std::fill(container.labelData.begin(), container.labelData.end(), 0.0);
subLabelData[subLabel] = container;
}
DataContainer<std::list<double>>& dataRef = subLabelData[subLabel];
list<double>& referencedList = dataRef.labelData;
while (referencedList.size() + data.size() >= state->historySize)
{
referencedList.pop_front();
}
for (int32_t i = data.size()-1; i >= 0; --i)
{
double val = data[i];
if (val < dataRef.minValue)
dataRef.minValue = val;
if (val > dataRef.maxValue)
dataRef.maxValue = val;
if (fabs(val) > dataRef.maxValue)
dataRef.maxValue = fabs(val);
referencedList.push_back(val);
}
}
}
void reset ( void )
{
subLabelData.clear();
}
void draw ( void )
{
uint32_t numElements = subLabelData.size();
uint16_t heightBetweenSubLabels = state->positionAndSize.height/numElements;
uint16_t subLabelY = 0;
ofSetColor (textColor);
ofDrawLine(state->positionAndSize.x, state->positionAndSize.y + heightBetweenSubLabels - 1.5,
state->positionAndSize.x + state->positionAndSize.width, state->positionAndSize.y + heightBetweenSubLabels - 1.5);
std::map<std::string, DataContainer<std::list<double>>>::iterator it;
for(it = subLabelData.begin(); it != subLabelData.end(); ++it)
{
std::string subLabel = it->first;
DataContainer<std::list<double>>& data = it->second;
drawSubGraph (subLabel, data, ofRectangle(state->positionAndSize.x,
state->positionAndSize.y + subLabelY + 3,
state->positionAndSize.width,
heightBetweenSubLabels - 6));
// Draw label and background
drawTextLabel(subLabel, ofVec2f(state->positionAndSize.x + state->positionAndSize.width,
state->positionAndSize.y + subLabelY),
ofColor(100, 100, 100), ofColor(textColor), TextAlignment::RIGHT, false);
// Draw max value
drawTextLabel(ofToString(data.maxValue),
ofVec2f(state->positionAndSize.x + state->positionAndSize.width/2,
state->positionAndSize.y + subLabelY),
ofColor(50, 50, 50), ofColor(255, 255, 255), TextAlignment::CENTER, false);
// Increment Y position
subLabelY += heightBetweenSubLabels;
// Draw min value
// Show actual min value?
drawTextLabel(ofToString((data.minValue < 0) ? -data.maxValue : 0),
ofVec2f(state->positionAndSize.x + state->positionAndSize.width/2,
state->positionAndSize.y + subLabelY),
ofColor(50, 50, 50), ofColor(255, 255, 255), TextAlignment::CENTER, true);
// Draw Line at bottom of graph
//ofSetLineWidth(2.0);
//ofSetColor (180,180,180);
/*ofDrawLine(state->positionAndSize.x, state->positionAndSize.y + subLabelY + 3,
state->positionAndSize.x + state->positionAndSize.width, state->positionAndSize.y + subLabelY + 3);*/
}
}
uint32_t getNumSubGraphs ( void ) const
{
return subLabelData.size();
}
protected:
std::map <std::string, DataContainer<std::list<double>>> subLabelData;
};
#endif /* HistoryGraph_h */
//
// LineGraph.hpp
// RapidVisualizerOSC
//
// Created by James on 09/11/2017.
//
//
#ifndef LineGraph_h
#define LineGraph_h
#include <stdio.h>
#include "RealTimeGraph.hpp"
class LineGraph : public RealTimeGraph
{
public:
LineGraph ( GraphState* state ) : RealTimeGraph (state)
{
//
}
~LineGraph ( void )
{
//
}
void updateRep ( void )
{
//
}
void drawSubGraph ( std::string subLabel, DataContainer<std::vector<double>>& data, ofRectangle subLabelRect )
{
double
minIn = 0,
minOut = 0,
maxOut = -subLabelRect.height,
startPosY = subLabelRect.height,
pointDistance = subLabelRect.width/data.labelData.size(),
separation = pointDistance/2;
//halfSeparation = separation/2;
bool drawZeroSep = false;
if (data.minValue < 0)
{ // Add negative part
startPosY = subLabelRect.height/2;
minIn = -data.maxValue;
minOut = subLabelRect.height/2;
maxOut /= 2;
drawZeroSep = true;
}
ofBeginShape();
ofFill();
ofVertex(subLabelRect.x, subLabelRect.y + startPosY);
double output = mapVals(data.labelData[0], minIn, data.maxValue, minOut, maxOut );
ofVertex(subLabelRect.x, subLabelRect.y + startPosY + output);
for (uint32_t i = 0; i < data.labelData.size(); ++i)
{
output = mapVals(data.labelData[i], minIn, data.maxValue, minOut, maxOut );
ofSetColor (graphColor);
ofVertex(subLabelRect.x + pointDistance * i + separation, subLabelRect.y + startPosY + output);
//ofDrawRectangle(subLabelRect.x + barSize * i + halfSeparation, subLabelRect.y + startPosY, barSize - separation, output );
}
output = mapVals(data.labelData[data.labelData.size()-1], minIn, data.maxValue, minOut, maxOut );
ofVertex(subLabelRect.x + subLabelRect.width, subLabelRect.y + startPosY + output);
ofVertex(subLabelRect.x + subLabelRect.width, subLabelRect.y + startPosY);
ofEndShape();
if (drawZeroSep)
{
ofSetLineWidth(1.25);
ofSetColor (175,150,150);
ofDrawLine(subLabelRect.x, subLabelRect.y + startPosY,
subLabelRect.x + subLabelRect.width, subLabelRect.y + startPosY);
}
}
void update ( void )
{
//
}
};
#endif /* LineGraph_h */