diff --git a/src/machineLearning/rapidXMM/rapidXMM.cpp b/src/machineLearning/rapidXMM/rapidXMM.cpp
index 9d4fc5a259a2bd63958a039ef3c0b24a138f9291..a60d032d232d393e27d24b04acb3c2452bc878d4 100644
--- a/src/machineLearning/rapidXMM/rapidXMM.cpp
+++ b/src/machineLearning/rapidXMM/rapidXMM.cpp
@@ -81,25 +81,27 @@ bool xmmTool<SingleClassModel, Model>::train(const rapidmix::trainingData& newTr
 template <class SingleClassModel, class Model>
 Json::Value xmmTool<SingleClassModel, Model>::toJSON(/*std::string modelType*/) {
   Json::Value root;
-  Json::Value metadata;
-  Json::Value modelSet;
 
-  metadata["creator"] = "Rapid API C++";
-  metadata["version"] = "v0.1.1"; //TODO: This should be a macro someplace
-  metadata["family"] = "xmm";
-  root["metadata"] = metadata;
+  root["docType"] = "rapid-mix:ml-model";
+  root["docVersion"] = RAPIDMIX_JSON_DOC_VERSION;
 
-  modelSet.append(model.toJson());
-  root["modelSet"] = modelSet;
+  Json::Value target;
+
+  target["name"] = "xmm";
+  target["version"] = "v1.0.0";
+
+  root["target"] = target;
+  root["payload"] = model.toJson();
 
   return root;
 }
 
 template <class SingleClassModel, class Model>
 bool xmmTool<SingleClassModel, Model>::fromJSON(Json::Value &jm) {
-  if (jm["metadata"]["family"].asString().compare("xmm") == 0 &&
-      jm["modelSet"].size() > 0) {
-    model.fromJson(jm["modelSet"][0]);
+  if (jm["docType"].asString().compare("rapid-mix:ml-model") == 0 &&
+      jm["target"]["name"].asString().compare("xmm") == 0 &&
+      jm["payload"].size() > 0) {
+    model.fromJson(jm["payload"]);
     model.reset();
     return true;
   }
diff --git a/tests/rapidMixTest.cpp b/tests/rapidMixTest.cpp
index f233517fe56fb3afcb39c3c950bdcffa1a205a4d..f372eaa81f088be5b5d39470a0402eb9ae890d6a 100644
--- a/tests/rapidMixTest.cpp
+++ b/tests/rapidMixTest.cpp
@@ -107,7 +107,7 @@ int main() {
         std::vector<float> f({ 1, 2, 3 });
         spHost.frames(0, 1, &f[0], 1, 1);
     }
-    std::cout << "pipo passed" << std::endl;
+    std::cout << "pipo passed." << std::endl;
 
     /////////////////////////////////////Test rapidStream signal processing
 
diff --git a/tests/src/test_rapidPiPo.cpp b/tests/src/test_rapidPiPo.cpp
index f44467e6bea777e80236aa838be314c0d1762368..185f10895f4807e4994e1406a575a9bc06916d98 100644
--- a/tests/src/test_rapidPiPo.cpp
+++ b/tests/src/test_rapidPiPo.cpp
@@ -17,6 +17,22 @@
 
 #define MAX_PATH_SIZE 256
 
+void doSomething(double time, double weight, PiPoValue *values, unsigned int size)
+{
+    std::cout << time << std::endl;
+}
+
+class Stuff {
+public:
+    Stuff() {}
+    ~Stuff() {}
+
+    void doSomething(double time, double weight, PiPoValue *values, unsigned int size)
+    {
+        std::cout << time << std::endl;
+    }
+};
+
 //=============================== ONSEG TEST =================================//
 
 SCENARIO("Test rapidPiPoHost", "[signalProcessing]")
@@ -24,23 +40,29 @@ SCENARIO("Test rapidPiPoHost", "[signalProcessing]")
     GIVEN("A rapidPiPoHost class with a rapidPiPo chain and an audio file")
     {
         maxiSample buffer;
+        Stuff stuff;
 
         // in XCode this gives the path to DerivedData folder
         // char pathStrBuf[MAX_PATH_SIZE];
         // char *cwd = getcwd(pathStrBuf, sizeof(pathStrBuf));
         // std::cout << std::string(cwd) << std::endl;
-        
+
         // but here we just add the file to the Copy File(s) Build Phase
         buffer.load("./data/DnB-loop-175BPM.wav", 0);
         // ( source : http://freesound.org/people/yewbic/sounds/40107/ )
 
         buffer.reset(); // (no real need to do this here)
-        
+
         //====================================================================//
 
         // instantiate PiPo related classes here :
-        rapidmix::signalProcessingHost host; // -> this class is located in rapidPiPoTools
-        
+        rapidmix::signalProcessingHost host;
+
+        // host.setFrameCallback(doSomething);
+        // host.setFrameCallback(stuff.doSomething);
+        // host.setFrameCallback(dynamic_cast<frameCallback>(std::bind(&Stuff::doSomething, stuff)));
+        // host.setFrameCallback(dynamic_cast<frameCallback>(Stuff::* doSomething));
+
         // if we want to add some custom PiPos to our collection :
         // #include "myCustomPiPo.h"
         // PiPoCollection::addToCollection("myCustomPiPo", new PiPoCreator<myCustomPiPo>);
@@ -50,10 +72,10 @@ SCENARIO("Test rapidPiPoHost", "[signalProcessing]")
 // #include "PiPoMaximChroma.h"
         // this one is not part of the default collection :
         // PiPoCollection::addToCollection("chroma", new PiPoCreator<PiPoMaximChroma>);
-        
+
         //*
         host.setGraph("slice:fft:sum:scale:onseg");
-        
+
         host.setAttr("slice.size", 1024);
         host.setAttr("slice.hop", 256);
         host.setAttr("slice.norm", "power");
@@ -73,7 +95,7 @@ SCENARIO("Test rapidPiPoHost", "[signalProcessing]")
         host.setAttr("onseg.startisonset", 1.);
         host.setAttr("onseg.threshold", 9.);
         host.setAttr("onseg.offthresh", -120.);
-        
+
         std::cout << "onseg threshold : ";
         std::cout << host.getDoubleAttr("onseg.threshold") << std::endl;
         std::cout << "fft mode : ";
@@ -81,7 +103,7 @@ SCENARIO("Test rapidPiPoHost", "[signalProcessing]")
         std::cout << "param names : " << std::endl;
 
         std::vector<std::string> attrs = host.getAttrNames();
-        
+
         for (int i = 0; i < attrs.size(); ++i)
         {
             std::cout << "- " << attrs[i] << std::endl;
@@ -94,7 +116,7 @@ SCENARIO("Test rapidPiPoHost", "[signalProcessing]")
         //std::string filePath = ${PROJECT_DIR};
         std::string filePath = "./data/pipo.json";
         std::cout << filePath << std::endl;
-        
+
         //host.writeJSON(filePath);
         host.readJSON(filePath);
         //host.putJSON(jj);
@@ -104,7 +126,7 @@ SCENARIO("Test rapidPiPoHost", "[signalProcessing]")
 
         // set another chain :
         // pipoHost.setChain("chroma");
-        
+
         WHEN("file is processed")
         {
             rapidmix::signalAttributes sa;
@@ -117,9 +139,9 @@ SCENARIO("Test rapidPiPoHost", "[signalProcessing]")
             sa.hasVarSize = false;
             sa.domain = 0;
             sa.maxFrames = 1;
-            
-            host.setInputStreamAttributes(sa);
-            
+
+            host.setInputSignalAttributes(sa);
+
             float value;
             for (unsigned int i = 0; i < buffer.length; ++i) {
                 value = buffer.play();
diff --git a/tests/src/test_rapidXMM.cpp b/tests/src/test_rapidXMM.cpp
index 590e78abda52f20a7ca0ea78aded95c654450abb..d80d57443829f6cdc9cebfff0a35a9ff22ef7e01 100644
--- a/tests/src/test_rapidXMM.cpp
+++ b/tests/src/test_rapidXMM.cpp
@@ -1,8 +1,3 @@
-//
-//  test_rapidXmmTools.cpp
-//  Unit tests for rapidXmmTools
-//
-
 #ifndef CATCH_CONFIG_MAIN
 #define CATCH_CONFIG_MAIN
 #endif
@@ -18,37 +13,37 @@ SCENARIO("Test GMM", "[machineLearning]")
     {
         rapidmix::xmmConfig xcfg;
         xcfg.relativeRegularization = 0.1;
-        
+
         rapidmix::trainingData myXmmData;
         std::vector<double> myXmmInput;
         std::vector<double> myXmmOutput;
-        
+
         myXmmData.startRecording("lab1");
         myXmmInput = { 0.2, 0.7 };
         myXmmData.addElement(myXmmInput, myXmmOutput);
         myXmmData.stopRecording();
-        
+
         myXmmData.startRecording("lab2");
         myXmmInput = { 0.8, 0.1 };
         myXmmData.addElement(myXmmInput, myXmmOutput);
         myXmmData.stopRecording();
-        
+
         myXmmData.writeJSON("/var/tmp/testTrainingData.json");
 
         rapidmix::xmmStaticClassification myGmm(xcfg);
-        
+
         myGmm.train(myXmmData);
-        
+
         std::string filepath = "/var/tmp/modelSetDescription";
         myGmm.writeJSON(filepath);
-        
+
         myXmmInput = { 0.2, 0.7 };
-        
+
         WHEN("GMM model is deserialized from file")
         {
             rapidmix::xmmStaticClassification myGmmFromFile;
             myGmmFromFile.readJSON(filepath);
-            
+
             THEN("compare results of original and deserialized models")
             {
                 REQUIRE(myGmm.run(myXmmInput)[0] == myGmmFromFile.run(myXmmInput)[0]);
@@ -59,7 +54,7 @@ SCENARIO("Test GMM", "[machineLearning]")
         {
             rapidmix::xmmStaticClassification myGmmFromString;
             myGmmFromString.putJSON(myGmm.getJSON());
-            
+
             THEN("compare results of original and deserialized models")
             {
                 REQUIRE(myGmm.run(myXmmInput)[0] == myGmmFromString.run(myXmmInput)[0]);
@@ -78,39 +73,39 @@ SCENARIO("Test GMR", "[machineLearning]")
     {
         rapidmix::xmmConfig xcfg;
         xcfg.relativeRegularization = 0.1;
-        
+
         rapidmix::trainingData myXmmData;
         std::vector<double> myXmmInput;
         std::vector<double> myXmmOutput;
-        
+
         myXmmData.startRecording("lab1");
         myXmmInput = { 0.2, 0.7 };
         myXmmOutput = { 1.0 };
         myXmmData.addElement(myXmmInput, myXmmOutput);
         myXmmData.stopRecording();
-        
+
         myXmmData.startRecording("lab2");
         myXmmInput = { 0.8, 0.1 };
         myXmmOutput = { 2.0 };
         myXmmData.addElement(myXmmInput, myXmmOutput);
         myXmmData.stopRecording();
-        
+
         myXmmData.writeJSON("/var/tmp/testTrainingData.json");
-        
+
         rapidmix::xmmStaticRegression myGmr(xcfg);
-        
+
         myGmr.train(myXmmData);
-        
+
         std::string filepath = "/var/tmp/modelSetDescription";
         myGmr.writeJSON(filepath);
-        
+
         myXmmInput = { 0.2, 0.7 };
-        
+
         WHEN("GMM model is deserialized from file")
         {
             rapidmix::xmmStaticClassification myGmrFromFile;
             myGmrFromFile.readJSON(filepath);
-            
+
             THEN("compare results of original and deserialized models")
             {
                 double epsilon = 0.001;
@@ -119,12 +114,12 @@ SCENARIO("Test GMR", "[machineLearning]")
                 REQUIRE(std::abs(origOut - fileOut) < epsilon);
             }
         }
-        
+
         WHEN("GMM model is deserialized from JSON stream")
         {
             rapidmix::xmmStaticClassification myGmrFromString;
             myGmrFromString.putJSON(myGmr.getJSON());
-            
+
             THEN("compare results of original and deserialized models")
             {
                 double epsilon = 0.001;
@@ -148,10 +143,10 @@ SCENARIO("Test HMM", "[machineLearning]")
         xcfg.relativeRegularization = 0.1;
         xcfg.states = 6;
         xcfg.likelihoodWindow = 10;
-        
+
         rapidmix::trainingData myXmmData;
         std::vector<double> myXmmOutput;
-        
+
         myXmmData.startRecording("lab1");
         std::vector<std::vector<double>> myXmmPhrase = {
             { 0.0, 0.0 },
@@ -179,16 +174,16 @@ SCENARIO("Test HMM", "[machineLearning]")
             myXmmData.addElement(myXmmPhrase[i], myXmmOutput);
         }
         myXmmData.stopRecording();
-        
+
         rapidmix::xmmTemporalClassification myHmm(xcfg);
 
         myHmm.train(myXmmData);
-        
+
         myXmmData.writeJSON("/var/tmp/testTrainingData.json");
-        
+
         std::string filepath = "/var/tmp/modelSetDescription";
         myHmm.writeJSON(filepath);
-        
+
         WHEN("HMM model processes the phrase it was trained with")
         {
             THEN("check its time progression output is constantly increasing")
@@ -201,16 +196,16 @@ SCENARIO("Test HMM", "[machineLearning]")
                 }
                 std::vector<double> sortedProgress = progress;
                 std::sort(sortedProgress.begin(), sortedProgress.end());
-                
+
                 REQUIRE(std::equal(progress.begin(), progress.end(), sortedProgress.begin()));
             }
         }
-        
+
         WHEN("HMM model is deserialized from file")
         {
             rapidmix::xmmTemporalClassification myHmmFromFile;
             myHmmFromFile.readJSON(filepath);
-            
+
             for (int i = 0; i < myXmmPhrase.size(); ++i) {
 
                 THEN("compare results of original and deserialized models")
@@ -219,14 +214,14 @@ SCENARIO("Test HMM", "[machineLearning]")
                 }
             }
         }
-        
+
         WHEN("HMM model is deserialized from JSON stream")
         {
             rapidmix::xmmTemporalClassification myHmmFromString;
             myHmmFromString.putJSON(myHmm.getJSON());
-            
+
             for (int i = 0; i < myXmmPhrase.size(); ++i) {
-                
+
                 THEN("compare results of original and deserialized models")
                 {
                     REQUIRE(myHmm.run(myXmmPhrase[i]) == myHmmFromString.run(myXmmPhrase[i]));
@@ -250,9 +245,9 @@ SCENARIO("Test HMR", "[machineLearning]")
         xcfg.absoluteRegularization = 0.001;
         xcfg.states = 6;
         xcfg.likelihoodWindow = 10;
-        
+
         rapidmix::trainingData myXmmData;
-        
+
         myXmmData.startRecording("lab1");
         std::vector <std::pair <std::vector<double>, std::vector<double>>> myXmmPhrase = {
             { { 0.0, 0.0 }, { 1.0 } },
@@ -276,54 +271,59 @@ SCENARIO("Test HMR", "[machineLearning]")
             { { 1.5, 2.5 }, { 19.0 } },
             { { 1.6, 2.6 }, { 20.0 } }
         };
-        
+
         for (int i = 0; i < myXmmPhrase.size(); ++i) {
             myXmmData.addElement(myXmmPhrase[i].first, myXmmPhrase[i].second);
         }
         myXmmData.stopRecording();
-        
+
         rapidmix::xmmTemporalRegression myHmr(xcfg);
-        
+
         myHmr.train(myXmmData);
-        
+
         myXmmData.writeJSON("/var/tmp/testTrainingData.json");
-        
+
         std::string filepath = "/var/tmp/modelSetDescription";
         myHmr.writeJSON(filepath);
-        
+
+        myHmr.reset();
+
         WHEN("HMR model processes the phrase it was trained with")
         {
             THEN("check its regression output is the same as the output example")
             {
                 int cnt = 0;
                 double sum = 0;
-                
+
                 for (int i = 0; i < myXmmPhrase.size(); ++i) {
                     std::vector<double> regression;
                     regression = myHmr.run(myXmmPhrase[i].first);
-                
+
                     for (int j = 0; j < regression.size(); ++j) {
                         double delta = regression[j] - myXmmPhrase[i].second[j];
                         sum += delta * delta;
                         cnt++;
                     }
                 }
-                
+
                 sum = std::sqrt(sum / cnt);
-                
+
                 // totally arbitrary epsilon value :
                 double epsilon = 1.0;
                 REQUIRE(sum <= epsilon);
             }
         }
-        
+
         WHEN("HMR model is deserialized from file")
         {
             rapidmix::xmmTemporalRegression myHmrFromFile;
             myHmrFromFile.readJSON(filepath);
-            
+
             for (int i = 0; i < myXmmPhrase.size(); ++i) {
-                
+
+                myHmr.reset();
+                myHmrFromFile.reset();
+
                 THEN("compare results of original and deserialized models")
                 {
                     int cnt = 0;
@@ -333,14 +333,14 @@ SCENARIO("Test HMR", "[machineLearning]")
                         std::vector<double> r1, r2;
                         r1 = myHmr.run(myXmmPhrase[i].first);
                         r2 = myHmrFromFile.run(myXmmPhrase[i].first);
-                    
+
                         for (int j = 0; j < r1.size(); ++j) {
                             double delta = r1[j] - r2[j];
                             sum += delta * delta;
                             cnt++;
                         }
                     }
-                    
+
                     sum = std::sqrt(sum / cnt);
 
                     // totally arbitrary epsilon value :
@@ -349,33 +349,36 @@ SCENARIO("Test HMR", "[machineLearning]")
                 }
             }
         }
-        
+
         WHEN("HMR model is deserialized from JSON stream")
         {
             rapidmix::xmmTemporalRegression myHmrFromString;
             myHmrFromString.putJSON(myHmr.getJSON());
-            
+
             for (int i = 0; i < myXmmPhrase.size(); ++i) {
-                
+
+                myHmr.reset();
+                myHmrFromString.reset();
+
                 THEN("compare results of original and deserialized models")
                 {
                     int cnt = 0;
                     double sum = 0;
-                    
+
                     for (int i = 0; i < myXmmPhrase.size(); ++i) {
                         std::vector<double> r1, r2;
                         r1 = myHmr.run(myXmmPhrase[i].first);
                         r2 = myHmrFromString.run(myXmmPhrase[i].first);
-                        
+
                         for (int j = 0; j < r1.size(); ++j) {
                             double delta = r1[j] - r2[j];
                             sum += delta * delta;
                             cnt++;
                         }
                     }
-                    
+
                     sum = std::sqrt(sum / cnt);
-                    
+
                     // totally arbitrary epsilon value :
                     double epsilon = 0.1;
                     REQUIRE(sum <= epsilon);
diff --git a/tests/src/test_trainingData.cpp b/tests/src/test_trainingData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dc36e8ddea5adf756cb4513f62f9ab2ac6a34bde
--- /dev/null
+++ b/tests/src/test_trainingData.cpp
@@ -0,0 +1,46 @@
+#ifndef CATCH_CONFIG_MAIN
+#define CATCH_CONFIG_MAIN
+#endif
+
+#include "catch.hpp"
+#include "machineLearning.h"
+
+//============================= TRAINING DATA ================================//
+
+SCENARIO("Test training sets managements", "[machineLearning]")
+{
+    GIVEN("A training set we fill in a variety of ways")
+    {
+        rapidmix::trainingData set;
+
+        set.createNewPhrase("test_label_01");
+
+        std::vector <std::pair <std::vector<double>, std::vector<double>>> phrase = {
+            { { 0.0, 0.0 }, { 9.0 } },
+            { { 1.0, 0.0 }, { 8.0 } },
+            { { 2.0, 0.0 }, { 7.0 } },
+            { { 3.0, 0.0 }, { 6.0 } },
+            { { 4.0, 0.0 }, { 5.0 } },
+            { { 5.0, 0.0 }, { 4.0 } },
+            { { 6.0, 0.0 }, { 3.0 } },
+            { { 7.0, 0.0 }, { 2.0 } },
+            { { 8.0, 0.0 }, { 1.0 } },
+            { { 9.0, 0.0 }, { 0.0 } }
+        };
+
+        for (int i = 0; i < phrase.size(); ++i) {
+            set.addElement(phrase[i].first, phrase[i].second);
+        }
+
+        WHEN("We serialize / deserialize a training set")
+        {
+            std::string js = set.getJSON();
+            std::cout << js << std::endl;
+
+            THEN("It should stay the same")
+            {
+
+            }
+        }
+    }
+}
diff --git a/tests/test_project.xcodeproj/project.pbxproj b/tests/test_project.xcodeproj/project.pbxproj
index fcfc561bd615ffc8920858cac0936da82dd3840f..f7ff94a1c3c94905fb0cf9bb59948a09dd9df169 100644
--- a/tests/test_project.xcodeproj/project.pbxproj
+++ b/tests/test_project.xcodeproj/project.pbxproj
@@ -38,6 +38,9 @@
 		311BA31E1EDC7ADE00244DAC /* maximilian.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE2C5A1F1ED8450C00E9FAFA /* maximilian.cpp */; };
 		311BA3211EDC7B2400244DAC /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 311BA3201EDC7B2400244DAC /* Accelerate.framework */; };
 		311BA3251EDCE80B00244DAC /* jsoncpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE2C5E081ED8450E00E9FAFA /* jsoncpp.cpp */; };
+		312C61BD1FE95A680085E283 /* trainingData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE2C5EC01ED8459300E9FAFA /* trainingData.cpp */; };
+		312C61CD1FE95A680085E283 /* jsoncpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE2C5E081ED8450E00E9FAFA /* jsoncpp.cpp */; };
+		312C61D41FE95A8F0085E283 /* test_trainingData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 312C61B71FE958CB0085E283 /* test_trainingData.cpp */; };
 		319C94A11FC5BFA80055BE40 /* PiPoHost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 319C93FD1FC49BAA0055BE40 /* PiPoHost.cpp */; };
 		319C94A21FC5C0C10055BE40 /* PiPoCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 319C947C1FC49D490055BE40 /* PiPoCollection.cpp */; };
 		319C94A31FC5C0DE0055BE40 /* BayesianFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 319C93ED1FC49B5C0055BE40 /* BayesianFilter.cpp */; };
@@ -148,6 +151,15 @@
 			);
 			runOnlyForDeploymentPostprocessing = 1;
 		};
+		312C61CF1FE95A680085E283 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
 		31D7B7281E6B048100917757 /* CopyFiles */ = {
 			isa = PBXCopyFilesBuildPhase;
 			buildActionMask = 12;
@@ -216,6 +228,8 @@
 		311BA2FC1EDC6F1900244DAC /* xmm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xmm.h; path = xmm/src/xmm.h; sourceTree = "<group>"; };
 		311BA3201EDC7B2400244DAC /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
 		311BA3231EDC7BA400244DAC /* DnB-loop-175BPM.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = "DnB-loop-175BPM.wav"; path = "data/DnB-loop-175BPM.wav"; sourceTree = "<group>"; };
+		312C61B71FE958CB0085E283 /* test_trainingData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_trainingData.cpp; sourceTree = "<group>"; };
+		312C61D31FE95A680085E283 /* test_trainingData */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_trainingData; sourceTree = BUILT_PRODUCTS_DIR; };
 		318E7A361FD748D900FEEB7E /* pipo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = pipo.json; path = data/pipo.json; sourceTree = "<group>"; };
 		319C93ED1FC49B5C0055BE40 /* BayesianFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BayesianFilter.cpp; path = pipo/modules/bayesfilter/src/BayesianFilter.cpp; sourceTree = "<group>"; };
 		319C93EE1FC49B5C0055BE40 /* BayesianFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BayesianFilter.h; path = pipo/modules/bayesfilter/src/BayesianFilter.h; sourceTree = "<group>"; };
@@ -448,6 +462,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		312C61CE1FE95A680085E283 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		31D7B7271E6B048100917757 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -1046,6 +1067,7 @@
 				BE2C5EE11ED8480D00E9FAFA /* test_rapidPiPo.cpp */,
 				BE2C5EE21ED8480D00E9FAFA /* test_rapidXMM.cpp */,
 				BE2C5EE31ED8480D00E9FAFA /* test_signalProcessing.cpp */,
+				312C61B71FE958CB0085E283 /* test_trainingData.cpp */,
 			);
 			path = src;
 			sourceTree = "<group>";
@@ -1079,6 +1101,7 @@
 				0BFFEF311E56085C00EF19A5 /* test_rapidXMM */,
 				0BFFEF3F1E5608C000EF19A5 /* test_signalProcessing */,
 				31D7B72C1E6B048100917757 /* test_rapidPiPo */,
+				312C61D31FE95A680085E283 /* test_trainingData */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -1154,6 +1177,23 @@
 			productReference = 0BFFEF3F1E5608C000EF19A5 /* test_signalProcessing */;
 			productType = "com.apple.product-type.tool";
 		};
+		312C61B91FE95A680085E283 /* test_trainingData */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 312C61D01FE95A680085E283 /* Build configuration list for PBXNativeTarget "test_trainingData" */;
+			buildPhases = (
+				312C61BA1FE95A680085E283 /* Sources */,
+				312C61CE1FE95A680085E283 /* Frameworks */,
+				312C61CF1FE95A680085E283 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = test_trainingData;
+			productName = test_XMM;
+			productReference = 312C61D31FE95A680085E283 /* test_trainingData */;
+			productType = "com.apple.product-type.tool";
+		};
 		31D7B7121E6B048100917757 /* test_rapidPiPo */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = 31D7B7291E6B048100917757 /* Build configuration list for PBXNativeTarget "test_rapidPiPo" */;
@@ -1211,6 +1251,7 @@
 				31D7B7121E6B048100917757 /* test_rapidPiPo */,
 				0BFFEF301E56085C00EF19A5 /* test_rapidXMM */,
 				0BFFEF3E1E5608C000EF19A5 /* test_signalProcessing */,
+				312C61B91FE95A680085E283 /* test_trainingData */,
 			);
 		};
 /* End PBXProject section */
@@ -1310,6 +1351,16 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		312C61BA1FE95A680085E283 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				312C61D41FE95A8F0085E283 /* test_trainingData.cpp in Sources */,
+				312C61BD1FE95A680085E283 /* trainingData.cpp in Sources */,
+				312C61CD1FE95A680085E283 /* jsoncpp.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		31D7B7131E6B048100917757 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -1426,6 +1477,22 @@
 			};
 			name = Release;
 		};
+		312C61D11FE95A680085E283 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		312C61D21FE95A680085E283 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
 		31D7B72A1E6B048100917757 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -1576,6 +1643,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		312C61D01FE95A680085E283 /* Build configuration list for PBXNativeTarget "test_trainingData" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				312C61D11FE95A680085E283 /* Debug */,
+				312C61D21FE95A680085E283 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		31D7B7291E6B048100917757 /* Build configuration list for PBXNativeTarget "test_rapidPiPo" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (