zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 2768767392a790991a67ddf1b60d6f859c47bbe3
parent 72d1b5378cdcb977ae6cf7673dedb39d67efd5c7
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Wed, 26 Aug 2009 09:29:48 -0400

Added some tests for Microtonal

Fixed: bug in microtonal, saving and loading Pinvertupdowncenter is now
a 127 variable rather than a bool

Diffstat:
Msrc/Misc/Microtonal.cpp | 59++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/Misc/Microtonal.h | 47+++++++++++++++++++++++++++++++----------------
Msrc/Tests/CMakeLists.txt | 1+
Asrc/Tests/MicrotonalTest.h | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Tests/make.sh | 5+++--
5 files changed, 244 insertions(+), 25 deletions(-)

diff --git a/src/Misc/Microtonal.cpp b/src/Misc/Microtonal.cpp @@ -78,7 +78,7 @@ Microtonal::~Microtonal() /* * Get the size of the octave */ -unsigned char Microtonal::getoctavesize() +unsigned char Microtonal::getoctavesize() const { if (Penabled!=0) return(octavesize); else return(12); @@ -87,7 +87,7 @@ unsigned char Microtonal::getoctavesize() /* * Get the frequency according the note number */ -REALTYPE Microtonal::getnotefreq(int note,int keyshift) +REALTYPE Microtonal::getnotefreq(int note,int keyshift) const { // in this function will appears many times things like this: // var=(a+b*100)%b @@ -166,6 +166,49 @@ REALTYPE Microtonal::getnotefreq(int note,int keyshift) }; }; +bool Microtonal::operator==(const Microtonal &micro) const +{ + return(!(*this!=micro)); +} + +/**\TODO remove printfs once testing is done +//A simple macro to test equality MiCRotonal EQuals (not the perfect approach, but good enough for debug) +#define MCREQ( x ) if(x!=micro.x){printf("%d\n",__LINE__);return true;} +//for floats +#define FMCREQ( x ) if(!((x<micro.x+0.0001)&&(x>micro.x-0.0001))){printf("%d\n",__LINE__);return true;} +bool Microtonal::operator!=(const Microtonal &micro) const +{ + MCREQ(Pinvertupdown); + MCREQ(Pinvertupdowncenter); + MCREQ(octavesize); + MCREQ(Penabled); + MCREQ(PAnote); + FMCREQ(PAfreq); + MCREQ(Pscaleshift); + + MCREQ(Pfirstkey); + MCREQ(Plastkey); + MCREQ(Pmiddlenote); + MCREQ(Pmapsize); + MCREQ(Pmappingenabled); + + for (int i=0;i<128;i++) + MCREQ(Pmapping[i]); + + for (int i=0;i<octavesize;i++) { + FMCREQ(octave[i].tuning); + MCREQ(octave[i].type); + MCREQ(octave[i].x1); + MCREQ(octave[i].x2); + } + if(strcmp((const char *)this->Pname,(const char *)micro.Pname)) + {printf("%d\n",__LINE__); return true;} + if(strcmp((const char *)this->Pcomment,(const char *)micro.Pcomment)) + {printf("%d\n",__LINE__);return true;} + MCREQ(Pglobalfinedetune); + return false; +} + /* * Convert a line to tunings; returns -1 if it ok @@ -411,13 +454,13 @@ int Microtonal::loadkbm(const char *filename) -void Microtonal::add2XML(XMLwrapper *xml) +void Microtonal::add2XML(XMLwrapper *xml)const { xml->addparstr("name",(char *) Pname); xml->addparstr("comment",(char *) Pcomment); xml->addparbool("invert_up_down",Pinvertupdown); - xml->addparbool("invert_up_down_center",Pinvertupdowncenter); + xml->addpar("invert_up_down_center",Pinvertupdowncenter); xml->addparbool("enabled",Penabled); xml->addpar("global_fine_detune",Pglobalfinedetune); @@ -456,6 +499,7 @@ void Microtonal::add2XML(XMLwrapper *xml) xml->addpar("degree",Pmapping[i]); xml->endbranch(); }; + xml->endbranch(); xml->endbranch(); }; @@ -466,7 +510,7 @@ void Microtonal::getfromXML(XMLwrapper *xml) xml->getparstr("comment",(char *) Pcomment,MICROTONAL_MAX_NAME_LEN); Pinvertupdown=xml->getparbool("invert_up_down",Pinvertupdown); - Pinvertupdowncenter=xml->getparbool("invert_up_down_center",Pinvertupdowncenter); + Pinvertupdowncenter=xml->getpar127("invert_up_down_center",Pinvertupdowncenter); Penabled=xml->getparbool("enabled",Penabled); Pglobalfinedetune=xml->getpar127("global_fine_detune",Pglobalfinedetune); @@ -512,7 +556,8 @@ void Microtonal::getfromXML(XMLwrapper *xml) }; -int Microtonal::saveXML(char *filename) + +int Microtonal::saveXML(const char *filename)const { XMLwrapper *xml=new XMLwrapper(); @@ -525,7 +570,7 @@ int Microtonal::saveXML(char *filename) return(result); }; -int Microtonal::loadXML(char *filename) +int Microtonal::loadXML(const char *filename) { XMLwrapper *xml=new XMLwrapper(); if (xml->loadXMLfile(filename)<0) { diff --git a/src/Misc/Microtonal.h b/src/Misc/Microtonal.h @@ -43,18 +43,17 @@ public: void defaults(); /**Calculates the frequency for a given note */ - REALTYPE getnotefreq(int note,int keyshift); + REALTYPE getnotefreq(int note,int keyshift) const; //Parameters - /**if the keys are inversed (the pitch is lower to keys from the right direction) \todo figure out why this is not a bool*/ + /**if the keys are inversed (the pitch is lower to keys from the right direction)*/ unsigned char Pinvertupdown; /**the central key of the inversion*/ unsigned char Pinvertupdowncenter; - /**0 for 12 key temperate scale, 1 for microtonal - * \todo find one good reason why this is not a bool*/ + /**0 for 12 key temperate scale, 1 for microtonal*/ unsigned char Penabled; /**the note of "A" key*/ @@ -70,35 +69,51 @@ public: unsigned char Pfirstkey; unsigned char Plastkey; - //The middle note where scale degree 0 is mapped to + /**The middle note where scale degree 0 is mapped to*/ unsigned char Pmiddlenote; - //Map size + /**Map size*/ unsigned char Pmapsize; - //Mapping ON/OFF + /**Mapping ON/OFF*/ unsigned char Pmappingenabled; - //Mapping (keys) + /**Mapping (keys)*/ short int Pmapping[128]; + /**Fine detune to be applied to all notes*/ unsigned char Pglobalfinedetune; // Functions - /** Return the current octave size - * \todo why is this not an int?*/ - unsigned char getoctavesize(); + /** Return the current octave size*/ + unsigned char getoctavesize() const; + /**Convert tunning to string*/ void tuningtoline(int n,char *line,int maxn); - int loadscl(const char *filename);//load the tunnings from a .scl file - int loadkbm(const char *filename);//load the mapping from .kbm file + /**load the tunnings from a .scl file*/ + int loadscl(const char *filename); + /**load the mapping from .kbm file*/ + int loadkbm(const char *filename); + /**Load text into the internal tunings + * + *\todo better description*/ int texttotunings(const char *text); + /**Load text into the internal mappings + * + *\todo better description*/ void texttomapping(const char *text); + + /**Name of Microtonal tuning*/ unsigned char *Pname; + /**Comment about the tuning*/ unsigned char *Pcomment; - void add2XML(XMLwrapper *xml); + void add2XML(XMLwrapper *xml)const; void getfromXML(XMLwrapper *xml); - int saveXML(char *filename); - int loadXML(char *filename); + int saveXML(const char *filename)const; + int loadXML(const char *filename); + + //simple operators primarily for debug + bool operator==(const Microtonal &micro) const; + bool operator!=(const Microtonal &micro) const; private: int linetotunings(unsigned int nline,const char *line); diff --git a/src/Tests/CMakeLists.txt b/src/Tests/CMakeLists.txt @@ -1,3 +1,4 @@ unit_test(ControllerTest ControllerTest.h "") unit_test(EchoTest EchoTest.h "") unit_test(SampleTest SampleTest.h "") +unit_test(MicrotonalTest MicrotonalTest.h "") diff --git a/src/Tests/MicrotonalTest.h b/src/Tests/MicrotonalTest.h @@ -0,0 +1,157 @@ +/* + ZynAddSubFX - a software synthesizer + + MicrotonalTest.h - CxxTest for Misc/Microtonal + Copyright (C) 2009-2009 Mark McCurry + Author: Mark McCurry + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program 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 (version 2 or later) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#include <cxxtest/TestSuite.h> +#include <iostream> +#include "../Misc/Microtonal.h" +#include <cstring> +#include <string> + +using namespace std; + +class MicrotonalTest : public CxxTest::TestSuite +{ +public: + void setUp() { + testMicro=new Microtonal(); + } + + void tearDown() { + delete testMicro; + } + + //Verifies that the object is initialized correctly + void testinit() { + TS_ASSERT_EQUALS(testMicro->Pinvertupdown, 0 ); + TS_ASSERT_EQUALS(testMicro->Pinvertupdowncenter, 60 ); + TS_ASSERT_EQUALS(testMicro->getoctavesize(), 12 ); + TS_ASSERT_EQUALS(testMicro->Penabled, 0 ); + TS_ASSERT_EQUALS(testMicro->PAnote, 69 ); + TS_ASSERT_EQUALS(testMicro->PAfreq, 440.0); + TS_ASSERT_EQUALS(testMicro->Pscaleshift, 64 ); + TS_ASSERT_EQUALS(testMicro->Pfirstkey, 0 ); + TS_ASSERT_EQUALS(testMicro->Plastkey, 127 ); + TS_ASSERT_EQUALS(testMicro->Pmiddlenote, 60 ); + TS_ASSERT_EQUALS(testMicro->Pmapsize, 12 ); + TS_ASSERT_EQUALS(testMicro->Pmappingenabled, 0 ); + TS_ASSERT_EQUALS(testMicro->Pglobalfinedetune, 64 ); + + TS_ASSERT_EQUALS(string((const char *)testMicro->Pname),"12tET"); + TS_ASSERT_EQUALS(string((const char *)testMicro->Pcomment),"Equal Temperament 12 notes per octave"); + + for (int i=0;i<128;i++) + TS_ASSERT_EQUALS(testMicro->Pmapping[i], i); + + TS_ASSERT_DELTA(testMicro->getnotefreq(19,0),24.4997,0.0001); + } + + //performs basic sanity check with the == and != operators + void testeqeq(){ + Microtonal other; + TS_ASSERT(*testMicro==other);//both are constructed the same, so they should be equal + other.PAfreq=220.0; + TS_ASSERT(*testMicro!=other);//other is now different + } + + //Tests saving/loading to XML + void testXML() { + //Gah, the XMLwrapper is a twisted maze + testMicro->Penabled=1; + XMLwrapper xml; + xml.beginbranch("Dummy"); //this should not be needed, but odd behavior + //seems to exist from MICROTONAL being on the + //top of the stack + xml.beginbranch("MICROTONAL"); + testMicro->add2XML(&xml); + xml.endbranch(); + xml.endbranch();//this will cause the system to complain about + //stack errors + + char *tmp=xml.getXMLdata(); + //printf("%s",tmp); + Microtonal other; + + cout << (char*)testMicro->Pname << " vs1 " + << (char*)other.Pname << endl; + + other.Penabled=1; + strcpy((char *)other.Pname,"Myname");//will be nicer with strings + + cout << (char*)testMicro->Pname << " vs1.5 " + << (char*)other.Pname << endl; + + TS_ASSERT(*testMicro!=other);//sanity check + + TS_ASSERT(xml.enterbranch("Dummy")); + TS_ASSERT(xml.enterbranch("MICROTONAL")); + //printf("%s",tmp); + + other.getfromXML(&xml); //failure here + xml.exitbranch(); + xml.exitbranch(); + char *tmpo=xml.getXMLdata(); + + cout << (char*)testMicro->Pname << " vs2 " + << (char*)other.Pname << endl; //shows error here + + //printf("%s",tmpo); + TS_ASSERT(!strcmp(tmp,tmpo)); //these should be equal, but there seems + //to be one line that is duplicated + //(I think in one of the reads) + free(tmp); + free(tmpo); + + TS_ASSERT(*testMicro==other); //cxxTest sees error here + cout << (char*)testMicro->Pname << " vs3 " + << (char*)other.Pname << endl; + + } + + /**\todo Test Saving/loading from file*/ + //void testSaveLoad() {} + + //Test texttomapping TODO finish + void testTextToMapping() { + //the mapping is from old documentation for "Intense Diatonic" scale + const char *mapping[12]= + {"0","x","1","x","2","3","x","4","x","5","x","6"}; + //for(int i=0;i<20;++i) + // cout << i << ':' << testMicro->getnotefreq(i,0) << endl; + // + // octave size == 7 + // find dead notes + } + //Test texttotunings TODO finish + void testTextToTunings() { + //the tuning is from old documentation for "Intense Diatonic" scale + const char *tuning[7]={"9/8","5/4","4/3","3/2","5/3","15/8","2/1"}; + const int numTunings=7; + //for(int i=0;i<20;++i) + // cout << i << ':' << testMicro->getnotefreq(i,0) << endl; + // go to middle key and verify the proportions + + } + /**\TODO test loading from scl and kbm files*/ + +private: + Microtonal *testMicro; + +}; diff --git a/src/Tests/make.sh b/src/Tests/make.sh @@ -1,5 +1,6 @@ cd ../ make cd Tests -cxxtestgen.py --error-printer -o runner.cpp SampleTest.h EchoTest.h ControllerTest.h -g++ -g -o runner runner.cpp ../Samples/AuSample.o ../Samples/Sample.o ../Effects/Echo.o ../Effects/Effect.o ../Controls/Control.o ../Controls/DelayCtl.o ../Params/Controller.o ../Misc/XMLwrapper.o ../Misc/Config.o ../Misc/Util.o -lmxml -lm -lz -lpthread +#cxxtestgen.py --error-printer -o runner.cpp SampleTest.h EchoTest.h ControllerTest.h MicrotonalTest.h +cxxtestgen.py --error-printer -o runner.cpp MicrotonalTest.h +g++ -g -o runner runner.cpp ../Samples/AuSample.o ../Samples/Sample.o ../Effects/Echo.o ../Effects/Effect.o ../Controls/Control.o ../Controls/DelayCtl.o ../Params/Controller.o ../Misc/XMLwrapper.o ../Misc/Config.o ../Misc/Util.o ../Misc/Microtonal.o -lmxml -lm -lz -lpthread