summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/Makefile.am.drumgizmo4
-rw-r--r--src/audiofile.cc4
-rw-r--r--src/audiofile.h4
-rw-r--r--src/drumkit.h3
-rw-r--r--src/drumkitparser.cc12
-rw-r--r--src/instrument.cc23
-rw-r--r--src/instrument.h8
-rw-r--r--src/instrumentparser.cc16
-rw-r--r--src/powerlist.cc219
-rw-r--r--src/powerlist.h57
-rw-r--r--src/sample.h1
-rw-r--r--src/versionstr.cc150
-rw-r--r--src/versionstr.h112
14 files changed, 612 insertions, 5 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 197485b..e686ec0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,6 +29,7 @@ EXTRA_DIST = \
semaphore.h \
thread.h \
velocity.h \
+ versionstr.h \
\
audiofile.cc \
audioinputengine.cc \
@@ -56,4 +57,5 @@ EXTRA_DIST = \
saxparser.cc \
semaphore.cc \
thread.cc \
- velocity.cc
+ velocity.cc \
+ versionstr.cc \ No newline at end of file
diff --git a/src/Makefile.am.drumgizmo b/src/Makefile.am.drumgizmo
index 606ed27..47d54a2 100644
--- a/src/Makefile.am.drumgizmo
+++ b/src/Makefile.am.drumgizmo
@@ -18,10 +18,12 @@ DRUMGIZMO_SOURCES = \
$(top_srcdir)/src/midimapper.cc \
$(top_srcdir)/src/mutex.cc \
$(top_srcdir)/src/path.cc \
+ $(top_srcdir)/src/powerlist.cc \
$(top_srcdir)/src/sample.cc \
$(top_srcdir)/src/semaphore.cc \
$(top_srcdir)/src/saxparser.cc \
$(top_srcdir)/src/thread.cc \
- $(top_srcdir)/src/velocity.cc
+ $(top_srcdir)/src/velocity.cc \
+ $(top_srcdir)/src/versionstr.cc
DRUMGIZMO_LIBS = $(SNDFILE_LIBS) $(EXPAT_LIBS) \ No newline at end of file
diff --git a/src/audiofile.cc b/src/audiofile.cc
index 511df27..37fb5cc 100644
--- a/src/audiofile.cc
+++ b/src/audiofile.cc
@@ -171,7 +171,7 @@ void AudioFile::reset()
mutex.unlock();
}
-void AudioFile::load()
+void AudioFile::load(int num_samples)
{
/*
Lazy load of drum kits
@@ -191,6 +191,8 @@ void AudioFile::load()
size = sf_info.frames;
+ if(num_samples != ALL_SAMPLES && (int)size > num_samples) size = num_samples;
+
sample_t* data = new sample_t[size];
size = sf_read_float(fh, data, size);
diff --git a/src/audiofile.h b/src/audiofile.h
index 46c9285..20ffdf3 100644
--- a/src/audiofile.h
+++ b/src/audiofile.h
@@ -67,12 +67,14 @@
#define LAZYLOAD
+#define ALL_SAMPLES -1
+
class AudioFile {
public:
AudioFile(std::string filename);
~AudioFile();
- void load();
+ void load(int num_samples = ALL_SAMPLES);
void unload();
bool isLoaded();
diff --git a/src/drumkit.h b/src/drumkit.h
index 2ed558d..c1e5a69 100644
--- a/src/drumkit.h
+++ b/src/drumkit.h
@@ -32,6 +32,7 @@
#include "channel.h"
#include "instrument.h"
+#include "versionstr.h"
class DrumKitParser;
class DrumKit {
@@ -55,6 +56,8 @@ private:
std::string _name;
std::string _description;
+
+ VersionStr _version;
};
#endif/*__DRUMGIZMO_DRUMKIT_H__*/
diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc
index 9100b5b..d838346 100644
--- a/src/drumkitparser.cc
+++ b/src/drumkitparser.cc
@@ -60,6 +60,18 @@ void DrumKitParser::startTag(std::string name,
if(attr.find("description") != attr.end())
kit._description = attr["description"];
+
+ if(attr.find("version") != attr.end()) {
+ try {
+ kit._version = VersionStr(attr["version"]);
+ } catch(const char *err) {
+ ERR(kitparser, "Error parsing version number: %s, using 1.0\n", err);
+ kit._version = VersionStr(1,0,0);
+ }
+ } else {
+ WARN(kitparser, "Missing version number, assuming 1.0\n");
+ kit._version = VersionStr(1,0,0);
+ }
}
if(name == "channels") {}
diff --git a/src/instrument.cc b/src/instrument.cc
index 7232431..3b357eb 100644
--- a/src/instrument.cc
+++ b/src/instrument.cc
@@ -34,6 +34,10 @@
#include "sample.h"
#include "configuration.h"
+#ifdef EXPERIMENTAL
+#define NEW_ALGORITHM
+#endif
+
Instrument::Instrument()
{
DEBUG(instrument, "new %p\n", this);
@@ -62,6 +66,8 @@ bool Instrument::isValid()
Sample *Instrument::sample(level_t level, size_t pos)
{
+ Sample *sample = NULL;
+
if(Conf::enable_velocity_modifier == false) {
mod = 1.0;
lastpos = 0;
@@ -81,24 +87,39 @@ Sample *Instrument::sample(level_t level, size_t pos)
if(mod > 1.0) mod = 1.0;
}
+#ifdef NEW_ALGORITHM
+ sample = powerlist.get(level * mod);
+#else
// printf("Find level %f\n", level);
std::vector<Sample*> s = samples.get(level * mod);
if(s.size() == 0) return NULL;
size_t idx = rand()%(s.size());
+ sample = s[idx];
+#endif/*NEW_ALGORITHM*/
if(Conf::enable_velocity_modifier) {
lastpos = pos;
mod *= Conf::velocity_modifier_weight;
}
- return s[idx];
+ return sample;
}
void Instrument::addSample(level_t a, level_t b, Sample *s)
{
samples.insert(a, b, s);
+#ifdef NEW_ALGORITHM
+ powerlist.add(s);
+#endif/*NEW_ALGORITHM*/
}
+void Instrument::finalise()
+{
+#ifdef NEW_ALGORITHM
+ powerlist.finalise();
+#endif/*NEW_ALGORITHM*/
+}}
+
std::string Instrument::name()
{
return _name;
diff --git a/src/instrument.h b/src/instrument.h
index a302412..b7ddeea 100644
--- a/src/instrument.h
+++ b/src/instrument.h
@@ -31,8 +31,10 @@
#include <vector>
#include "rangemap.h"
+#include "powerlist.h"
#include "sample.h"
+#include "versionstr.h"
class InstrumentParser;
class Instrument {
@@ -61,8 +63,14 @@ private:
std::string _group;
std::string _name;
std::string _description;
+
+ VersionStr _version;
+
RangeMap<level_t, Sample*> samples;
+ PowerList powerlist;
+
void addSample(level_t a, level_t b, Sample *s);
+ void finalise(); ///< Signal instrument that no more samples will be added.
std::vector<Sample*> samplelist;
diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc
index 15195e1..454877f 100644
--- a/src/instrumentparser.cc
+++ b/src/instrumentparser.cc
@@ -57,6 +57,18 @@ void InstrumentParser::startTag(std::string name,
if(attr.find("description") != attr.end())
instrument._description = attr["description"];
+
+ if(attr.find("version") != attr.end()) {
+ try {
+ instrument._version = VersionStr(attr["version"]);
+ } catch(const char *err) {
+ ERR(instrparser, "Error parsing version number: %s, using 1.0\n", err);
+ instrument._version = VersionStr(1,0,0);
+ }
+ } else {
+ WARN(instrparser, "Missing version number, assuming 1.0\n");
+ instrument._version = VersionStr(1,0,0);
+ }
}
if(name == "samples") {
@@ -147,6 +159,10 @@ void InstrumentParser::endTag(std::string name)
instrument.samplelist.push_back(s);
s = NULL;
}
+
+ if(name == "instrument") {
+ instrument.finalise();
+ }
}
int InstrumentParser::readData(char *data, size_t size)
diff --git a/src/powerlist.cc b/src/powerlist.cc
new file mode 100644
index 0000000..a298927
--- /dev/null
+++ b/src/powerlist.cc
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * powerlist.cc
+ *
+ * Sun Jul 28 19:45:48 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "powerlist.h"
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include <hugin.hpp>
+
+#define SIZE 500
+
+// Box–Muller transform.
+// See: http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
+float box_muller_transform(float mean, float stddev)
+{
+ float U1 = (float)rand() / (float)RAND_MAX;
+ float U2 = (float)rand() / (float)RAND_MAX;
+
+ float x = sqrt(-2.0 * log(U1)) * cos(2.0 * M_PI * U2);
+
+ return mean + stddev * x;
+}
+
+PowerList::PowerList()
+{
+ power_max = 0;
+}
+
+#define THRES 1.0
+
+void PowerList::add(Sample *sample)
+{
+ PowerListItem item;
+ item.power = -1;
+ item.sample = sample;
+
+ samples.push_back(item);
+}
+
+Channel *PowerList::getMasterChannel()
+{
+ std::map<Channel *, int> count;
+
+ std::vector<PowerListItem>::iterator si = samples.begin();
+ while(si != samples.end()) {
+ PowerListItem &item = *si;
+ Sample *sample = item.sample;
+
+ Channel *max_channel = NULL;
+ sample_t max_val = 0;
+
+ // DEBUG(rand, "Sample: %s\n", sample->name.c_str());
+
+ size_t ci = 0;
+ AudioFiles::iterator ai = sample->audiofiles.begin();
+ while(ai != sample->audiofiles.end()) {
+ Channel *c = ai->first;
+ AudioFile *af = ai->second;
+
+ af->load(SIZE);
+
+ float silence = 0;
+ size_t silence_length = 4;
+ for(size_t s = af->size; s > 0 && s > af->size - silence_length; s--) {
+ silence += af->data[s];
+ }
+ silence /= silence_length;
+
+ size_t s = 0;
+ for(; s < af->size; s++) {
+ float val = af->data[s] * af->data[s] * (1.0 / (float)(s+1));
+ if(val > max_val) {
+ max_val = val;
+ max_channel = c;
+ break;
+ }
+ }
+
+ af->unload();
+
+ ai++;
+ ci++;
+ }
+
+ if(max_channel) {
+ if(count.find(max_channel) == count.end()) count[max_channel] = 0;
+ count[max_channel]++;
+ }
+
+ si++;
+ }
+
+ Channel *master = NULL;
+ int max_count = -1;
+
+ std::map<Channel *, int>::iterator ci = count.begin();
+ while(ci != count.end()) {
+ if(ci->second > max_count &&
+ strstr(ci->first->name.c_str(), "Alesis") == 0) {
+ master = ci->first;
+ max_count = ci->second;
+ }
+ ci++;
+ }
+
+ return master;
+}
+
+void PowerList::finalise()
+{
+ Channel *master_channel = getMasterChannel();
+
+ if(master_channel == NULL) {
+ ERR(rand, "No master channel found!\n");
+ return; // This should not happen...
+ }
+
+ DEBUG(rand, "Master channel: %s\n", master_channel->name.c_str());
+
+ std::vector<PowerListItem>::iterator si = samples.begin();
+ while(si != samples.end()) {
+ PowerListItem &item = *si;
+ Sample *sample = item.sample;
+
+ DEBUG(rand, "Sample: %s\n", sample->name.c_str());
+
+ AudioFile *master = NULL;
+
+ AudioFiles::iterator afi = sample->audiofiles.begin();
+ while(afi != sample->audiofiles.end()) {
+ if(afi->first->name == master_channel->name) {
+ master = afi->second;
+ break;
+ }
+ afi++;
+ }
+
+ if(master == NULL) {
+ si++;
+ continue;
+ }
+
+ master->load();
+
+ float power = 0;
+ size_t s = 0;
+ for(; s < SIZE && s < master->size; s++) {
+ power += master->data[s] * master->data[s];
+ }
+
+ power = sqrt(power);
+
+ if(power > power_max) power_max = power;
+
+ item.power = power;
+
+ DEBUG(rand, " - power: %f\n", power);
+
+ si++;
+ }
+}
+
+Sample *PowerList::get(level_t level)
+{
+ Sample *sample = NULL;
+ float power = 0;
+
+ float mean = level * power_max;
+ float stddev = power_max / samples.size() * 2;
+
+ float lvl = box_muller_transform(mean, stddev);
+
+ DEBUG(rand, "lvl: %f (mean: %.2f, stddev: %.2f)\n",
+ lvl, mean, stddev);
+
+ std::vector<PowerListItem>::iterator i = samples.begin();
+ while(i != samples.end()) {
+ if(sample == NULL) {
+ sample = i->sample;
+ power = i->power;
+ }
+
+ if(fabs(i->power - lvl) < fabs(power - lvl)) {
+ sample = i->sample;
+ power = i->power;
+ }
+
+ i++;
+ }
+
+ DEBUG(rand, "Found power %f\n", power);
+
+ return sample;
+}
diff --git a/src/powerlist.h b/src/powerlist.h
new file mode 100644
index 0000000..0bcd11c
--- /dev/null
+++ b/src/powerlist.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * powerlist.h
+ *
+ * Sun Jul 28 19:45:47 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __DRUMGIZMO_POWERLIST_H__
+#define __DRUMGIZMO_POWERLIST_H__
+
+#include <vector>
+
+#include "sample.h"
+
+class PowerList {
+public:
+ PowerList();
+
+ void add(Sample *s);
+ void finalise(); ///< Call this when no more samples will be added.
+
+ Sample *get(level_t velocity);
+
+private:
+ class PowerListItem {
+ public:
+ Sample *sample;
+ float power;
+ };
+
+ std::vector<PowerListItem> samples;
+ float power_max;
+ float power_min;
+
+ Channel *getMasterChannel();
+};
+
+#endif/*__DRUMGIZMO_POWERLIST_H__*/
diff --git a/src/sample.h b/src/sample.h
index 70cfee2..cd3e111 100644
--- a/src/sample.h
+++ b/src/sample.h
@@ -38,6 +38,7 @@ typedef std::map< Channel*, AudioFile* > AudioFiles;
class InstrumentParser;
class Sample {
friend class InstrumentParser;
+ friend class PowerList;
public:
Sample(std::string name);
~Sample();
diff --git a/src/versionstr.cc b/src/versionstr.cc
new file mode 100644
index 0000000..3ef09e2
--- /dev/null
+++ b/src/versionstr.cc
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * versionstr.cc
+ *
+ * Wed Jul 22 11:41:32 CEST 2009
+ * Copyright 2009 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "versionstr.h"
+
+#include <memory.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+// Workaround - major, minor and patch are defined as macros when using _GNU_SOURCES
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
+#ifdef patch
+#undef patch
+#endif
+
+VersionStr::VersionStr(std::string v) throw(const char *)
+{
+ memset(version, 0, sizeof(version));
+ set(v);
+}
+
+VersionStr::VersionStr(size_t major, size_t minor, size_t patch)
+{
+ version[0] = major;
+ version[1] = minor;
+ version[2] = patch;
+}
+
+void VersionStr::set(std::string v) throw(const char *)
+{
+ std::string num;
+ size_t idx = 0;
+ for(size_t i = 0; i < v.length(); i++) {
+ if(v[i] == '.') {
+ if(idx > 2) throw "Version string is too long.";
+ version[idx] = atoi(num.c_str());
+ idx++;
+ num = "";
+ } else if(v[i] >= '0' && v[i] <= '9') {
+ num.append(1, v[i]);
+ } else {
+ throw "Version string contains illegal character.";
+ }
+ }
+ if(idx > 2) throw "Version string is too long.";
+ version[idx] = atoi(num.c_str());
+}
+
+VersionStr::operator std::string() const
+{
+ std::string v;
+ char *buf;
+ size_t sz;
+ if(patch()) sz = asprintf(&buf, "%d.%d.%d", major(), minor(), patch());
+ else sz = asprintf(&buf, "%d.%d", major(), minor());
+ if(sz) v = buf;
+ free(buf);
+ return v;
+}
+
+void VersionStr::operator=(std::string v) throw(const char *)
+{
+ set(v);
+}
+
+// return a - b simplified as -1, 0 or 1
+static int vdiff(const VersionStr &a, const VersionStr &b)
+{
+ if(a.major() < b.major()) return -1;
+ if(a.major() > b.major()) return 1;
+ if(a.minor() < b.minor()) return -1;
+ if(a.minor() > b.minor()) return 1;
+ if(a.patch() < b.patch()) return -1;
+ if(a.patch() > b.patch()) return 1;
+ return 0;
+}
+
+bool VersionStr::operator<(const VersionStr &other) const
+{
+ if(vdiff(*this, other) == -1) return true;
+ return false;
+}
+
+bool VersionStr::operator>(const VersionStr &other) const
+{
+ if(vdiff(*this, other) == 1) return true;
+ return false;
+}
+
+bool VersionStr::operator==(const VersionStr &other) const
+{
+ if(vdiff(*this, other) == 0) return true;
+ return false;
+}
+
+bool VersionStr::operator<=(const VersionStr &other) const
+{
+ if(vdiff(*this, other) != 1) return true;
+ return false;
+}
+
+bool VersionStr::operator>=(const VersionStr &other) const
+{
+ if(vdiff(*this, other) != -1) return true;
+ return false;
+}
+
+size_t VersionStr::major() const
+{
+ return version[0];
+}
+
+size_t VersionStr::minor() const
+{
+ return version[1];
+}
+
+size_t VersionStr::patch() const
+{
+ return version[2];
+}
diff --git a/src/versionstr.h b/src/versionstr.h
new file mode 100644
index 0000000..ecb1df3
--- /dev/null
+++ b/src/versionstr.h
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * versionstr.h
+ *
+ * Wed Jul 22 11:41:32 CEST 2009
+ * Copyright 2009 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __PRACRO_VERSIONSTR_H__
+#define __PRACRO_VERSIONSTR_H__
+
+#include <string>
+
+// Workaround - major, minor and patch are defined as macros when using _GNU_SOURCES
+#ifdef major
+#undef major
+#endif
+#ifdef minor
+#undef minor
+#endif
+#ifdef patch
+#undef patch
+#endif
+
+/**
+ * VersionStr class.
+ * It hold a version number and is capable of correct sorting, as well as string
+ * conversion both ways.
+ */
+class VersionStr {
+public:
+ /**
+ * Constructor.
+ * Throws an exeption if the string does not parse.
+ * @param v A std::string containing a version string on the form a.b or a.b.c
+ */
+ VersionStr(std::string v) throw(const char *);
+
+ /**
+ * Constructor.
+ * @param major A size_t containing the major version number.
+ * @param minor A size_t containing the minor version number.
+ * @param patch A size_t containing the patch level.
+ */
+ VersionStr(size_t major = 0, size_t minor = 0, size_t patch = 0);
+
+ /**
+ * Typecast to std::string operator.
+ * It simply converts the version numbers into a string of the form major.minor
+ * (if patch i 0) or major.minor.patch
+ */
+ operator std::string() const;
+
+ /**
+ * Assignment from std::string operator.
+ * Same as in the VersionStr(std::string v) constructor.
+ * Throws an exeption if the string does not parse.
+ */
+ void operator=(std::string v) throw(const char *);
+
+ /**
+ * Comparison operator.
+ * The version objects are sorted according to their major, minor and patch
+ * level numbers.
+ */
+ bool operator<(const VersionStr &other) const;
+ bool operator==(const VersionStr &other) const;
+ bool operator>(const VersionStr &other) const;
+ bool operator>=(const VersionStr &other) const;
+ bool operator<=(const VersionStr &other) const;
+
+
+ /**
+ * @return Major version number.
+ */
+ size_t major() const;
+
+ /**
+ * @return Minor version number.
+ */
+ size_t minor() const;
+
+ /**
+ * @return Patch level.
+ */
+ size_t patch() const;
+
+private:
+ void set(std::string v) throw(const char *);
+ size_t version[3];
+};
+
+#endif/*__PRACRO_VERSIONSTR_H__*/