Mercurial > hg > match-vamp
changeset 199:cca298ecfc72
Merge from branch re-minimise
author | Chris Cannam |
---|---|
date | Fri, 27 Feb 2015 09:29:37 +0000 |
parents | a68204b9a529 (current diff) 082ff90f1c82 (diff) |
children | f6be68852c1d |
files | src/MatchFeeder.cpp src/MatchFeeder.h test/expected.csv test/regressiontest.sh |
diffstat | 34 files changed, 9100 insertions(+), 6866 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Fri Nov 14 10:24:13 2014 +0000 +++ b/.hgignore Fri Feb 27 09:29:37 2015 +0000 @@ -4,3 +4,7 @@ *.dylib *.so *.o +*.orig +re:^test/TestDistanceMetric$ +re:^test/TestFeatureConditioner$ +re:^test/TestFeatureExtractor$
--- a/Makefile.inc Fri Nov 14 10:24:13 2014 +0000 +++ b/Makefile.inc Fri Feb 27 09:29:37 2015 +0000 @@ -4,37 +4,65 @@ CXX ?= g++ CC ?= gcc +CXXFLAGS := -Isrc -DUSE_COMPACT_TYPES $(CXXFLAGS) + +TEST_LDFLAGS += -lboost_unit_test_framework + HEADERS := $(wildcard src/*.h) SOURCES := $(wildcard src/*.cpp) - OBJECTS := $(SOURCES:.cpp=.o) +TEST_SOURCES := $(wildcard test/*.cpp) +TEST_OBJECTS := $(TEST_SOURCES:.cpp=.o) +TESTS := $(TEST_OBJECTS:.o=) + +all: $(PLUGIN) $(TESTS) + for t in $(TESTS); do echo "Running $$t"; ./"$$t" || exit 1; done + $(PLUGIN): $(OBJECTS) - $(CXX) -o $@ $^ $(LDFLAGS) + $(CXX) -o $@ $^ $(LDFLAGS) $(PLUGIN_LDFLAGS) + +test/%: test/%.o $(OBJECTS) + $(CXX) -o $@ $^ $(LDFLAGS) $(TEST_LDFLAGS) clean: - rm -f $(OBJECTS) + rm -f $(OBJECTS) $(TEST_OBJECTS) $(TESTS) distclean: clean rm -f $(PLUGIN) depend: - makedepend -Y -fMakefile.inc $(SOURCES) $(HEADERS) + makedepend -Y -fMakefile.inc $(SOURCES) $(HEADERS) $(TEST_SOURCES) + # DO NOT DELETE src/DistanceMetric.o: src/DistanceMetric.h -src/MatchFeeder.o: src/MatchFeeder.h src/Matcher.h src/DistanceMetric.h -src/MatchFeeder.o: src/Finder.h src/Path.o: src/Path.h +src/FeatureConditioner.o: src/FeatureConditioner.h src/MatchFeatureFeeder.o: src/MatchFeatureFeeder.h src/Matcher.h -src/MatchFeatureFeeder.o: src/DistanceMetric.h src/Finder.h -src/Finder.o: src/Finder.h src/Matcher.h src/DistanceMetric.h src/Path.h -src/Matcher.o: src/Matcher.h src/DistanceMetric.h -src/MatchVampPlugin.o: src/MatchVampPlugin.h src/Matcher.h -src/MatchVampPlugin.o: src/DistanceMetric.h src/MatchFeeder.h src/Finder.h +src/MatchFeatureFeeder.o: src/DistanceMetric.h src/MatchTypes.h src/Finder.h +src/FeatureExtractor.o: src/FeatureExtractor.h +src/Finder.o: src/Finder.h src/Matcher.h src/DistanceMetric.h src/MatchTypes.h +src/Finder.o: src/Path.h +src/Matcher.o: src/Matcher.h src/DistanceMetric.h src/MatchTypes.h +src/MatchPipeline.o: src/MatchPipeline.h src/Matcher.h src/DistanceMetric.h +src/MatchPipeline.o: src/MatchTypes.h src/Finder.h src/FeatureExtractor.h +src/MatchPipeline.o: src/FeatureConditioner.h src/MatchFeatureFeeder.h +src/MatchVampPlugin.o: src/MatchVampPlugin.h src/MatchPipeline.h +src/MatchVampPlugin.o: src/Matcher.h src/DistanceMetric.h src/MatchTypes.h +src/MatchVampPlugin.o: src/Finder.h src/FeatureExtractor.h +src/MatchVampPlugin.o: src/FeatureConditioner.h src/MatchFeatureFeeder.h src/MatchVampPlugin.o: src/Path.h -src/MatchFeeder.o: src/Matcher.h src/DistanceMetric.h src/Finder.h -src/MatchFeatureFeeder.o: src/Matcher.h src/DistanceMetric.h src/Finder.h -src/Finder.o: src/Matcher.h src/DistanceMetric.h -src/Matcher.o: src/DistanceMetric.h -src/MatchVampPlugin.o: src/Matcher.h src/DistanceMetric.h +src/MatchFeatureFeeder.o: src/Matcher.h src/DistanceMetric.h src/MatchTypes.h +src/MatchFeatureFeeder.o: src/Finder.h +src/Finder.o: src/Matcher.h src/DistanceMetric.h src/MatchTypes.h +src/Matcher.o: src/DistanceMetric.h src/MatchTypes.h +src/MatchPipeline.o: src/Matcher.h src/DistanceMetric.h src/MatchTypes.h +src/MatchPipeline.o: src/Finder.h src/FeatureExtractor.h +src/MatchPipeline.o: src/FeatureConditioner.h src/MatchFeatureFeeder.h +src/MatchVampPlugin.o: src/MatchPipeline.h src/Matcher.h src/DistanceMetric.h +src/MatchVampPlugin.o: src/MatchTypes.h src/Finder.h src/FeatureExtractor.h +src/MatchVampPlugin.o: src/FeatureConditioner.h src/MatchFeatureFeeder.h +test/TestFeatureConditioner.o: src/FeatureConditioner.h +test/TestDistanceMetric.o: src/DistanceMetric.h +test/TestFeatureExtractor.o: src/FeatureExtractor.h
--- a/Makefile.linux Fri Nov 14 10:24:13 2014 +0000 +++ b/Makefile.linux Fri Feb 27 09:29:37 2015 +0000 @@ -1,6 +1,10 @@ -CXXFLAGS += -fPIC -ffast-math -O3 -Wall -Werror -LDFLAGS += -shared -Wl,-Bstatic -lvamp-sdk -Wl,-Bdynamic -Wl,-Bsymbolic -Wl,-z,defs -lpthread -Wl,--version-script=vamp-plugin.map +CXXFLAGS += -fPIC -ffast-math -O3 -Wall -Werror -Werror=old-style-cast -Wconversion -std=c++11 -DPERFORM_ERROR_CHECKS=1 + +#CXXFLAGS += -fPIC -g -Wall -Werror -Werror=old-style-cast -Wconversion -DPERFORM_ERROR_CHECKS=1 -std=c++11 + +LDFLAGS += -Wl,-Bstatic -lvamp-sdk -Wl,-Bdynamic +PLUGIN_LDFLAGS += -shared -Wl,-Bsymbolic -Wl,-z,defs -lpthread -Wl,--version-script=vamp-plugin.map include Makefile.inc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile.osx Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,12 @@ + +ARCHFLAGS := -arch x86_64 -mmacosx-version-min=10.7 +CFLAGS := $(ARCHFLAGS) -O3 -I../vamp-plugin-sdk -I/usr/local/boost -Wall -fPIC -std=c++11 +CXXFLAGS := $(CFLAGS) + +LDFLAGS := -L../vamp-plugin-sdk -lvamp-sdk $(ARCHFLAGS) +PLUGIN_LDFLAGS := -dynamiclib $(LDFLAGS) -exported_symbols_list vamp-plugin.list +TEST_LDFLAGS := $(LDFLAGS) -lboost_unit_test_framework +PLUGIN_EXT := .dylib + +include Makefile.inc +
--- a/match-vamp-plugin.n3 Fri Nov 14 10:24:13 2014 +0000 +++ b/match-vamp-plugin.n3 Fri Feb 27 09:29:37 2015 +0000 @@ -6,24 +6,26 @@ @prefix dc: <http://purl.org/dc/elements/1.1/> . @prefix af: <http://purl.org/ontology/af/> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . @prefix cc: <http://web.resource.org/cc/> . @prefix : <#> . -<> a vamp:PluginDescription ; - foaf:maker <http://www.vamp-plugins.org/doap.rdf#template-generator> ; - foaf:primaryTopic <http://vamp-plugins.org/rdf/plugins/match-vamp-plugin> . +<> a vamp:PluginDescription ; + foaf:maker <http://vamp-plugins.org/rdf/template-generator> ; + foaf:primaryTopic <http://vamp-plugins.org/rdf/plugins/match-vamp-plugin> . -:maker +:library_maker foaf:name "Simon Dixon and Chris Cannam" ; foaf:logo <http://vamp-plugins.org/rdf/plugins/makers/qm.png> ; - foaf:page <http://c4dm.eecs.qmul.ac.uk/> . + foaf:page <http://c4dm.eecs.qmul.ac.uk/> ; + . plugbase:library a vamp:PluginLibrary ; vamp:identifier "match-vamp-plugin" ; dc:title "MATCH Vamp Plugin" ; dc:description """Vamp implementation of the MATCH audio alignment algorithm from Simon Dixon. Sonic Visualiser can use this for automatic time alignment among multiple audio files.""" ; vamp:available_plugin plugbase:match ; - foaf:maker :maker ; + foaf:maker :library_maker ; foaf:page <http://code.soundsoftware.ac.uk/projects/match-vamp> ; . @@ -31,15 +33,27 @@ dc:title "Match Performance Aligner" ; vamp:name "Match Performance Aligner" ; dc:description """Calculate alignment between two performances in separate channel inputs""" ; - foaf:maker :maker ; + foaf:maker :library_maker ; dc:rights """GPL""" ; # cc:license <Place plugin license URI here and uncomment> ; vamp:identifier "match" ; vamp:vamp_API_version vamp:api_version_2 ; - owl:versionInfo "1" ; + owl:versionInfo "3" ; vamp:input_domain vamp:FrequencyDomain ; - + vamp:parameter plugbase:match_param_freq1 ; + vamp:parameter plugbase:match_param_freq2 ; + vamp:parameter plugbase:match_param_usechroma ; + vamp:parameter plugbase:match_param_usespecdiff ; + vamp:parameter plugbase:match_param_framenorm ; + vamp:parameter plugbase:match_param_metric ; + vamp:parameter plugbase:match_param_distnorm ; + vamp:parameter plugbase:match_param_silencethreshold ; + vamp:parameter plugbase:match_param_noise ; + vamp:parameter plugbase:match_param_gradientlimit ; + vamp:parameter plugbase:match_param_zonewidth ; + vamp:parameter plugbase:match_param_diagonalweight ; + vamp:parameter plugbase:match_param_smooth ; vamp:parameter plugbase:match_param_serialise ; vamp:output plugbase:match_output_path ; @@ -47,10 +61,155 @@ vamp:output plugbase:match_output_b_a ; vamp:output plugbase:match_output_a_b_divergence ; vamp:output plugbase:match_output_a_b_temporatio ; + vamp:output plugbase:match_output_a_features ; + vamp:output plugbase:match_output_b_features ; + vamp:output plugbase:match_output_a_cfeatures ; + vamp:output plugbase:match_output_b_cfeatures ; + vamp:output plugbase:match_output_overall_cost ; + . + +plugbase:match_param_freq1 a vamp:Parameter ; + vamp:identifier "freq1" ; + dc:title "Tuning frequency of first input" ; + dc:format "Hz" ; + vamp:min_value 220 ; + vamp:max_value 880 ; + vamp:unit "Hz" ; + vamp:default_value 440 ; + vamp:value_names (); + . +plugbase:match_param_freq2 a vamp:Parameter ; + vamp:identifier "freq2" ; + dc:title "Tuning frequency of second input" ; + dc:format "Hz" ; + vamp:min_value 220 ; + vamp:max_value 880 ; + vamp:unit "Hz" ; + vamp:default_value 440 ; + vamp:value_names (); + . +plugbase:match_param_usechroma a vamp:QuantizedParameter ; + vamp:identifier "usechroma" ; + dc:title "Feature type" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 0 ; + vamp:value_names ( "Spectral" "Chroma"); + . +plugbase:match_param_usespecdiff a vamp:QuantizedParameter ; + vamp:identifier "usespecdiff" ; + dc:title "Use feature difference" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 1 ; + vamp:value_names (); + . +plugbase:match_param_framenorm a vamp:QuantizedParameter ; + vamp:identifier "framenorm" ; + dc:title "Frame normalisation" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 2 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 1 ; + vamp:value_names ( "None" "Sum to 1" "Long-term average"); + . +plugbase:match_param_metric a vamp:QuantizedParameter ; + vamp:identifier "metric" ; + dc:title "Distance metric" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 2 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 0 ; + vamp:value_names ( "Manhattan" "Euclidean" "Cosine"); + . +plugbase:match_param_distnorm a vamp:QuantizedParameter ; + vamp:identifier "distnorm" ; + dc:title "Distance normalisation" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 2 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 2 ; + vamp:value_names ( "None" "Sum of frames" "Log sum of frames"); + . +plugbase:match_param_silencethreshold a vamp:Parameter ; + vamp:identifier "silencethreshold" ; + dc:title "Silence threshold" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 0.1 ; + vamp:unit "" ; + vamp:default_value 0.01 ; + vamp:value_names (); + . +plugbase:match_param_noise a vamp:QuantizedParameter ; + vamp:identifier "noise" ; + dc:title "Add noise" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 1 ; + vamp:value_names (); + . +plugbase:match_param_gradientlimit a vamp:QuantizedParameter ; + vamp:identifier "gradientlimit" ; + dc:title "Gradient limit" ; + dc:format "" ; + vamp:min_value 1 ; + vamp:max_value 10 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 3 ; + vamp:value_names (); + . +plugbase:match_param_zonewidth a vamp:QuantizedParameter ; + vamp:identifier "zonewidth" ; + dc:title "Search zone width" ; + dc:format "s" ; + vamp:min_value 1 ; + vamp:max_value 60 ; + vamp:unit "s" ; + vamp:quantize_step 1 ; + vamp:default_value 10 ; + vamp:value_names (); + . +plugbase:match_param_diagonalweight a vamp:Parameter ; + vamp:identifier "diagonalweight" ; + dc:title "Diagonal weight" ; + dc:format "" ; + vamp:min_value 1 ; + vamp:max_value 2 ; + vamp:unit "" ; + vamp:default_value 2 ; + vamp:value_names (); + . +plugbase:match_param_smooth a vamp:QuantizedParameter ; + vamp:identifier "smooth" ; + dc:title "Use path smoothing" ; + dc:format "" ; + vamp:min_value 0 ; + vamp:max_value 1 ; + vamp:unit "" ; + vamp:quantize_step 1 ; + vamp:default_value 0 ; + vamp:value_names (); . plugbase:match_param_serialise a vamp:QuantizedParameter ; vamp:identifier "serialise" ; - dc:title "Serialise Plugin Invocations" ; + dc:title "Serialise plugin invocations" ; dc:format "" ; vamp:min_value 0 ; vamp:max_value 1 ; @@ -62,7 +221,7 @@ plugbase:match_output_path a vamp:SparseOutput ; vamp:identifier "path" ; dc:title "Path" ; - dc:description "Alignment path" ; + dc:description """Alignment path""" ; vamp:fixed_bin_count "true" ; vamp:unit "" ; a vamp:QuantizedOutput ; @@ -77,7 +236,7 @@ plugbase:match_output_a_b a vamp:SparseOutput ; vamp:identifier "a_b" ; dc:title "A-B Timeline" ; - dc:description "Timing in performance B corresponding to moments in performance A" ; + dc:description """Timing in performance B corresponding to moments in performance A""" ; vamp:fixed_bin_count "true" ; vamp:unit "sec" ; vamp:bin_count 1 ; @@ -90,7 +249,7 @@ plugbase:match_output_b_a a vamp:SparseOutput ; vamp:identifier "b_a" ; dc:title "B-A Timeline" ; - dc:description "Timing in performance A corresponding to moments in performance B" ; + dc:description """Timing in performance A corresponding to moments in performance B""" ; vamp:fixed_bin_count "true" ; vamp:unit "sec" ; vamp:bin_count 1 ; @@ -103,7 +262,7 @@ plugbase:match_output_a_b_divergence a vamp:SparseOutput ; vamp:identifier "a_b_divergence" ; dc:title "A-B Divergence" ; - dc:description "Difference between timings in performances A and B" ; + dc:description """Difference between timings in performances A and B""" ; vamp:fixed_bin_count "true" ; vamp:unit "sec" ; vamp:bin_count 1 ; @@ -116,7 +275,7 @@ plugbase:match_output_a_b_temporatio a vamp:SparseOutput ; vamp:identifier "a_b_temporatio" ; dc:title "A-B Tempo Ratio" ; - dc:description "Ratio of tempi between performances A and B" ; + dc:description """Ratio of tempi between performances A and B""" ; vamp:fixed_bin_count "true" ; vamp:unit "" ; vamp:bin_count 1 ; @@ -126,4 +285,59 @@ # vamp:computes_feature <Place feature attribute URI here and uncomment> ; # vamp:computes_signal_type <Place signal type URI here and uncomment> ; . +plugbase:match_output_a_features a vamp:DenseOutput ; + vamp:identifier "a_features" ; + dc:title "Raw A Features" ; + dc:description """Spectral features extracted from performance A""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 84 ; +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:match_output_b_features a vamp:DenseOutput ; + vamp:identifier "b_features" ; + dc:title "Raw B Features" ; + dc:description """Spectral features extracted from performance B""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 84 ; +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:match_output_a_cfeatures a vamp:DenseOutput ; + vamp:identifier "a_cfeatures" ; + dc:title "Conditioned A Features" ; + dc:description """Spectral features extracted from performance A, after normalisation and conditioning""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 84 ; +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:match_output_b_cfeatures a vamp:DenseOutput ; + vamp:identifier "b_cfeatures" ; + dc:title "Conditioned B Features" ; + dc:description """Spectral features extracted from performance B, after norrmalisation and conditioning""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 84 ; +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + . +plugbase:match_output_overall_cost a vamp:DenseOutput ; + vamp:identifier "overall_cost" ; + dc:title "Overall Cost" ; + dc:description """Normalised overall path cost for the cheapest path""" ; + vamp:fixed_bin_count "true" ; + vamp:unit "" ; + vamp:bin_count 1 ; +# vamp:computes_event_type <Place event type URI here and uncomment> ; +# vamp:computes_feature <Place feature attribute URI here and uncomment> ; +# vamp:computes_signal_type <Place signal type URI here and uncomment> ; + .
--- a/src/DistanceMetric.cpp Fri Nov 14 10:24:13 2014 +0000 +++ b/src/DistanceMetric.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -18,50 +18,173 @@ #include <cassert> #include <cmath> +#include <iostream> -using std::vector; +using namespace std; -double -DistanceMetric::calcDistance(const vector<double> &f1, - const vector<double> &f2) +//#define DEBUG_DISTANCE_METRIC 1 + +template <> uint8_t +DistanceMetric::scaleIntoRange(double distance) +{ + double scaled = m_params.scale * distance; + if (scaled < 0) { + scaled = 0; + } + if (scaled > MaxDistance) { + scaled = MaxDistance; + ++m_overcount; + } + return uint8_t(scaled); +} + +template <> float +DistanceMetric::scaleIntoRange(double distance) +{ + return float(distance); +} + +template <> double +DistanceMetric::scaleIntoRange(double distance) +{ + return distance; +} + +DistanceMetric::DistanceMetric(Parameters params) : + m_params(params), + m_max(0), + m_overcount(0) +{ +#ifdef DEBUG_DISTANCE_METRIC + cerr << "*** DistanceMetric: metric = " << m_params.metric + << ", norm = " << m_params.norm + << ", noise = " << m_params.noise + << ", scale = " << m_params.scale + << endl; +#endif +} + +DistanceMetric::~DistanceMetric() +{ +#ifdef DEBUG_DISTANCE_METRIC + cerr << "*** DistanceMetric::~DistanceMetric: metric = " << m_params.metric + << ", norm = " << m_params.norm + << ", noise = " << m_params.noise; +#ifdef USE_COMPACT_TYPES + cerr << ", scale = " << m_params.scale; + cerr << "\n*** DistanceMetric::~DistanceMetric: max scaled value = " + << distance_print_t(m_max) + << ", " << m_overcount << " clipped" << endl; +#else + cerr << ", no scaling"; + cerr << "\n*** DistanceMetric::~DistanceMetric: max value = " + << distance_print_t(m_max) + << endl; +#endif +#endif +} + +distance_t +DistanceMetric::scaleValueIntoDistanceRange(double value) +{ + return scaleIntoRange<distance_t>(value); +} + +distance_t +DistanceMetric::scaleAndTally(double value) +{ + distance_t dist = scaleIntoRange<distance_t>(value); + if (dist > m_max) m_max = dist; + return dist; +} + +distance_t +DistanceMetric::calcDistance(const feature_t &f1, + const feature_t &f2) { double d = 0; double sum = 0; + double eps = 1e-16; - int featureSize = f1.size(); - assert(int(f2.size()) == featureSize); + assert(f2.size() == f1.size()); + int featureSize = static_cast<int>(f1.size()); + + double minNoise = 0.0; +#ifdef USE_COMPACT_TYPES + minNoise = 1.0 / m_params.scale; +#endif - for (int i = 0; i < featureSize; i++) { - d += fabs(f1[i] - f2[i]); - sum += f1[i] + f2[i]; + if (m_params.metric == Cosine) { + + double num = 0, denom1 = 0, denom2 = 0; + + for (int i = 0; i < featureSize; ++i) { + num += f1[i] * f2[i]; + denom1 += f1[i] * f1[i]; + denom2 += f2[i] * f2[i]; + } + + d = 1.0 - (num / (eps + sqrt(denom1 * denom2))); + + if (m_params.noise == AddNoise) { + double noise = 1e-2; + if (noise < minNoise) noise = minNoise; + d += noise; + } + if (d > 1.0) d = 1.0; + + return scaleAndTally(d); // normalisation param ignored } - if (sum == 0) - return 0; - if (m_norm == NormaliseDistanceToSum) - return d / sum; // 0 <= d/sum <= 2 - if (m_norm != NormaliseDistanceToLogSum) - return d; + if (m_params.metric == Manhattan) { + for (int i = 0; i < featureSize; i++) { + d += fabs(f1[i] - f2[i]); + sum += fabs(f1[i]) + fabs(f2[i]); + } + } else { + // Euclidean + for (int i = 0; i < featureSize; i++) { + d += (f1[i] - f2[i]) * (f1[i] - f2[i]); + sum += fabs(f1[i]) + fabs(f2[i]); + } + d = sqrt(d); + } - // note if this were to be restored, it would have to use - // totalEnergies vector instead of f1[freqMapSize] which used to - // store the total energy: - // double weight = (5 + Math.log(f1[freqMapSize] + f2[freqMapSize]))/10.0; + if (m_params.noise == AddNoise) { + double noise = 1e-3 * featureSize; + if (noise < minNoise) noise = minNoise; + d += noise; + sum += noise; + } + + if (sum == 0) { + return scaleAndTally(0); + } - double weight = (8 + log(sum)) / 10.0; + double distance = 0; - if (weight < 0) weight = 0; - else if (weight > 1) weight = 1; + if (m_params.norm == NormaliseDistanceToSum) { - return d / sum * weight; + distance = d / sum; // 0 <= d/sum <= 2 + + } else if (m_params.norm == NormaliseDistanceToLogSum) { + + // note if this were to be restored, it would have to use + // totalEnergies vector instead of f1[freqMapSize] which used to + // store the total energy: + // double weight = (5 + Math.log(f1[freqMapSize] + f2[freqMapSize]))/10.0; + + double weight = (8 + log(sum)) / 10.0; + + if (weight < 0) weight = 0; + else if (weight > 1) weight = 1; + + distance = d / sum * weight; + + } else { + + distance = d; + } + + return scaleAndTally(distance); } - -int -DistanceMetric::calcDistanceScaled(const vector<double> &f1, - const vector<double> &f2, - double scale) -{ - double distance = calcDistance(f1, f2); - return int(distance * scale); -} -
--- a/src/DistanceMetric.h Fri Nov 14 10:24:13 2014 +0000 +++ b/src/DistanceMetric.h Fri Feb 27 09:29:37 2015 +0000 @@ -17,11 +17,28 @@ #ifndef DISTANCE_METRIC_H #define DISTANCE_METRIC_H -#include <vector> +#include "MatchTypes.h" class DistanceMetric { public: + enum Metric { + + /** Calculate the Manhattan distance between feature + * vectors. If the vectors contain energy, as the default + * MATCH feature does, this could be considered as a squared + * Euclidean distance metric. */ + Manhattan, + + /** Calculate the Euclidean distance between feature vectors. */ + Euclidean, + + /** Calculate the cosine distance between feature vectors. The + * normalisation setting will be ignored as the result is + * already magnitude-independent. */ + Cosine, + }; + enum DistanceNormalisation { /** Do not normalise distance metrics */ @@ -35,39 +52,61 @@ * of the sum of the frames. */ NormaliseDistanceToLogSum, }; + + enum NoiseAddition { - DistanceMetric(DistanceNormalisation norm) : m_norm(norm) { } + /** Don't add noise. */ + NoNoise, + + /** Add a constant noise term. This can help avoid + * mis-tracking when one file contains a lot of silence. */ + AddNoise, + }; - /** Calculates the Manhattan distance between two vectors, with an - * optional normalisation by the combined values in the - * vectors. Since the vectors contain energy, this could be - * considered as a squared Euclidean distance metric. Note that - * normalisation assumes the values are all non-negative. + struct Parameters { + + Parameters() : + metric(Manhattan), + norm(NormaliseDistanceToLogSum), + noise(AddNoise), + scale(100.) + {} + + Metric metric; + DistanceNormalisation norm; + NoiseAddition noise; + double scale; + }; + + DistanceMetric(Parameters params); + + ~DistanceMetric(); + + /** Calculates the distance in some metric between two vectors, + * with an optional normalisation by the combined values in the + * vectors. Note that normalisation assumes the values are all + * non-negative. * * @param f1 one of the vectors involved in the distance calculation * @param f2 one of the vectors involved in the distance calculation * @return the distance */ - double calcDistance(const std::vector<double> &f1, - const std::vector<double> &f2); + distance_t calcDistance(const feature_t &f1, + const feature_t &f2); + + /** + * Mostly for internal use and testing + */ + distance_t scaleValueIntoDistanceRange(double value); - /** Calculates the Manhattan distance between two vectors, with an - * optional normalisation by the combined values in the - * vectors. Since the vectors contain energy, this could be - * considered as a squared Euclidean distance metric. Note that - * normalisation assumes the values are all non-negative. - * - * @param f1 one of the vectors involved in the distance calculation - * @param f2 one of the vectors involved in the distance calculation - * @param scale the scaling factor to place the result in integer range - * @return the distance, scaled by scale and truncated to an integer - */ - int calcDistanceScaled(const std::vector<double> &f1, - const std::vector<double> &f2, - double scale); +private: + Parameters m_params; -private: - DistanceNormalisation m_norm; + distance_t scaleAndTally(double); + template <typename T> T scaleIntoRange(double); + + distance_t m_max; + int m_overcount; }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/FeatureConditioner.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,108 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + + This program 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "FeatureConditioner.h" + +#include <iostream> +#include <cmath> + +using namespace std; + +//#define DEBUG_FEATURE_CONDITIONER 1 + +FeatureConditioner::FeatureConditioner(Parameters parameters) : + m_params(parameters), + m_ltAverage(0.0) +{ +#ifdef DEBUG_FEATURE_CONDITIONER + cerr << "*** FeatureConditioner: norm = " << parameters.norm + << ", order = " << parameters.order + << ", silenceThreshold = " << parameters.silenceThreshold + << ", decay = " << parameters.decay << endl; +#endif +} + +feature_t +FeatureConditioner::process(const feature_t &feature) +{ + if (m_prev.empty()) { + m_prev.resize(feature.size(), 0.0); + } + if (m_prev.size() != feature.size()) { + cerr << "ERROR: FeatureConditioner::process: feature size " + << feature.size() << " differs from previous feature size " + << m_prev.size() << endl; + return feature; + } + + int size = static_cast<int>(feature.size()); + + feature_t out(size, 0.0); + + double totalEnergy = 0; + + switch (m_params.order) { + + case OutputRectifiedDerivative: + for (int i = 0; i < size; i++) { + totalEnergy += feature[i]; + if (feature[i] > m_prev[i]) { + out[i] = feature[i] - m_prev[i]; + } else { + out[i] = 0; + } + } + break; + + case OutputDerivative: + for (int i = 0; i < size; i++) { + totalEnergy += feature[i]; + out[i] = fabs(feature[i] - m_prev[i]); + } + break; + + case OutputFeatures: + for (int i = 0; i < size; i++) { + totalEnergy += feature[i]; + out[i] = feature[i]; + } + break; + } + + if (m_ltAverage == 0.0) { + m_ltAverage = totalEnergy; + } else { + double decay = m_params.decay; + m_ltAverage = m_ltAverage * decay + totalEnergy * (1.0 - decay); + } + + if (totalEnergy <= m_params.silenceThreshold) { + for (int i = 0; i < size; i++) { + out[i] = 0; + } + } else if (m_params.norm == NormaliseToSum1) { + for (int i = 0; i < size; i++) { + out[i] = featurebin_t(out[i] / totalEnergy); + } + } else if (m_params.norm == NormaliseToLTAverage) { + for (int i = 0; i < size; i++) { + out[i] = featurebin_t(out[i] / m_ltAverage); + } + } + + m_prev = feature; + return out; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/FeatureConditioner.h Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,112 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + + This program 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef FEATURE_CONDITIONER_H +#define FEATURE_CONDITIONER_H + +#include "MatchTypes.h" + +/** + * Take a series of feature vectors and apply conditioning of some + * sort, such as normalisation or first-order derivative. + * + * Note that FeatureConditioner maintains internal frame-to-frame + * state: use one FeatureConditioner per audio source, and construct a + * new one for each new source. + */ +class FeatureConditioner +{ +public: + enum Normalisation { + + /** Do not normalise */ + NoNormalisation, + + /** Normalise each feature vector to have a sum of 1 */ + NormaliseToSum1, + + /** Normalise each feature vector by the long-term average of + * the summed energy */ + NormaliseToLTAverage, + }; + + enum OutputOrder { + + /** Output the normalised features without further processing */ + OutputFeatures, + + /** Output the half-wave rectified difference between the + * previous and current features instead of the straight + * feature values. */ + OutputRectifiedDerivative, + + /** Output the absolute difference between the previous and + * current features instead of the straight feature + * values. */ + OutputDerivative, + }; + + struct Parameters { + + Parameters() : + norm(NormaliseToSum1), + order(OutputRectifiedDerivative), + silenceThreshold(0.01), + decay(0.99) + {} + + /** Feature normalisation. */ + Normalisation norm; + + /** Type of output to generate (plain feature, derivative etc). */ + OutputOrder order; + + /** Silence threshold. If non-zero, any feature whose total + * energy (simply the sum of feature values) is below that + * threshold will be rounded down to all zeros. Note that + * this refers to the energy of the pre-norm feature, not of + * its derivative even if that is what is being returned. */ + double silenceThreshold; + + /** Frame-to-frame decay factor in calculating long-term average */ + double decay; + }; + + /** + * Construct a FeatureConditioner with the given parameters. + * + * Note that FeatureConditioner maintains internal frame-to-frame + * state: use one FeatureConditioner per audio source, and construct + * a new one for each new source. + */ + FeatureConditioner(Parameters parameters); + + /** + * Process the given feature and return the conditioned feature. + */ + feature_t process(const feature_t &feature); + +protected: + Parameters m_params; + + /** Long term average feature energy. */ + double m_ltAverage; + + /** The most recent feature, used for calculating the feature to + * feature difference. This is therefore not yet normalised. */ + feature_t m_prev; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/FeatureExtractor.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,263 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. + + This program 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "FeatureExtractor.h" + +#include <iostream> + +#include <cstdlib> +#include <cassert> +#include <cmath> + +using namespace std; + +//#define DEBUG_FEATURE_EXTRACTOR 1 + +FeatureExtractor::FeatureExtractor(Parameters parameters) : + m_params(parameters) +{ + m_featureSize = getFeatureSizeFor(parameters); + makeFreqMap(); + +#ifdef DEBUG_FEATURE_EXTRACTOR + cerr << "*** FeatureExtractor: sampleRate = " << parameters.sampleRate + << ", useChromaFrequencyMap = " << parameters.useChromaFrequencyMap + << ", fftSize = " << parameters.fftSize << endl; +#endif +} + +int +FeatureExtractor::getFeatureSizeFor(Parameters parameters) +{ + if (parameters.useChromaFrequencyMap) { + return 13; + } else { + return 84; + } +} + +void +FeatureExtractor::makeFreqMap() +{ + m_freqMap = vector<int>(m_params.fftSize / 2 + 1, 0); + + if (m_params.useChromaFrequencyMap) { +#ifdef DEBUG_FEATURE_EXTRACTOR + cerr << "makeFreqMap: calling makeChromaFrequencyMap" << endl; +#endif + makeChromaFrequencyMap(); + } else { +#ifdef DEBUG_FEATURE_EXTRACTOR + cerr << "makeFreqMap: calling makeStandardFrequencyMap" << endl; +#endif + makeStandardFrequencyMap(); + } +} + +void +FeatureExtractor::makeStandardFrequencyMap() +{ + // Our handling of the referenceFrequency parameter depends on the + // frequency map in use. + + // With the chroma frequency map, we use referenceFrequency to set + // up the chroma bin frequencies when constructing the map, and + // then just follow the map (without having to refer to + // referenceFrequency again) when we get the frequency-domain + // audio. + + // With the standard frequency map, using referenceFrequency to + // set up the map doesn't work so well -- it only really affects + // the crossover frequency, and much of the useful information is + // below that frequency. What we do instead is to ignore the + // referenceFrequency when creating the map -- setting it up for + // 440Hz -- and then use it to scale the individual + // frequency-domain audio frames before applying the map to them. + + double refFreq = 440.; // See above -- *not* the parameter! + double binWidth = double(m_params.sampleRate) / m_params.fftSize; + int crossoverBin = int(2 / (pow(2, 1/12.0) - 1)); + int crossoverMidi = int(log(crossoverBin * binWidth / refFreq)/ + log(2.0) * 12 + 69 + 0.5); + + int i = 0; + while (i <= crossoverBin) { + double freq = i * binWidth; + if (freq < m_params.minFrequency || freq > m_params.maxFrequency) { + m_freqMap[i++] = -1; + } else { + m_freqMap[i] = i; + i++; + } + } + + while (i <= m_params.fftSize/2) { + double freq = i * binWidth; + if (freq < m_params.minFrequency || freq > m_params.maxFrequency) { + m_freqMap[i++] = -1; + } else { + double midi = log(freq / refFreq) / log(2.0) * 12 + 69; + if (midi > 127) midi = 127; + int target = crossoverBin + int(midi + 0.5) - crossoverMidi; + if (target >= m_featureSize) target = m_featureSize - 1; + m_freqMap[i++] = target; + } + } + +#ifdef DEBUG_FEATURE_EXTRACTOR + cerr << "FeatureExtractor: crossover bin is " << crossoverBin << " for midi " + << crossoverMidi << endl; + cerr << "FeatureExtractor: map is:" << endl; + for (i = 0; i <= m_params.fftSize/2; ++i) { + cerr << i << ": " << m_freqMap[i] << ", "; + } + cerr << endl; +#endif +} + +void +FeatureExtractor::makeChromaFrequencyMap() +{ + double refFreq = m_params.referenceFrequency; + double binWidth = double(m_params.sampleRate) / m_params.fftSize; + int crossoverBin = int(1 / (pow(2, 1/12.0) - 1)); + int i = 0; + while (i <= crossoverBin) { + double freq = i * binWidth; + if (freq < m_params.minFrequency || freq > m_params.maxFrequency) { + m_freqMap[i++] = -1; + } else { + m_freqMap[i++] = 0; + } + } + while (i <= m_params.fftSize/2) { + double freq = i * binWidth; + if (freq < m_params.minFrequency || freq > m_params.maxFrequency) { + m_freqMap[i++] = -1; + } else { + double midi = log(freq / refFreq) / log(2.0) * 12 + 69; + m_freqMap[i++] = (int(midi + 0.5)) % 12 + 1; + } + } +} + +feature_t +FeatureExtractor::process(const vector<double> &real, const vector<double> &imag) +{ + vector<float> mags(m_params.fftSize/2 + 1, 0.0); + + for (int i = 0; i <= m_params.fftSize/2; i++) { + mags[i] = float(real[i] * real[i] + imag[i] * imag[i]); + } + + return processMags(mags); +} + +feature_t +FeatureExtractor::process(const vector<float> &real, const vector<float> &imag) +{ + vector<float> mags(m_params.fftSize/2 + 1, 0.0); + + for (int i = 0; i <= m_params.fftSize/2; i++) { + mags[i] = real[i] * real[i] + imag[i] * imag[i]; + } + + return processMags(mags); +} + +feature_t +FeatureExtractor::process(const float *cframe) +{ + vector<float> mags(m_params.fftSize/2 + 1, 0.0); + + for (int i = 0; i <= m_params.fftSize/2; i++) { + mags[i] = cframe[i*2] * cframe[i*2] + cframe[i*2+1] * cframe[i*2+1]; + } + + return processMags(mags); +} + +feature_t +FeatureExtractor::processMags(const vector<float> &mags) +{ + feature_t frame(m_featureSize, 0.0); + + if (!m_params.useChromaFrequencyMap && + (m_params.referenceFrequency != 440.)) { + + // See comment in makeStandardFrequencyMap above + vector<float> scaled = scaleMags(mags); + + for (int i = 0; i <= m_params.fftSize/2; i++) { + int index = m_freqMap[i]; + if (index >= 0) { + frame[index] += scaled[i]; + } + } + + } else { + for (int i = 0; i <= m_params.fftSize/2; i++) { + int index = m_freqMap[i]; + if (index >= 0) { + frame[index] += mags[i]; + } + } + } + + return frame; +} + +vector<float> +FeatureExtractor::scaleMags(const vector<float> &mags) +{ + // Scale the pitch content in the given magnitude spectrum to + // accommodate a difference in tuning frequency (between the 440Hz + // reference and the actual tuning frequency of the input audio). + // We only do this when not using chroma features -- see the + // comment in makeStandardFrequencyMap() above. + + if (m_params.useChromaFrequencyMap) return mags; + + double ratio = 440.f / m_params.referenceFrequency; + + int n = static_cast<int>(mags.size()); + + vector<float> scaled(n, 0.0); + + for (int target = 0; target < n; ++target) { + + double source = target / ratio; + + int lower = int(source); + int higher = lower + 1; + + double lowerProp = higher - source; + double higherProp = source - lower; + + double value = 0.0; + if (lower >= 0 && lower < n) { + value += lowerProp * mags[lower]; + } + if (higher >= 0 && higher < n) { + value += higherProp * mags[higher]; + } + + scaled[target] = float(value); + } + + return scaled; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/FeatureExtractor.h Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,178 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. + + This program 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef FEATURE_EXTRACTOR_H +#define FEATURE_EXTRACTOR_H + +#include "MatchTypes.h" + +/** + * Convert frequency-domain audio frames into features suitable for + * MATCH alignment calculation. + * + * The default feature is a warping of the frequency data to map FFT + * frequency bins into feature bins. The mapping is linear (1-1) until + * the resolution reaches 2 points per semitone, then logarithmic with + * a semitone resolution. e.g. for 44.1kHz sampling rate and fftSize + * of 2048 (46ms), bin spacing is 21.5Hz, which is mapped linearly for + * bins 0-34 (0 to 732Hz), and logarithmically for the remaining bins + * (midi notes 79 to 127, bins 35 to 83), where all energy above note + * 127 is mapped into the final bin. + * + * Alternatively a chroma mapping is also available. This produces a + * 13-bin feature by mapping all FFT bins into bin 0 until the + * resolution reaches 1 point per semitone, then mapping each + * subsequent bin into its corresponding semitone in the remaining 12 + * bins (where bin 1 is C). e.g. e.g. for 44.1kHz sampling rate and + * fftSize of 2048 (46ms), frequencies up to 361 Hz go to bin 0, + * subsequent frequencies to the chroma bins. + */ +class FeatureExtractor +{ +public: + struct Parameters { + + Parameters(float rate_, int fftSize_) : + sampleRate(rate_), + useChromaFrequencyMap(false), + fftSize(fftSize_), + referenceFrequency(440.0), + minFrequency(100.), + maxFrequency(rate_/2.) + {} + + /** Sample rate of audio */ + float sampleRate; + + /** Flag indicating whether to use a chroma frequency map (12 + * bins) instead of the default warped spectrogram */ + bool useChromaFrequencyMap; + + /** Size of an FFT frame in samples. Note that the data passed + * in is already in the frequency domain, so this expresses + * the size of the frame that the caller will be providing. */ + int fftSize; + + /** Frequency of concert A */ + double referenceFrequency; + + /** Minimum frequency cutoff to include in feature */ + double minFrequency; + + /** Maximum frequency cutoff to include in feature */ + double maxFrequency; + }; + + /** + * Construct a FeatureExtractor with the given parameters. + * + * Note that FeatureExtractor maintains internal frame-to-frame + * state: use one FeatureExtractor per audio source, and construct + * a new one for each new source. + */ + FeatureExtractor(Parameters params); + + /** + * Return the feature vector size that will be returned from process(). + */ + int getFeatureSize() const { return m_featureSize; } + + /** + * Return the feature vector size that would be returned from + * process() with these parameters. + */ + static int getFeatureSizeFor(Parameters params); + + /** + * Process one frequency-domain audio frame (provided as real & + * imaginary components from the FFT output). Return a feature + * vector of size given by getFeatureSize(). Input vectors must + * have at least params.fftSize/2+1 elements each. + * + * Operates by mapping the frequency bins into a part-linear + * part-logarithmic array, unless useChromaFrequencyMap is true in + * which case they are mapped into chroma bins. + */ + feature_t process(const std::vector<double> &real, + const std::vector<double> &imag); + + /** + * Process one frequency-domain audio frame (provided as real & + * imaginary components from the FFT output). Return a feature + * vector of size given by getFeatureSize(). Input vectors must + * have at least params.fftSize/2+1 elements each. + * + * Operates by mapping the frequency bins into a part-linear + * part-logarithmic array, unless useChromaFrequencyMap is true in + * which case they are mapped into chroma bins. + */ + feature_t process(const std::vector<float> &real, + const std::vector<float> &imag); + + /** + * Process one frequency-domain audio frame, provided as a single + * array of alternating real and imaginary components. Input array + * must have at least 2 * (params.fftSize/2 + 1) elements. + * + * Operates by mapping the frequency bins into a part-linear + * part-logarithmic array, unless useChromaFrequencyMap is true in + * which case they are mapped into chroma bins. + */ + feature_t process(const float *carray); + +protected: + /** Make either standard or chroma map, depending on m_params */ + void makeFreqMap(); + + /** Creates a map of FFT frequency bins to comparison bins. Where + * the spacing of FFT bins is less than 0.5 semitones, the + * mapping is one to one. Where the spacing is greater than 0.5 + * semitones, the FFT energy is mapped into semitone-wide + * bins. No scaling is performed; that is the energy is summed + * into the comparison bins. */ + void makeStandardFrequencyMap(); + + /** Creates a map of FFT frequency bins to semitone chroma bins. */ + void makeChromaFrequencyMap(); + + /** Configuration parameters */ + Parameters m_params; + + /** A mapping function for mapping FFT bins to final frequency + * bins. The mapping is linear (1-1) until the resolution + * reaches 2 points per semitone, then logarithmic with a + * semitone resolution. e.g. for 44.1kHz sampling rate and + * fftSize of 2048 (46ms), bin spacing is 21.5Hz, which is mapped + * linearly for bins 0-34 (0 to 732Hz), and logarithmically for + * the remaining bins (midi notes 79 to 127, bins 35 to 83), + * where all energy above note 127 is mapped into the final + * bin. + * + * If a bin's frequency is outside the minFrequency->maxFrequency + * range, it will be mapped to a target bin of -1 and should be + * discarded. + */ + std::vector<int> m_freqMap; + + feature_t processMags(const std::vector<float> &mags); + std::vector<float> scaleMags(const std::vector<float> &mags); + + /** The size of a returned feature. */ + int m_featureSize; +}; + +#endif +
--- a/src/Finder.cpp Fri Nov 14 10:24:13 2014 +0000 +++ b/src/Finder.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -19,267 +19,480 @@ #include "Path.h" #include <algorithm> +#include <iomanip> +using namespace std; -Finder::Finder(Matcher *p1, Matcher *p2) +//#define DEBUG_FINDER 1 +//#define PERFORM_ERROR_CHECKS 1 + +Finder::Finder(Matcher *pm) { - if (!p1->firstPM) - std::cerr << "Warning: wrong args in Finder()" << std::endl; - pm1 = p1; - pm2 = p2; - index1 = 0; - index2 = 0; - rowRange = new int[2]; - colRange = new int[2]; + m_m = pm; + m_duration1 = -1; + m_duration2 = -1; } // constructor Finder::~Finder() { - delete[] rowRange; - delete[] colRange; +} + +void +Finder::setMatcher(Matcher *pm) +{ + cerr << "Finder::setMatcher: finder " << this << ", matcher " << pm << endl; + m_m = pm; +} + +void +Finder::setDurations(int d1, int d2) +{ +#ifdef DEBUG_FINDER + cerr << "*** setDurations: " << d1 << ", " << d2 << endl; +#endif + m_duration1 = d1; + m_duration2 = d2; } bool -Finder::find(int i1, int i2) +Finder::getBestRowCost(int row, int &bestCol, normpathcost_t &min) { - if (i1 >= 0) { - index1 = i1; - index2 = i2 - pm1->first[i1]; + if (!m_m->isRowAvailable(row)) return false; + pair<int, int> colRange = m_m->getColRange(row); + if (colRange.first >= colRange.second) return false; + for (int index = colRange.first; index < colRange.second; index++) { + normpathcost_t tmp = m_m->getNormalisedPathCost(row, index); + if (index == colRange.first || tmp < min) { + min = tmp; + bestCol = index; + } } - return (i1 >= 0) && (i2 >= pm1->first[i1]) && (i2 < pm1->last[i1]); -} // find() + return true; +} + +bool +Finder::getBestColCost(int col, int &bestRow, normpathcost_t &min) +{ + if (!m_m->isColAvailable(col)) return false; + pair<int, int> rowRange = m_m->getRowRange(col); + if (rowRange.first >= rowRange.second) return false; + bestRow = rowRange.first; + for (int index = rowRange.first; index < rowRange.second; index++) { + normpathcost_t tmp = m_m->getNormalisedPathCost(index, col); + if (index == rowRange.first) { + min = tmp; + } else if (tmp < min) { + min = tmp; + bestRow = index; + } + } + return true; +} void -Finder::getColRange(int row, int *range) +Finder::getBestEdgeCost(int row, int col, + int &bestRow, int &bestCol, + normpathcost_t &min) { - range[0] = pm1->first[row]; - range[1] = pm1->last[row]; -} // getColRange() - -void -Finder::getRowRange(int col, int *range) -{ - range[0] = pm2->first[col]; - range[1] = pm2->last[col]; -} // getRowRange() - -int -Finder::getExpandDirection(int row, int col) -{ - return getExpandDirection(row, col, false); -} // getExpandDirection() - -int -Finder::getExpandDirection(int row, int col, bool check) -{ - int min = getPathCost(row, col); + min = m_m->getNormalisedPathCost(row, col); + bestRow = row; bestCol = col; - getRowRange(col, rowRange); - if (rowRange[1] > row+1) - rowRange[1] = row+1; // don't cheat by looking at future :) - for (int index = rowRange[0]; index < rowRange[1]; index++) { - int tmp = getPathCost(index, col); + + pair<int, int> rowRange = m_m->getRowRange(col); + if (rowRange.second > row+1) { + rowRange.second = row+1; // don't cheat by looking at future :) + } + for (int index = rowRange.first; index < rowRange.second; index++) { + normpathcost_t tmp = m_m->getNormalisedPathCost(index, col); if (tmp < min) { min = tmp; bestRow = index; } } - getColRange(row, colRange); - if (colRange[1] > col+1) - colRange[1] = col+1; // don't cheat by looking at future :) - for (int index = colRange[0]; index < colRange[1]; index++) { - int tmp = getPathCost(row, index); + + pair<int, int> colRange = m_m->getColRange(row); + if (colRange.second > col+1) { + colRange.second = col+1; // don't cheat by looking at future :) + } + for (int index = colRange.first; index < colRange.second; index++) { + normpathcost_t tmp = m_m->getNormalisedPathCost(row, index); if (tmp < min) { min = tmp; bestCol = index; bestRow = row; } } - // System.err.print(" BEST: " + bestRow + " " + bestCol + " " + check); - // System.err.println(" " + pm1->frameCount + " " + pm2->frameCount); - if (check) { - // System.err.println(find(row+1, col) + " " + find(row, col+1)); - if (!find(row, col+1)) - return ADVANCE_THIS; - if (!find(row+1, col)) - return ADVANCE_OTHER; +} + +advance_t +Finder::getExpandDirection() +{ + return getExpandDirection(m_m->getFrameCount() - 1, + m_m->getOtherFrameCount() - 1); +} + +advance_t +Finder::getExpandDirection(int row, int col) +{ + // To determine which direction to expand the search area in, we + // look at the path costs along the leading edges of the search + // area (the final row and column within the area). We find the + // lowest path cost within the final row, and the lowest within + // the final column, and we compare them. If the row is cheaper + // then we expand by adding another row next to it; if the column + // is cheaper then we expand by adding another column next to + // it. (The overall lowest path cost across the row and column + // represents the best alignment we have within the entire search + // area given the data available and the assumption that the piece + // is not ending yet.) + + int bestRow = row; + int bestCol = col; + normpathcost_t bestCost = -1; + +// cerr << "Finder " << this << "::getExpandDirection: "; + + getBestEdgeCost(row, col, bestRow, bestCol, bestCost); + +// cerr << "at [" << row << "," << col << "] (cost " << m_m->getPathCost(row, col) << ") blocksize = " << m_m->getBlockSize() << " best is [" << bestRow << "," << bestCol << "] (cost " << bestCost << ")" << endl; + + if (bestRow == row) { + if (bestCol == col) { + return AdvanceBoth; + } else { + return AdvanceThis; + } + } else if (bestCol == col) { + return AdvanceOther; + } else { + return AdvanceNone; } - return ((bestRow==row)? ADVANCE_THIS: 0) | - ((bestCol==col)? ADVANCE_OTHER: 0); - -} // getExpandDirection() - -unsigned char -Finder::getDistance(int row, int col) -{ - if (find(row, col)) { - return pm1->distance[row][col - pm1->first[row]]; - } - std::cerr << "getDistance(" << row << "," << col << "): out of bounds" << std::endl; - throw "getDistance index out of bounds"; -} // getDistance()/2 - -void -Finder::setDistance(int row, int col, unsigned char b) -{ - if (find(row, col)) { - pm1->distance[row][col - pm1->first[row]] = b; - return; - } - std::cerr << "setDistance(" << row << "," << col << "," << b << "): out of bounds" << std::endl; - throw "setDistance index out of bounds"; -} // setDistance() - -int -Finder::getPathCost(int row, int col) -{ - if (find(row, col)) // "1" avoids div by 0 below - return pm1->bestPathCost[row][col - pm1->first[row]]*100/ (1+row+col); - std::cerr << "getPathCost(" << row << "," << col << "): out of bounds" << std::endl; - throw "getPathCost index out of bounds"; -} // getPathCost() - -int -Finder::getRawPathCost(int row, int col) -{ - if (find(row, col)) - return pm1->bestPathCost[row][col - pm1->first[row]]; - std::cerr << "getRawPathCost(" << row << "," << col << "): out of bounds" << std::endl; - throw "getRawPathCost index out of bounds"; -} // getRawPathCost() - -void -Finder::setPathCost(int row, int col, int i) -{ - if (find(row, col)) { - pm1->bestPathCost[row][col - pm1->first[row]] = i; - return; - } - std::cerr << "setPathCost(" << row << "," << col << "," << i << "): out of bounds" << std::endl; - throw "setPathCost index out of bounds"; -} // setPathCost() - -unsigned char -Finder::getDistance() -{ - return pm1->distance[index1][index2]; -} // getDistance()/0 - -void -Finder::setDistance(int b) -{ - pm1->distance[index1][index2] = (unsigned char)b; -} // setDistance() - -int -Finder::getPathCost() -{ - return pm1->bestPathCost[index1][index2]; -} // getPathCost() - -void -Finder::setPathCost(int i) -{ - pm1->bestPathCost[index1][index2] = i; -} // setPathCost() +} void Finder::recalculatePathCostMatrix(int r1, int c1, int r2, int c2) { - if (!find(r1,c1)) { - std::cerr << "recalculatePathCostMatrix(" << r1 << "," << c1 << "): out of bounds" << std::endl; - throw "recalculatePathCostMatrix index out of bounds"; + int prevRowStart = 0, prevRowStop = 0; + + for (int r = r1; r <= r2; r++) { + + pair<int, int> colRange = m_m->getColRange(r); + + int rowStart = max(c1, colRange.first); + int rowStop = min(c2 + 1, colRange.second); + + for (int c = rowStart; c < rowStop; c++) { + + advance_t dir = AdvanceNone; + pathcost_t straightIncrement = m_m->getDistance(r, c); + pathcost_t diagIncrement = pathcost_t(straightIncrement * + m_m->getDiagonalWeight()); + + if (r > r1) { // not first row + pathcost_t min = -1; + if ((c > prevRowStart) && (c <= prevRowStop)) { + // diagonal from (r-1,c-1) + min = m_m->getPathCost(r-1, c-1) + diagIncrement; + dir = AdvanceBoth; + } + if ((c >= prevRowStart) && (c < prevRowStop)) { + // vertical from (r-1,c) + pathcost_t cost = m_m->getPathCost(r-1, c) + straightIncrement; + if ((min < 0) || (cost < min)) { + min = cost; + dir = AdvanceThis; + } + } + if (c > rowStart) { + // horizontal from (r,c-1) + pathcost_t cost = m_m->getPathCost(r, c-1) + straightIncrement; + if ((min < 0) || (cost < min)) { + min = cost; + dir = AdvanceOther; + } + } + + m_m->setPathCost(r, c, dir, min); + + } else if (c > rowStart) { // first row + // horizontal from (r,c-1) + m_m->setPathCost(r, c, AdvanceOther, + m_m->getPathCost(r, c-1) + straightIncrement); + } + } + + prevRowStart = rowStart; + prevRowStop = rowStop; } - int thisRowStart, c; +} + +#ifdef PERFORM_ERROR_CHECKS +Finder::ErrorPosition +Finder::checkPathCostMatrix() +{ + ErrorPosition err; + + int r1 = 0; + int c1 = 0; + int r2 = m_m->getFrameCount() - 1; + int c2 = m_m->getOtherFrameCount() - 1; + + if (r2 < r1 || c2 < c1) { + return err; + } + int prevRowStart = 0, prevRowStop = 0; + for (int r = r1; r <= r2; r++) { - thisRowStart = pm1->first[r]; - if (thisRowStart < c1) - thisRowStart = c1; - for (c = thisRowStart; c <= c2; c++) { - if (find(r,c)) { - int i2 = index2; - int newCost = pm1->distance[r][i2]; - int dir = 0; - if (r > r1) { // not first row - int min = -1; - if ((c > prevRowStart) && (c <= prevRowStop)) { - // diagonal from (r-1,c-1) - min = pm1->bestPathCost[r-1][c-pm1->first[r-1]-1] + - newCost * 2; - dir = ADVANCE_BOTH; + + pair<int, int> colRange = m_m->getColRange(r); + + int rowStart = max(c1, colRange.first); + int rowStop = min(c2 + 1, colRange.second); + + for (int c = rowStart; c < rowStop; c++) { + + advance_t dir = AdvanceNone; + pathcost_t updateTo = InvalidPathCost; + distance_t distance = m_m->getDistance(r, c); + pathcost_t straightIncrement = distance; + pathcost_t diagIncrement = pathcost_t(distance * m_m->getDiagonalWeight()); + err.distance = distance; + + if (r > r1) { // not first row + pathcost_t min = -1; + if ((c > prevRowStart) && (c <= prevRowStop)) { + // diagonal from (r-1,c-1) + min = m_m->getPathCost(r-1, c-1) + diagIncrement; + err.prevCost = m_m->getPathCost(r-1, c-1); + dir = AdvanceBoth; + } + if ((c >= prevRowStart) && (c < prevRowStop)) { + // vertical from (r-1,c) + pathcost_t cost = m_m->getPathCost(r-1, c) + straightIncrement; + if ((min < 0) || (cost < min)) { + min = cost; + err.prevCost = m_m->getPathCost(r-1, c); + dir = AdvanceThis; } - if ((c >= prevRowStart) && (c < prevRowStop)) { - // vertical from (r-1,c) - int cost = pm1->bestPathCost[r-1][c-pm1->first[r-1]] + - newCost; - if ((min == -1) || (cost < min)) { - min = cost; - dir = ADVANCE_THIS; - } + } + if (c > rowStart) { + // horizontal from (r,c-1) + pathcost_t cost = m_m->getPathCost(r, c-1) + straightIncrement; + if ((min < 0) || (cost < min)) { + min = cost; + err.prevCost = m_m->getPathCost(r, c-1); + dir = AdvanceOther; } - if (c > thisRowStart) { - // horizontal from (r,c-1) - int cost =pm1->bestPathCost[r][i2-1]+newCost; - if ((min == -1) || (cost < min)) { - min = cost; - dir = ADVANCE_OTHER; - } - } - pm1->bestPathCost[r][i2] = min; - } else if (c > thisRowStart) { // first row + } + + updateTo = min; + + } else { // first row + + if (c > rowStart) { // horizontal from (r,c-1) - pm1->bestPathCost[r][i2] = pm1->bestPathCost[r][i2-1] + - newCost; - dir = ADVANCE_OTHER; + updateTo = m_m->getPathCost(r, c-1) + straightIncrement; + err.prevCost = m_m->getPathCost(r, c-1); + dir = AdvanceOther; } - if ((r != r1) || (c != c1)) { - pm1->distance[r][i2] = (unsigned char) - ((pm1->distance[r][i2] & MASK) | dir); + } + + if (dir != AdvanceNone) { + if (m_m->getAdvance(r, c) != dir) { + err.type = ErrorPosition::WrongAdvance; + err.r = r; + err.c = c; + err.costWas = m_m->getPathCost(r, c); + err.costShouldBe = updateTo; + err.advanceWas = m_m->getAdvance(r, c); + err.advanceShouldBe = dir; + return err; } - } else - break; // end of row + if (m_m->getPathCost(r, c) != updateTo) { + err.type = ErrorPosition::WrongCost; + err.r = r; + err.c = c; + err.costWas = m_m->getPathCost(r, c); + err.costShouldBe = updateTo; + err.advanceWas = m_m->getAdvance(r, c); + err.advanceShouldBe = dir; + return err; + } + } else { + // AdvanceNone should occur only at r = r1, c = c1 + if (r != r1 || c != c1) { + err.type = ErrorPosition::NoAdvance; + err.r = r; + err.c = c; + err.costWas = m_m->getPathCost(r, c); + err.costShouldBe = updateTo; + err.advanceWas = m_m->getAdvance(r, c); + err.advanceShouldBe = dir; + return err; + } + } } - prevRowStart = thisRowStart; - prevRowStop = c; + + prevRowStart = rowStart; + prevRowStop = rowStop; } -} // recalculatePathCostMatrix() + + return err; +} + +void +Finder::checkAndReport() +{ + cerr << "Finder: Checking path-cost matrix..." << endl; + ErrorPosition err = checkPathCostMatrix(); + if (err.type == ErrorPosition::NoError) { + cerr << "No errors found" << endl; + } else { + cerr << "\nWARNING: Checking path-cost matrix returned mismatch:" << endl; + cerr << "Type: " << err.type << ": "; + switch (err.type) { + case ErrorPosition::NoError: break; + case ErrorPosition::WrongCost: cerr << "WrongCost"; break; + case ErrorPosition::WrongAdvance: cerr << "WrongAdvance"; break; + case ErrorPosition::NoAdvance: cerr << "NoAdvance"; break; + } + cerr << endl; + cerr << "At row " << err.r << ", column " << err.c + << "\nShould be advancing " + << Matcher::advanceToString(err.advanceShouldBe) + << ", advance in matrix is " + << Matcher::advanceToString(err.advanceWas) + << "\nPrev cost " << err.prevCost + << " plus distance " << distance_print_t(err.distance) + << " [perhaps diagonalised] gives " + << err.costShouldBe << ", matrix contains " << err.costWas + << endl; + cerr << "Note: diagonal weight = " << m_m->getDiagonalWeight() << endl; + cerr << endl; + + int w(4); + int ww(15); + + cerr << "Distance matrix leading up to this point:" << endl; + cerr << setprecision(12) << setw(w) << ""; + for (int i = -4; i <= 0; ++i) { + cerr << setw(ww) << i; + } + cerr << endl; + for (int j = -4; j <= 0; ++j) { + cerr << setw(w) << j; + for (int i = -4; i <= 0; ++i) { + cerr << setw(ww) + << distance_print_t(m_m->getDistance(err.r + j, err.c + i)); + } + cerr << endl; + } + cerr << endl; + + cerr << "Cost matrix leading up to this point:" << endl; + cerr << setw(w) << ""; + for (int i = -4; i <= 0; ++i) { + cerr << setw(ww) << i; + } + cerr << endl; + for (int j = -4; j <= 0; ++j) { + cerr << setw(w) << j; + for (int i = -4; i <= 0; ++i) { + cerr << setw(ww) << m_m->getPathCost(err.r + j, err.c + i); + } + cerr << endl; + } + cerr << endl; + } +} +#endif + +pathcost_t +Finder::getOverallCost() +{ + int ex = m_m->getOtherFrameCount() - 1; + int ey = m_m->getFrameCount() - 1; + + if (ex < 0 || ey < 0) { + return 0; + } + + return m_m->getPathCost(ey, ex); +} int Finder::retrievePath(bool smooth, vector<int> &pathx, vector<int> &pathy) { - int x = pm2->getFrameCount() - 1; - int y = pm1->getFrameCount() - 1; + pathx.clear(); + pathy.clear(); + +#ifdef PERFORM_ERROR_CHECKS + checkAndReport(); +#endif + + int ex = m_m->getOtherFrameCount() - 1; + int ey = m_m->getFrameCount() - 1; + + if (ex < 0 || ey < 0) { + return 0; + } + + int x = ex; + int y = ey; + +#ifdef DEBUG_FINDER + cerr << "*** retrievePath: smooth = " << smooth << endl; + cerr << "*** retrievePath: before: x = " << x << ", y = " << y << endl; +#endif + + if (m_duration2 > 0 && m_duration2 < m_m->getOtherFrameCount()) { + x = m_duration2 - 1; + } + if (m_duration1 > 0 && m_duration1 < m_m->getFrameCount()) { + y = m_duration1 - 1; + } + + if (!m_m->isAvailable(y, x)) { + // Path did not pass through the expected end point -- + // probably means the pieces are substantially different in + // the later bits. Reset the expected end point to the end of + // both files including any trailing silence. + cerr << "NOTE: Path did not pass through expected end point, inputs are probably significantly different" << endl; + x = ex; + y = ey; + } recalculatePathCostMatrix(0, 0, y, x); - pathx.clear(); - pathy.clear(); - - while (find(y, x) && ((x > 0) || (y > 0))) { +#ifdef DEBUG_FINDER + cerr << "*** retrievePath: start: x = " << x << ", y = " << y << endl; +#endif + + while (m_m->isAvailable(y, x) && (x > 0 || y > 0)) { // cerr << "x = " << x << ", y = " << y; pathx.push_back(x); pathy.push_back(y); - switch (getDistance() & ADVANCE_BOTH) { - case ADVANCE_THIS: -// cerr << ", going down (dist = " << (int)getDistance() << ")" << endl; + switch (m_m->getAdvance(y, x)) { + case AdvanceThis: +// cerr << ", going down (dist = " << getDistance() << ")" << endl; y--; break; - case ADVANCE_OTHER: -// cerr << ", going left (dist = " << (int)getDistance() << ")" << endl; + case AdvanceOther: +// cerr << ", going left (dist = " << getDistance() << ")" << endl; x--; break; - case ADVANCE_BOTH: -// cerr << ", going diag (dist = " << (int)getDistance() << ")" << endl; + case AdvanceBoth: +// cerr << ", going diag (dist = " << getDistance() << ")" << endl; x--; y--; break; - default: // this would indicate a bug, but we wouldn't want to hang -// cerr << "WARNING: Neither matcher advanced in path backtrack at (" << x << "," << y << ")" << endl; + case AdvanceNone: // this would indicate a bug, but we wouldn't want to hang + cerr << "WARNING: Neither matcher advanced in path backtrack at (" << x << "," << y << ")" << endl; if (x > y) { x--; } else { @@ -289,14 +502,20 @@ } } - std::reverse(pathx.begin(), pathx.end()); - std::reverse(pathy.begin(), pathy.end()); + if (x > 0 || y > 0) { + cerr << "WARNING: Ran out of available path at (" << y << "," << x + << ")!" << endl; + } + + reverse(pathx.begin(), pathx.end()); + reverse(pathy.begin(), pathy.end()); if (smooth) { - int smoothedLen = Path().smooth(pathx, pathy, pathx.size()); + int smoothedLen = Path().smooth + (pathx, pathy, static_cast<int>(pathx.size())); return smoothedLen; } else { - return pathx.size(); + return static_cast<int>(pathx.size()); } }
--- a/src/Finder.h Fri Nov 14 10:24:13 2014 +0000 +++ b/src/Finder.h Fri Feb 27 09:29:37 2015 +0000 @@ -22,57 +22,66 @@ #include "Matcher.h" -/** Maps cost matrix coordinates into an efficient - * (linear instead of quadratic space) representation. - * Stores result of most recent mapping for fast - * sequential access. - */ -class Finder { +class Finder +{ +public: + Finder(Matcher *pm); -protected: - Matcher *pm1, *pm2; - int index1, index2, bestRow, bestCol; - int *rowRange; - int *colRange; - -public: - Finder(Matcher *p1, Matcher *p2); + // default copy ctor and operator= are fine ~Finder(); - /** Sets up the instance variables to point to the given - * coordinate in the distance matrix. - * - * @param i1 frameNumber in the first Matcher - * @param i2 frameNumber in the second Matcher - * @return true iff the point (i2,i1) is represented in the distance matrix + void setMatcher(Matcher *pm); + + /** + * Tell the finder that one or both files ends sooner than it + * thought, i.e. that some of the trailing features are silence or + * otherwise to be ignored. d1 and d2 are feature frame counts for + * matchers 1 and 2 respectively. If this is not called, the full + * duration of each input will be considered. */ - bool find(int i1, int i2); + void setDurations(int d1, int d2); - /** Returns the range [lo,hi) of legal column indices for the - * given row. */ - void getColRange(int row, int *range); + /** + * Find the location and normalised path cost of the column with + * the cheapest path cost within the given row. If the row is out + * of range, return false and leave the bestCol and bestCost + * variables unchanged. + */ + bool getBestRowCost(int row, int &bestCol, normpathcost_t &bestCost); - /** Returns the range [lo,hi) of legal row indices for the given - * column. */ - void getRowRange(int col, int *range); + /** + * Find the location and normalised path cost of the row with the + * cheapest path cost within the given column. If the column is + * out of range, return false and leave the bestRow and bestCost + * variables unchanged. + */ + bool getBestColCost(int col, int &bestRow, normpathcost_t &bestCost); + + /** + * Find the location and normalised path cost of the cheapest path + * cost within the final row and column of the search area, given + * that the area extends as far as the point at (row, col). This + * is used by getExpandDirection and can also be used, for + * example, to determine the current best estimate alignment for a + * frame we have just reached. + */ + void getBestEdgeCost(int row, int col, + int &bestRow, int &bestCol, + normpathcost_t &bestCost); - int getExpandDirection(int row, int col); - int getExpandDirection(int row, int col, bool check); - - unsigned char getDistance(int row, int col); - void setDistance(int row, int col, unsigned char b); - - int getPathCost(int row, int col); - int getRawPathCost(int row, int col); - void setPathCost(int row, int col, int i); - - unsigned char getDistance(); - void setDistance(int b); - - int getPathCost(); - void setPathCost(int i); - + /** + * Calculate which direction to expand the search area in, given + * its current extents. + */ + advance_t getExpandDirection(); + + /** + * Calculate which direction to expand the search area in, given + * that so far it extends as far as the point at (row, col). + */ + advance_t getExpandDirection(int row, int col); + /** Calculates a rectangle of the path cost matrix so that the * minimum cost path between the bottom left and top right * corners can be computed. Caches previous values to avoid @@ -97,7 +106,36 @@ * @param smooth whether to smooth the path before returning it */ int retrievePath(bool smooth, std::vector<int> &pathx, std::vector<int> &pathy); + + /** + * Get the path cost for the overall path to the end of both + * sources. + */ + pathcost_t getOverallCost(); -}; // class Finder +protected: +#ifdef PERFORM_ERROR_CHECKS + struct ErrorPosition { + enum Type { NoError = 0, WrongCost, WrongAdvance, NoAdvance }; + ErrorPosition() : type(NoError) { } + Type type; + int r; + int c; + pathcost_t prevCost; + distance_t distance; + pathcost_t costWas; + pathcost_t costShouldBe; + advance_t advanceWas; + advance_t advanceShouldBe; + }; + ErrorPosition checkPathCostMatrix(); + void checkAndReport(); +#endif + + Matcher *m_m; // I do not own this + + int m_duration1; + int m_duration2; +}; #endif
--- a/src/MatchFeatureFeeder.cpp Fri Nov 14 10:24:13 2014 +0000 +++ b/src/MatchFeatureFeeder.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -19,23 +19,57 @@ using std::vector; MatchFeatureFeeder::MatchFeatureFeeder(Matcher *m1, Matcher *m2) : - pm1(m1), pm2(m2) + m_pm1(m1), + m_pm2(m2), + m_finder(m_pm1) { - finder = new Finder(m1, m2); } MatchFeatureFeeder::~MatchFeatureFeeder() { - delete finder; } void -MatchFeatureFeeder::feed(vector<double> f1, vector<double> f2) +MatchFeatureFeeder::feed(feature_t f1, feature_t f2) { - q1.push(f1); - q2.push(f2); + // We maintain two FIFO queues of feature vectors, one per input + // stream. When the match-feeder function is entered, it knows + // that it has at least one feature in each queue. It loops, + // processing up to one feature per matcher, until a queue is + // empty. Then it returns, to be called again with more data. - while (!q1.empty() && !q2.empty()) { + if (!f1.empty()) { + m_q1.push(f1); + } + + if (!f2.empty()) { + m_q2.push(f2); + } + + while (!m_q1.empty() && !m_q2.empty()) { + feedBlock(); + } +} + +int +MatchFeatureFeeder::getEstimatedReferenceFrame() +{ + if (m_pm1->getFrameCount() == 0 || m_pm2->getFrameCount() == 0) { + return 0; + } + int bestRow = 0; + normpathcost_t bestCost = 0; + if (!m_finder.getBestColCost(m_pm2->getFrameCount()-1, bestRow, bestCost)) { + return -1; + } else { + return bestRow; + } +} + +void +MatchFeatureFeeder::finish() +{ + while (!m_q1.empty() || !m_q2.empty()) { feedBlock(); } } @@ -43,42 +77,50 @@ void MatchFeatureFeeder::feedBlock() { - if (pm1->frameCount < pm1->blockSize) { // fill initial block + if (m_q1.empty()) { // ended + feed2(); + } else if (m_q2.empty()) { // ended + feed1(); + } else if (m_pm1->isFillingInitialBlock()) { feed1(); feed2(); - } - else if (pm1->runCount >= pm1->params.maxRunCount) { // slope constraints + } else if (m_pm1->isOverrunning()) { // slope constraints feed2(); - } else if (pm2->runCount >= pm2->params.maxRunCount) { + } else if (m_pm2->isOverrunning()) { feed1(); } else { - switch (finder->getExpandDirection - (pm1->frameCount-1, pm2->frameCount-1)) { - case ADVANCE_THIS: + switch (m_finder.getExpandDirection()) { + case AdvanceThis: feed1(); break; - case ADVANCE_OTHER: + case AdvanceOther: feed2(); break; - case ADVANCE_BOTH: + case AdvanceBoth: feed1(); feed2(); break; + case AdvanceNone: + cerr << "m_finder says AdvanceNone!" << endl; + break; } } + + m_fpx.push_back(m_pm2->getFrameCount()); + m_fpy.push_back(m_pm1->getFrameCount()); } void MatchFeatureFeeder::feed1() { - pm1->consumeFeatureVector(q1.front()); - q1.pop(); + m_pm1->consumeFeatureVector(m_q1.front()); + m_q1.pop(); } void MatchFeatureFeeder::feed2() { - pm2->consumeFeatureVector(q2.front()); - q2.pop(); + m_pm2->consumeFeatureVector(m_q2.front()); + m_q2.pop(); }
--- a/src/MatchFeatureFeeder.h Fri Nov 14 10:24:13 2014 +0000 +++ b/src/MatchFeatureFeeder.h Fri Feb 27 09:29:37 2015 +0000 @@ -33,22 +33,60 @@ * respectively (depending on their advance status). Matchers must * have been constructed using the external featureSize * constructor. + * + * f1 and f2 are normally expected to have the same number of + * values, and that number should be the featureSize passed to the + * constructors for both Matchers. The exception is when one input + * ends before the other one: subsequent calls should pass a + * feature vector as normal for the input that is still going on, + * and an empty vector for the one that has ended. */ - void feed(std::vector<double> f1, std::vector<double> f2); + void feed(feature_t f1, feature_t f2); - Finder *getFinder() { return finder; } + /** + * Get the best estimate for the frame in the reference (f1) + * corresponding to the latest frame in the other input (f2). + */ + int getEstimatedReferenceFrame(); + + /** + * Indicate that both inputs have come to an end. + */ + void finish(); + + /** + * Return the forward path, that is, the estimate of the + * lowest-cost path that was generated (possibly in real-time) + * while initially tracking the inputs. This is the path that is + * used to determine the shape of the search zone within which the + * eventual reverse path will be sought by the Finder. + */ + void retrieveForwardPath(std::vector<int> &pathx, std::vector<int> &pathy) { + pathx = m_fpx; + pathy = m_fpy; + } + + Finder *getFinder() { return &m_finder; } protected: void feedBlock(); void feed1(); void feed2(); - Finder *finder; - Matcher *pm1; - Matcher *pm2; + Matcher *m_pm1; // I do not own this + Matcher *m_pm2; // I do not own this - std::queue<std::vector<double> > q1; - std::queue<std::vector<double> > q2; + Finder m_finder; // I own this, and it refers to m_pm1 + + std::queue<feature_t> m_q1; + std::queue<feature_t> m_q2; + + vector<int> m_fpx; + vector<int> m_fpy; + + // not provided: + MatchFeatureFeeder(const MatchFeatureFeeder &other); + MatchFeatureFeeder &operator=(const MatchFeatureFeeder &other); }; #endif
--- a/src/MatchFeeder.cpp Fri Nov 14 10:24:13 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Vamp feature extraction plugin using the MATCH audio alignment - algorithm. - - Centre for Digital Music, Queen Mary, University of London. - This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. - - This program 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. See the file - COPYING included with this distribution for more information. -*/ - -#include "MatchFeeder.h" - -using std::vector; - -MatchFeeder::MatchFeeder(Matcher *m1, Matcher *m2) : - pm1(m1), pm2(m2) -{ - fftSize = m1->params.fftSize; - finder = new Finder(m1, m2); - reBuffer = new double[fftSize/2+1]; - imBuffer = new double[fftSize/2+1]; -} - -MatchFeeder::~MatchFeeder() -{ - delete[] imBuffer; - delete[] reBuffer; - while (!q1.empty()) { - delete[] q1.front(); - q1.pop(); - } - while (!q2.empty()) { - delete[] q2.front(); - q2.pop(); - } - delete finder; -} - -void -MatchFeeder::feed(const float *const *input) -{ - // We maintain two FIFO queues of audio data frame block pointers, - // one per input stream. When the match-feeder function is - // entered, it knows that it has at least one block in each queue. - // It loops, processing up to one block per matcher, until a queue - // is empty. Then it returns, to be called again with more data. - - prepare(input); - - while (!q1.empty() && !q2.empty()) { -// std::cerr << "MatchFeeder::feed: q1 " << q1.size() << " q2 " << q2.size() << std::endl; - (void)feedBlock(); - } -} - -MatchFeeder::Features -MatchFeeder::feedAndGetFeatures(const float *const *input) -{ - prepare(input); - - Features all; - - while (!q1.empty() && !q2.empty()) { - Features ff = feedBlock(); - all.f1.insert(all.f1.end(), ff.f1.begin(), ff.f1.end()); - all.f2.insert(all.f2.end(), ff.f2.begin(), ff.f2.end()); - } - - return all; -} - -void -MatchFeeder::prepare(const float *const *input) -{ - float *block = new float[fftSize+2]; - for (size_t i = 0; i < fftSize+2; ++i) { - block[i] = input[0][i]; - } - q1.push(block); - - block = new float[fftSize+2]; - for (size_t i = 0; i < fftSize+2; ++i) { - block[i] = input[1][i]; - } - q2.push(block); -} - -MatchFeeder::Features -MatchFeeder::feedBlock() -{ - Features ff; - vector<double> f1, f2; - - if (pm1->frameCount < pm1->blockSize) { // fill initial block -// std::cerr << "feeding initial block" << std::endl; - f1 = feed1(); - f2 = feed2(); - } -//!!! } else if (pm1->atEnd) { -// feed2(); -//!!! } else if (pm2->atEnd) -// feed1(); - else if (pm1->runCount >= pm1->params.maxRunCount) { // slope constraints -// std::cerr << "pm1 too slopey" << std::endl; - f2 = feed2(); - } else if (pm2->runCount >= pm2->params.maxRunCount) { -// std::cerr << "pm2 too slopey" << std::endl; - f1 = feed1(); - } else { - switch (finder->getExpandDirection - (pm1->frameCount-1, pm2->frameCount-1)) { - case ADVANCE_THIS: -// std::cerr << "finder says ADVANCE_THIS" << std::endl; - f1 = feed1(); - break; - case ADVANCE_OTHER: -// std::cerr << "finder says ADVANCE_OTHER" << std::endl; - f2 = feed2(); - break; - case ADVANCE_BOTH: -// std::cerr << "finder says ADVANCE_BOTH" << std::endl; - f1 = feed1(); - f2 = feed2(); - break; - } - } - - if (!f1.empty()) ff.f1.push_back(f1); - if (!f2.empty()) ff.f2.push_back(f2); - return ff; -} - -vector<double> -MatchFeeder::feed1() -{ -// std::cerr << "feed1" << std::endl; - float *block = q1.front(); - q1.pop(); - for (size_t i = 0; i <= fftSize/2; ++i) { - reBuffer[i] = block[i*2]; - } - for (size_t i = 0; i <= fftSize/2; ++i) { - imBuffer[i] = block[i*2+1]; - } - delete[] block; - return pm1->consumeFrame(reBuffer, imBuffer); -} - -vector<double> -MatchFeeder::feed2() -{ -// std::cerr << "feed2" << std::endl; - float *block = q2.front(); - q2.pop(); - for (size_t i = 0; i <= fftSize/2; ++i) { - reBuffer[i] = block[i*2]; - } - for (size_t i = 0; i <= fftSize/2; ++i) { - imBuffer[i] = block[i*2+1]; - } - delete[] block; - return pm2->consumeFrame(reBuffer, imBuffer); -} -
--- a/src/MatchFeeder.h Fri Nov 14 10:24:13 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ -/* - Vamp feature extraction plugin using the MATCH audio alignment - algorithm. - - Centre for Digital Music, Queen Mary, University of London. - This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. - - This program 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. See the file - COPYING included with this distribution for more information. -*/ - -#ifndef _MATCH_FEEDER_H_ -#define _MATCH_FEEDER_H_ - -#include "Matcher.h" -#include "Finder.h" - -#include <queue> -#include <vector> - -class MatchFeeder -{ -public: - MatchFeeder(Matcher *m1, Matcher *m2); - ~MatchFeeder(); - - /** - * Feed the two supplied channels of frequency-domain input data - * to feeders 1 and 2 respectively, as appropriate (depending on - * their advance status). - */ - void feed(const float *const *input); - - struct Features { - std::vector<std::vector<double> > f1; - std::vector<std::vector<double> > f2; - }; - - /** - * Feed the two supplied channels of frequency-domain input data - * to matchers 1 and 2 respectively, as appropriate (depending on - * their advance status) and return any new feature vectors - * calculated by the two feeders. - */ - Features feedAndGetFeatures(const float *const *input); - - Finder *getFinder() { return finder; } - -protected: - void prepare(const float *const *input); - Features feedBlock(); - std::vector<double> feed1(); - std::vector<double> feed2(); - - Finder *finder; - Matcher *pm1; - Matcher *pm2; - - size_t fftSize; - double *reBuffer; - double *imBuffer; - - std::queue<float *> q1; - std::queue<float *> q2; -}; - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/MatchPipeline.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,162 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. + + This program 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "MatchPipeline.h" + +//#define DEBUG_MATCH_PIPELINE 1 + +MatchPipeline::MatchPipeline(FeatureExtractor::Parameters feParams, + FeatureConditioner::Parameters fcParams, + DistanceMetric::Parameters dParams, + Matcher::Parameters matchParams, + double secondReferenceFrequency) : + m_fe1(feParams), + m_fe2(paramsWithFreq(feParams, secondReferenceFrequency)), + m_fc1(fcParams), + m_fc2(fcParams), + m_pm1(matchParams, dParams, 0), + m_pm2(matchParams, dParams, &m_pm1), + m_feeder(&m_pm1, &m_pm2), + m_lastFrameIn1(0), + m_lastFrameIn2(0), + m_frameNo(0) +{ + m_pm1.setOtherMatcher(&m_pm2); +} + +MatchPipeline::~MatchPipeline() +{ +} + +FeatureExtractor::Parameters +MatchPipeline::paramsWithFreq(FeatureExtractor::Parameters params, double freq) +{ + if (freq == 0.0) return params; + params.referenceFrequency = freq; + return params; +} + +void +MatchPipeline::feedFrequencyDomainAudio(const float *arr1, const float *arr2) +{ + feedFeatures(m_fe1.process(arr1), m_fe2.process(arr2)); +} + +void +MatchPipeline::feedFeatures(const feature_t &f1, const feature_t &f2) +{ + m_f1 = f1; + m_f2 = f2; + +#ifdef DEBUG_MATCH_PIPELINE + if (m_lastFrameIn1 == 1) { + cerr << "features 1 -> "; + for (int i = 0; i < (int) m_f1.size(); ++i) { + cerr << m_f1[i] << " "; + } + cerr << endl; + } +#endif + + feedConditionedFeatures(m_fc1.process(f1), m_fc2.process(f2)); +} + +void +MatchPipeline::feedConditionedFeatures(const feature_t &c1, const feature_t &c2) +{ + m_c1 = c1; + m_c2 = c2; + +#ifdef DEBUG_MATCH_PIPELINE + if (m_lastFrameIn1 == 1) { + cerr << "conditioned features 1 -> "; + for (int i = 0; i < (int) m_c1.size(); ++i) { + cerr << m_c1[i] << " "; + } + cerr << endl; + } +#endif + + m_feeder.feed(c1, c2); + + if (aboveThreshold(c1)) m_lastFrameIn1 = m_frameNo; + if (aboveThreshold(c2)) m_lastFrameIn2 = m_frameNo; + +#ifdef DEBUG_MATCH_PIPELINE + cerr << "last frames are " << m_lastFrameIn1 << ", " << m_lastFrameIn2 + << endl; +#endif + + ++m_frameNo; +} + +void +MatchPipeline::extractFeatures(feature_t &f1, feature_t &f2) +{ + f1 = m_f1; + f2 = m_f2; +} + +void +MatchPipeline::extractConditionedFeatures(feature_t &c1, feature_t &c2) +{ + c1 = m_c1; + c2 = m_c2; +} + +bool +MatchPipeline::aboveThreshold(const feature_t &f) +{ + // This threshold is used only to determine when either of the + // input streams has ended -- the last frame for a stream is + // considered to be the last one that was above the + // threshold. This is different from the silence threshold in + // FeatureConditioner. + double threshold = 1e-4f; + double sum = 0.f; + for (int i = 0; i < int(f.size()); ++i) { + sum += f[i] * f[i]; + } +#ifdef DEBUG_MATCH_PIPELINE + cerr << "aboveThreshold: sum " << sum << ", threshold " << threshold + << ", returning " << (sum >= threshold) << endl; +#endif + return (sum >= threshold); +} + +void +MatchPipeline::finish() +{ + m_feeder.finish(); + m_feeder.getFinder()->setDurations(m_lastFrameIn1, m_lastFrameIn2); +} + +int +MatchPipeline::retrievePath(bool smooth, std::vector<int> &pathx, std::vector<int> &pathy) +{ + return m_feeder.getFinder()->retrievePath(smooth, pathx, pathy); +} + +void +MatchPipeline::retrieveForwardPath(std::vector<int> &pathx, std::vector<int> &pathy) { + return m_feeder.retrieveForwardPath(pathx, pathy); +} + +double +MatchPipeline::getOverallCost() +{ + return m_feeder.getFinder()->getOverallCost(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/MatchPipeline.h Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,142 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. + + This program 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef MATCH_PIPELINE_H +#define MATCH_PIPELINE_H + +#include "Matcher.h" +#include "Finder.h" +#include "FeatureExtractor.h" +#include "FeatureConditioner.h" +#include "MatchFeatureFeeder.h" + +class MatchPipeline +{ +public: + /** + * Pipeline consisting of two Matchers, two FeatureConditioners, + * two FeatureExtractors, and a Finder. Features may be inserted + * at any point in the pipeline. + * + * The pipeline goes: + * Frequency-domain audio + * -> Features + * -> Conditioned features + * -> Matcher + * + * Only one set of FeatureExtractor::Parameters is provided; this + * contains a single reference frequency, but it's possible the + * two input streams may have different tuning frequencies. A + * separate frequency for the second input can be provided here as + * an optional parameter if needed. + */ + MatchPipeline(FeatureExtractor::Parameters feParams, + FeatureConditioner::Parameters fcParams, + DistanceMetric::Parameters dParams, + Matcher::Parameters matchParams, + double secondReferenceFrequency = 0.0); + + ~MatchPipeline(); + + /** + * Feed in data at the first pipeline stage. The input arrays + * represent frames of audio from the two different sources. Each + * is provided as a single array of alternating real and imaginary + * components. + * + * Input arrays must have at least 2 * (feParams.fftSize/2 + 1) + * elements. The arrays will be passed to FeatureExtractor and + * then on into the rest of the pipeline. + */ + void feedFrequencyDomainAudio(const float *arr1, const float *arr2); + + /** + * Feed in data at the second pipeline stage. The vectors + * represent feature frames from two different sources. They will + * be passed in to FeatureConditioner and then on to the rest of + * the pipeline. + */ + void feedFeatures(const feature_t &f1, const feature_t &f2); + + /** + * Feed in data at the third pipeline stage. The vectors represent + * conditioned feature frames from two different sources. They + * will be passed to MatchFeatureFeeder for feeding to the two + * matchers. + */ + void feedConditionedFeatures(const feature_t &f1, const feature_t &f2); + + /** + * If a frame was just fed in at the first or second pipeline + * stage, it can be retrieved from the second stage here. That is, + * if you provided frequency-domain audio, extractFeatures will + * give you back the FeatureExtractor's features. + */ + void extractFeatures(feature_t &f1, feature_t &f2); + + /** + * Retrieve the conditioned features from the third pipeline stage. + */ + void extractConditionedFeatures(feature_t &f1, feature_t &f2); + + /** + * Indicate that both inputs have come to an end. + */ + void finish(); + + /** + * Retrieve the final path. Only valid once all the features have + * been supplied and finish() has been called. + * + * See Finder::retrievePath for more details. + */ + int retrievePath(bool smooth, std::vector<int> &pathx, std::vector<int> &pathy); + + /** + * Retrieve the forward path resulting from the online search. + * + * See MatchFeatureFeeder::retrieveForwardPath for more details. + */ + void retrieveForwardPath(std::vector<int> &pathx, std::vector<int> &pathy); + + /** + * Get the path cost for the overall path to the end of both + * sources. + * + * See Finder::getOverallCost for more details. + */ + double getOverallCost(); + +private: + FeatureExtractor m_fe1; + FeatureExtractor m_fe2; + FeatureConditioner m_fc1; + FeatureConditioner m_fc2; + Matcher m_pm1; + Matcher m_pm2; + MatchFeatureFeeder m_feeder; + int m_lastFrameIn1; + int m_lastFrameIn2; + int m_frameNo; + feature_t m_f1; + feature_t m_f2; + feature_t m_c1; + feature_t m_c2; + bool aboveThreshold(const feature_t &f); + FeatureExtractor::Parameters paramsWithFreq(FeatureExtractor::Parameters, + double); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/MatchTypes.h Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,114 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + + This program 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef MATCH_TYPES_H +#define MATCH_TYPES_H + +#include <vector> +#include <cstdint> +#include <float.h> + +#ifdef USE_COMPACT_TYPES + +/// A single value in a feature vector +typedef float featurebin_t; + +/// The distance between two feature vectors +typedef uint8_t distance_t; + +/// What to cast a distance_t to when printing it (to avoid printing as char) +typedef int distance_print_t; + +const distance_t MaxDistance = 0xfe; +const distance_t InvalidDistance = 0xff; + +/// The integrated distance (path cost) from the origin to a given point +typedef uint32_t pathcost_t; + +const pathcost_t MaxPathCost = 0xfffffffe; +const pathcost_t InvalidPathCost = 0xffffffff; + +/// A direction advance instruction or state +enum advance_t : uint8_t { + AdvanceNone, + AdvanceBoth, + AdvanceThis, + AdvanceOther +}; + +#else + +#ifndef USE_PRECISE_TYPES +#error You must define either USE_COMPACT_TYPES or USE_PRECISE_TYPES +#endif + +/// A single value in a feature vector +typedef double featurebin_t; + +/// The distance between two feature vectors +typedef float distance_t; + +/// What to cast a distance_t to when printing it +typedef distance_t distance_print_t; + +const float MaxDistance = FLT_MAX; +const float InvalidDistance = -1.f; + +/// The integrated distance (path cost) from the origin to a given point +typedef double pathcost_t; + +const double MaxPathCost = DBL_MAX; +const double InvalidPathCost = -1.; + +/// A direction advance instruction or state +enum advance_t { + AdvanceNone, + AdvanceBoth, + AdvanceThis, + AdvanceOther +}; + +#endif + + +/// A feature vector +typedef std::vector<featurebin_t> feature_t; + +/// A sequence of feature vectors +typedef std::vector<feature_t> featureseq_t; + +/// A distance vector +typedef std::vector<distance_t> distancevec_t; + +/// A distance matrix +typedef std::vector<distancevec_t> distancemat_t; + +/// A vector of path costs +typedef std::vector<pathcost_t> pathcostvec_t; + +/// A matrix of path costs +typedef std::vector<pathcostvec_t> pathcostmat_t; + +/// A vector of advance directions +typedef std::vector<advance_t> advancevec_t; + +/// A matrix of advance directions +typedef std::vector<advancevec_t> advancemat_t; + +/// A normalised path cost, i.e. a pathcost_t divided by some scale factor +typedef double normpathcost_t; + + +#endif
--- a/src/MatchVampPlugin.cpp Fri Nov 14 10:24:13 2014 +0000 +++ b/src/MatchVampPlugin.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -17,7 +17,8 @@ #include "MatchVampPlugin.h" #include "Matcher.h" -#include "MatchFeeder.h" +#include "MatchFeatureFeeder.h" +#include "FeatureExtractor.h" #include "Path.h" #include <vamp/vamp.h> @@ -45,19 +46,27 @@ // sample rates static float sampleRateMin = 5000.f; -static float defaultStepTime = 0.020; +static float defaultStepTime = 0.020f; MatchVampPlugin::MatchVampPlugin(float inputSampleRate) : Plugin(inputSampleRate), - m_stepSize(inputSampleRate * defaultStepTime + 0.001), + m_stepSize(int(inputSampleRate * defaultStepTime + 0.001)), m_stepTime(defaultStepTime), m_blockSize(2048), m_serialise(false), m_begin(true), m_locked(false), - m_smooth(true), - m_params(inputSampleRate, defaultStepTime, m_blockSize), - m_defaultParams(inputSampleRate, defaultStepTime, m_blockSize) + m_smooth(false), + m_frameNo(0), + m_params(defaultStepTime), + m_defaultParams(defaultStepTime), + m_feParams(inputSampleRate, m_blockSize), + m_defaultFeParams(inputSampleRate, m_blockSize), + m_secondReferenceFrequency(m_defaultFeParams.referenceFrequency), + m_fcParams(), + m_defaultFcParams(), + m_dParams(), + m_defaultDParams() { if (inputSampleRate < sampleRateMin) { std::cerr << "MatchVampPlugin::MatchVampPlugin: input sample rate " @@ -75,9 +84,7 @@ #endif } - pm1 = 0; - pm2 = 0; - feeder = 0; + m_pipeline = 0; // std::cerr << "MatchVampPlugin::MatchVampPlugin(" << this << "): extant = " << ++extant << std::endl; } @@ -85,9 +92,7 @@ { // std::cerr << "MatchVampPlugin::~MatchVampPlugin(" << this << "): extant = " << --extant << std::endl; - delete feeder; - delete pm1; - delete pm2; + delete m_pipeline; if (m_locked) { #ifdef _WIN32 @@ -126,7 +131,7 @@ int MatchVampPlugin::getPluginVersion() const { - return 2; + return 3; } string @@ -142,8 +147,193 @@ ParameterDescriptor desc; + desc.identifier = "freq1"; + desc.name = "Tuning frequency of first input"; + desc.description = "Tuning frequency (concert A) for the reference audio."; + desc.minValue = 220.0; + desc.maxValue = 880.0; + desc.defaultValue = float(m_defaultFeParams.referenceFrequency); + desc.isQuantized = false; + desc.unit = "Hz"; + list.push_back(desc); + + desc.identifier = "freq2"; + desc.name = "Tuning frequency of second input"; + desc.description = "Tuning frequency (concert A) for the other audio."; + desc.minValue = 220.0; + desc.maxValue = 880.0; + desc.defaultValue = float(m_defaultFeParams.referenceFrequency); + desc.isQuantized = false; + desc.unit = "Hz"; + list.push_back(desc); + + desc.identifier = "minfreq"; + desc.name = "Minimum frequency"; + desc.description = "Minimum frequency to include in features."; + desc.minValue = 0.0; + desc.maxValue = float(m_inputSampleRate / 4.f); + desc.defaultValue = float(m_defaultFeParams.minFrequency); + desc.isQuantized = false; + desc.unit = "Hz"; + list.push_back(desc); + + desc.identifier = "maxfreq"; + desc.name = "Maximum frequency"; + desc.description = "Maximum frequency to include in features."; + desc.minValue = 1000.0; + desc.maxValue = float(m_inputSampleRate / 2.f); + desc.defaultValue = float(m_defaultFeParams.maxFrequency); + desc.isQuantized = false; + desc.unit = "Hz"; + list.push_back(desc); + + desc.unit = ""; + + desc.identifier = "usechroma"; + desc.name = "Feature type"; + desc.description = "Whether to use warped spectrogram or chroma frequency map"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = m_defaultFeParams.useChromaFrequencyMap ? 1 : 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.clear(); + desc.valueNames.push_back("Spectral"); + desc.valueNames.push_back("Chroma"); + list.push_back(desc); + + desc.valueNames.clear(); + + desc.identifier = "usespecdiff"; + desc.name = "Use feature difference"; + desc.description = "Whether to use half-wave rectified feature-to-feature difference instead of straight spectral or chroma feature"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = float(m_defaultFcParams.order); + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "framenorm"; + desc.name = "Frame normalisation"; + desc.description = "Type of normalisation to use for features"; + desc.minValue = 0; + desc.maxValue = 2; + desc.defaultValue = float(m_defaultFcParams.norm); + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.clear(); + desc.valueNames.push_back("None"); + desc.valueNames.push_back("Sum to 1"); + desc.valueNames.push_back("Long-term average"); + list.push_back(desc); + desc.valueNames.clear(); + desc.defaultValue = float(m_defaultFcParams.silenceThreshold); + + desc.identifier = "metric"; + desc.name = "Distance metric"; + desc.description = "Metric for distance calculations."; + desc.minValue = 0; + desc.maxValue = 2; + desc.defaultValue = float(m_defaultDParams.metric); + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.clear(); + desc.valueNames.push_back("Manhattan"); + desc.valueNames.push_back("Euclidean"); + desc.valueNames.push_back("Cosine"); + list.push_back(desc); + desc.valueNames.clear(); + + desc.identifier = "distnorm"; + desc.name = "Distance normalisation"; + desc.description = "Type of normalisation to use for distance metric"; + desc.minValue = 0; + desc.maxValue = 2; + desc.defaultValue = float(m_defaultDParams.norm); + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.clear(); + desc.valueNames.push_back("None"); + desc.valueNames.push_back("Sum of frames"); + desc.valueNames.push_back("Log sum of frames"); + list.push_back(desc); + desc.valueNames.clear(); + +#ifdef USE_COMPACT_TYPES + desc.identifier = "scale"; + desc.name = "Distance scale"; + desc.description = "Scale factor to use when mapping distance metric into byte range for storage"; + desc.minValue = 1; + desc.maxValue = 1000; + desc.defaultValue = float(m_defaultDParams.scale); + desc.isQuantized = false; + list.push_back(desc); +#endif + + desc.identifier = "silencethreshold"; + desc.name = "Silence threshold"; + desc.description = "Total frame energy threshold below which a feature will be regarded as silent"; + desc.minValue = 0; + desc.maxValue = 0.1f; + desc.defaultValue = float(m_defaultFcParams.silenceThreshold); + desc.isQuantized = false; + list.push_back(desc); + + desc.identifier = "noise"; + desc.name = "Add noise"; + desc.description = "Whether to mix in a small constant white noise term when calculating feature distance. This can improve alignment against sources containing cleanly synthesised audio."; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = float(m_defaultDParams.noise); + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "gradientlimit"; + desc.name = "Gradient limit"; + desc.description = "Limit of number of frames that will be accepted from one source without a frame from the other source being accepted"; + desc.minValue = 1; + desc.maxValue = 10; + desc.defaultValue = float(m_defaultParams.maxRunCount); + desc.isQuantized = true; + desc.quantizeStep = 1; + list.push_back(desc); + + desc.identifier = "zonewidth"; + desc.name = "Search zone width"; + desc.description = "Width of the search zone (error margin) either side of the ongoing match position, in seconds"; + desc.minValue = 1; + desc.maxValue = 60; + desc.defaultValue = float(m_defaultParams.blockTime); + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.unit = "s"; + list.push_back(desc); + + desc.identifier = "diagonalweight"; + desc.name = "Diagonal weight"; + desc.description = "Weight applied to cost of diagonal step relative to horizontal or vertical step. The default of 2.0 is good for gross tracking of quite different performances; closer to 1.0 produces a smoother path for performances more similar in tempo"; + desc.minValue = 1.0; + desc.maxValue = 2.0; + desc.defaultValue = float(m_defaultParams.diagonalWeight); + desc.isQuantized = false; + desc.unit = ""; + list.push_back(desc); + + desc.identifier = "smooth"; + desc.name = "Use path smoothing"; + desc.description = "Smooth the path by replacing steps with diagonals. (This was enabled by default in earlier versions of the MATCH plugin, but the default now is to produce an un-smoothed path.)"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.unit = ""; + list.push_back(desc); + desc.identifier = "serialise"; - desc.name = "Serialise Plugin Invocations"; + desc.name = "Serialise plugin invocations"; desc.description = "Reduce potential memory load at the expense of multiprocessor performance by serialising multi-threaded plugin runs"; desc.minValue = 0; desc.maxValue = 1; @@ -151,89 +341,7 @@ desc.isQuantized = true; desc.quantizeStep = 1; list.push_back(desc); - - desc.identifier = "framenorm"; - desc.name = "Frame Normalisation"; - desc.description = "Type of normalisation to use for frequency-domain audio features"; - desc.minValue = 0; - desc.maxValue = 2; - desc.defaultValue = (int)m_defaultParams.frameNorm; - desc.isQuantized = true; - desc.quantizeStep = 1; - desc.valueNames.clear(); - desc.valueNames.push_back("None"); - desc.valueNames.push_back("Sum To 1"); - desc.valueNames.push_back("Long-Term Average"); - list.push_back(desc); - desc.valueNames.clear(); - - desc.identifier = "distnorm"; - desc.name = "Distance Normalisation"; - desc.description = "Type of normalisation to use for distance metric"; - desc.minValue = 0; - desc.maxValue = 2; - desc.defaultValue = (int)m_defaultParams.distanceNorm; - desc.isQuantized = true; - desc.quantizeStep = 1; - desc.valueNames.clear(); - desc.valueNames.push_back("None"); - desc.valueNames.push_back("Sum of Frames"); - desc.valueNames.push_back("Log Sum of Frames"); - list.push_back(desc); - desc.valueNames.clear(); - - desc.identifier = "usespecdiff"; - desc.name = "Use Spectral Difference"; - desc.description = "Whether to use half-wave rectified spectral difference instead of straight spectrum"; - desc.minValue = 0; - desc.maxValue = 1; - desc.defaultValue = m_defaultParams.useSpectralDifference ? 1 : 0; - desc.isQuantized = true; - desc.quantizeStep = 1; - list.push_back(desc); - - desc.identifier = "usechroma"; - desc.name = "Use Chroma Frequency Map"; - desc.description = "Whether to use a chroma frequency map instead of the default warped spectrogram"; - desc.minValue = 0; - desc.maxValue = 1; - desc.defaultValue = m_defaultParams.useChromaFrequencyMap ? 1 : 0; - desc.isQuantized = true; - desc.quantizeStep = 1; - list.push_back(desc); - - desc.identifier = "gradientlimit"; - desc.name = "Gradient Limit"; - desc.description = "Limit of number of frames that will be accepted from one source without a frame from the other source being accepted"; - desc.minValue = 1; - desc.maxValue = 10; - desc.defaultValue = m_defaultParams.maxRunCount; - desc.isQuantized = true; - desc.quantizeStep = 1; - list.push_back(desc); - - desc.identifier = "zonewidth"; - desc.name = "Search Zone Width"; - desc.description = "Width of the search zone (error margin) either side of the ongoing match position, in seconds"; - desc.minValue = 1; - desc.maxValue = 60; - desc.defaultValue = m_defaultParams.blockTime; - desc.isQuantized = true; - desc.quantizeStep = 1; - desc.unit = "s"; - list.push_back(desc); - - desc.identifier = "smooth"; - desc.name = "Smooth Path"; - desc.description = "Smooth the path by replacing steps with diagonals"; - desc.minValue = 0; - desc.maxValue = 1; - desc.defaultValue = 1; - desc.isQuantized = true; - desc.quantizeStep = 1; - desc.unit = ""; - list.push_back(desc); - + return list; } @@ -243,19 +351,37 @@ if (name == "serialise") { return m_serialise ? 1.0 : 0.0; } else if (name == "framenorm") { - return (int)m_params.frameNorm; + return float(m_fcParams.norm); } else if (name == "distnorm") { - return (int)m_params.distanceNorm; + return float(m_dParams.norm); } else if (name == "usespecdiff") { - return m_params.useSpectralDifference ? 1.0 : 0.0; + return float(m_fcParams.order); } else if (name == "usechroma") { - return m_params.useChromaFrequencyMap ? 1.0 : 0.0; + return m_feParams.useChromaFrequencyMap ? 1.0 : 0.0; } else if (name == "gradientlimit") { - return m_params.maxRunCount; + return float(m_params.maxRunCount); + } else if (name == "diagonalweight") { + return float(m_params.diagonalWeight); } else if (name == "zonewidth") { - return m_params.blockTime; + return float(m_params.blockTime); } else if (name == "smooth") { return m_smooth ? 1.0 : 0.0; + } else if (name == "silencethreshold") { + return float(m_fcParams.silenceThreshold); + } else if (name == "metric") { + return float(m_dParams.metric); + } else if (name == "noise") { + return m_dParams.noise; + } else if (name == "scale") { + return float(m_dParams.scale); + } else if (name == "freq1") { + return float(m_feParams.referenceFrequency); + } else if (name == "freq2") { + return float(m_secondReferenceFrequency); + } else if (name == "minfreq") { + return float(m_feParams.minFrequency); + } else if (name == "maxfreq") { + return float(m_feParams.maxFrequency); } return 0.0; @@ -267,26 +393,44 @@ if (name == "serialise") { m_serialise = (value > 0.5); } else if (name == "framenorm") { - m_params.frameNorm = (Matcher::FrameNormalisation)(int(value + 0.1)); + m_fcParams.norm = FeatureConditioner::Normalisation(int(value + 0.1)); } else if (name == "distnorm") { - m_params.distanceNorm = (DistanceMetric::DistanceNormalisation)(int(value + 0.1)); + m_dParams.norm = DistanceMetric::DistanceNormalisation(int(value + 0.1)); } else if (name == "usespecdiff") { - m_params.useSpectralDifference = (value > 0.5); + m_fcParams.order = FeatureConditioner::OutputOrder(int(value + 0.1)); } else if (name == "usechroma") { - m_params.useChromaFrequencyMap = (value > 0.5); + m_feParams.useChromaFrequencyMap = (value > 0.5); } else if (name == "gradientlimit") { m_params.maxRunCount = int(value + 0.1); + } else if (name == "diagonalweight") { + m_params.diagonalWeight = value; } else if (name == "zonewidth") { m_params.blockTime = value; } else if (name == "smooth") { m_smooth = (value > 0.5); + } else if (name == "silencethreshold") { + m_fcParams.silenceThreshold = value; + } else if (name == "metric") { + m_dParams.metric = DistanceMetric::Metric(int(value + 0.1)); + } else if (name == "noise") { + m_dParams.noise = DistanceMetric::NoiseAddition(int(value + 0.1)); + } else if (name == "scale") { + m_dParams.scale = value; + } else if (name == "freq1") { + m_feParams.referenceFrequency = value; + } else if (name == "freq2") { + m_secondReferenceFrequency = value; + } else if (name == "minfreq") { + m_feParams.minFrequency = value; + } else if (name == "maxfreq") { + m_feParams.maxFrequency = value; } } size_t MatchVampPlugin::getPreferredStepSize() const { - return m_inputSampleRate * defaultStepTime; + return int(m_inputSampleRate * defaultStepTime + 0.001); } size_t @@ -299,11 +443,10 @@ MatchVampPlugin::createMatchers() { m_params.hopTime = m_stepTime; - m_params.fftSize = m_blockSize; - pm1 = new Matcher(m_params, 0); - pm2 = new Matcher(m_params, pm1); - pm1->setOtherMatcher(pm2); - feeder = new MatchFeeder(pm1, pm2); + m_feParams.fftSize = m_blockSize; + + m_pipeline = new MatchPipeline(m_feParams, m_fcParams, m_dParams, m_params, + m_secondReferenceFrequency); } bool @@ -320,9 +463,9 @@ if (stepSize > blockSize/2 || blockSize != getPreferredBlockSize()) return false; - m_stepSize = stepSize; + m_stepSize = int(stepSize); m_stepTime = float(stepSize) / m_inputSampleRate; - m_blockSize = blockSize; + m_blockSize = int(blockSize); createMatchers(); m_begin = true; @@ -334,13 +477,9 @@ void MatchVampPlugin::reset() { - delete feeder; - delete pm1; - delete pm2; - feeder = 0; - pm1 = 0; - pm2 = 0; - + delete m_pipeline; + m_pipeline = 0; + m_frameNo = 0; createMatchers(); m_begin = true; m_locked = false; @@ -351,7 +490,7 @@ { OutputList list; - float outRate = 1.0 / m_stepTime; + float outRate = 1.0f / m_stepTime; OutputDescriptor desc; desc.identifier = "path"; @@ -365,7 +504,7 @@ desc.quantizeStep = 1; desc.sampleType = OutputDescriptor::VariableSampleRate; desc.sampleRate = outRate; - m_pathOutNo = list.size(); + m_pathOutNo = int(list.size()); list.push_back(desc); desc.identifier = "a_b"; @@ -378,7 +517,7 @@ desc.isQuantized = false; desc.sampleType = OutputDescriptor::VariableSampleRate; desc.sampleRate = outRate; - m_abOutNo = list.size(); + m_abOutNo = int(list.size()); list.push_back(desc); desc.identifier = "b_a"; @@ -391,7 +530,7 @@ desc.isQuantized = false; desc.sampleType = OutputDescriptor::VariableSampleRate; desc.sampleRate = outRate; - m_baOutNo = list.size(); + m_baOutNo = int(list.size()); list.push_back(desc); desc.identifier = "a_b_divergence"; @@ -404,7 +543,7 @@ desc.isQuantized = false; desc.sampleType = OutputDescriptor::VariableSampleRate; desc.sampleRate = outRate; - m_abDivOutNo = list.size(); + m_abDivOutNo = int(list.size()); list.push_back(desc); desc.identifier = "a_b_temporatio"; @@ -417,35 +556,76 @@ desc.isQuantized = false; desc.sampleType = OutputDescriptor::VariableSampleRate; desc.sampleRate = outRate; - m_abRatioOutNo = list.size(); + m_abRatioOutNo = int(list.size()); list.push_back(desc); + int featureSize = FeatureExtractor(m_feParams).getFeatureSize(); + desc.identifier = "a_features"; - desc.name = "A Features"; + desc.name = "Raw A Features"; desc.description = "Spectral features extracted from performance A"; desc.unit = ""; desc.hasFixedBinCount = true; - desc.binCount = Matcher::getFeatureSizeFor(m_params); + desc.binCount = featureSize; desc.hasKnownExtents = false; desc.isQuantized = false; desc.sampleType = OutputDescriptor::FixedSampleRate; desc.sampleRate = outRate; - m_aFeaturesOutNo = list.size(); + m_aFeaturesOutNo = int(list.size()); list.push_back(desc); desc.identifier = "b_features"; - desc.name = "B Features"; + desc.name = "Raw B Features"; desc.description = "Spectral features extracted from performance B"; desc.unit = ""; desc.hasFixedBinCount = true; - desc.binCount = Matcher::getFeatureSizeFor(m_params); + desc.binCount = featureSize; desc.hasKnownExtents = false; desc.isQuantized = false; desc.sampleType = OutputDescriptor::FixedSampleRate; desc.sampleRate = outRate; - m_bFeaturesOutNo = list.size(); + m_bFeaturesOutNo = int(list.size()); list.push_back(desc); + desc.identifier = "a_cfeatures"; + desc.name = "Conditioned A Features"; + desc.description = "Spectral features extracted from performance A, after normalisation and conditioning"; + desc.unit = ""; + desc.hasFixedBinCount = true; + desc.binCount = featureSize; + desc.hasKnownExtents = false; + desc.isQuantized = false; + desc.sampleType = OutputDescriptor::FixedSampleRate; + desc.sampleRate = outRate; + m_caFeaturesOutNo = int(list.size()); + list.push_back(desc); + + desc.identifier = "b_cfeatures"; + desc.name = "Conditioned B Features"; + desc.description = "Spectral features extracted from performance B, after norrmalisation and conditioning"; + desc.unit = ""; + desc.hasFixedBinCount = true; + desc.binCount = featureSize; + desc.hasKnownExtents = false; + desc.isQuantized = false; + desc.sampleType = OutputDescriptor::FixedSampleRate; + desc.sampleRate = outRate; + m_cbFeaturesOutNo = int(list.size()); + list.push_back(desc); + + desc.identifier = "overall_cost"; + desc.name = "Overall Cost"; + desc.description = "Normalised overall path cost for the cheapest path"; + desc.unit = ""; + desc.hasFixedBinCount = true; + desc.binCount = 1; + desc.hasKnownExtents = false; + desc.isQuantized = false; + desc.sampleType = OutputDescriptor::FixedSampleRate; + desc.sampleRate = 1; + m_overallCostOutNo = int(list.size()); + list.push_back(desc); + return list; } @@ -468,45 +648,60 @@ // std::cerr << timestamp.toString(); - MatchFeeder::Features ff = feeder->feedAndGetFeatures(inputBuffers); + m_pipeline->feedFrequencyDomainAudio(inputBuffers[0], inputBuffers[1]); FeatureSet returnFeatures; + feature_t f1, f2; + m_pipeline->extractFeatures(f1, f2); + + feature_t cf1, cf2; + m_pipeline->extractConditionedFeatures(cf1, cf2); + Feature f; f.hasTimestamp = false; - for (int i = 0; i < (int)ff.f1.size(); ++i) { - f.values.clear(); - for (int j = 0; j < (int)ff.f1[i].size(); ++j) { - f.values.push_back(ff.f1[i][j]); - } - returnFeatures[m_aFeaturesOutNo].push_back(f); - } + f.values.clear(); + for (auto v: f1) f.values.push_back(float(v)); + returnFeatures[m_aFeaturesOutNo].push_back(f); - for (int i = 0; i < (int)ff.f2.size(); ++i) { - f.values.clear(); - for (int j = 0; j < (int)ff.f2[i].size(); ++j) { - f.values.push_back(ff.f2[i][j]); - } - returnFeatures[m_bFeaturesOutNo].push_back(f); - } + f.values.clear(); + for (auto v: f2) f.values.push_back(float(v)); + returnFeatures[m_bFeaturesOutNo].push_back(f); + + f.values.clear(); + for (auto v: cf1) f.values.push_back(float(v)); + returnFeatures[m_caFeaturesOutNo].push_back(f); + + f.values.clear(); + for (auto v: cf2) f.values.push_back(float(v)); + returnFeatures[m_cbFeaturesOutNo].push_back(f); // std::cerr << "."; // std::cerr << std::endl; + ++m_frameNo; + return returnFeatures; } MatchVampPlugin::FeatureSet MatchVampPlugin::getRemainingFeatures() { - Finder *finder = feeder->getFinder(); + m_pipeline->finish(); + + FeatureSet returnFeatures; + std::vector<int> pathx; std::vector<int> pathy; - int len = finder->retrievePath(m_smooth, pathx, pathy); + int len = m_pipeline->retrievePath(m_smooth, pathx, pathy); + + double cost = m_pipeline->getOverallCost(); + Feature costFeature; + costFeature.hasTimestamp = false; + costFeature.values.push_back(float(cost)); + returnFeatures[m_overallCostOutNo].push_back(costFeature); - FeatureSet returnFeatures; - int prevx = 0; int prevy = 0; @@ -516,15 +711,15 @@ int y = pathy[i]; Vamp::RealTime xt = Vamp::RealTime::frame2RealTime - (x * m_stepSize, lrintf(m_inputSampleRate)); + (x * m_stepSize, int(m_inputSampleRate + 0.5)); Vamp::RealTime yt = Vamp::RealTime::frame2RealTime - (y * m_stepSize, lrintf(m_inputSampleRate)); + (y * m_stepSize, int(m_inputSampleRate + 0.5)); Feature feature; feature.hasTimestamp = true; feature.timestamp = m_startTime + xt; feature.values.clear(); - feature.values.push_back(yt.sec + double(yt.nsec)/1.0e9); + feature.values.push_back(float(yt.sec + double(yt.nsec)/1.0e9)); returnFeatures[m_pathOutNo].push_back(feature); if (x != prevx) { @@ -532,12 +727,12 @@ feature.hasTimestamp = true; feature.timestamp = m_startTime + xt; feature.values.clear(); - feature.values.push_back(yt.sec + yt.msec()/1000.0); + feature.values.push_back(float(yt.sec + yt.msec()/1000.0)); returnFeatures[m_abOutNo].push_back(feature); Vamp::RealTime diff = yt - xt; feature.values.clear(); - feature.values.push_back(diff.sec + diff.msec()/1000.0); + feature.values.push_back(float(diff.sec + diff.msec()/1000.0)); returnFeatures[m_abDivOutNo].push_back(feature); if (i > 0) { @@ -560,7 +755,7 @@ feature.hasTimestamp = true; feature.timestamp = m_startTime + yt; feature.values.clear(); - feature.values.push_back(xt.sec + xt.msec()/1000.0); + feature.values.push_back(float(xt.sec + xt.msec()/1000.0)); returnFeatures[m_baOutNo].push_back(feature); } @@ -568,12 +763,8 @@ prevy = y; } - delete feeder; - delete pm1; - delete pm2; - feeder = 0; - pm1 = 0; - pm2 = 0; + delete m_pipeline; + m_pipeline = 0; if (m_locked) { #ifdef _WIN32
--- a/src/MatchVampPlugin.h Fri Nov 14 10:24:13 2014 +0000 +++ b/src/MatchVampPlugin.h Fri Feb 27 09:29:37 2015 +0000 @@ -25,9 +25,7 @@ #include <pthread.h> #endif -#include "Matcher.h" - -class MatchFeeder; +#include "MatchPipeline.h" class MatchVampPlugin : public Vamp::Plugin { @@ -66,10 +64,9 @@ protected: void createMatchers(); + bool aboveThreshold(const float *); - Matcher *pm1; - Matcher *pm2; - MatchFeeder *feeder; + MatchPipeline *m_pipeline; Vamp::RealTime m_startTime; int m_stepSize; @@ -80,9 +77,21 @@ bool m_locked; bool m_smooth; + int m_frameNo; + Matcher::Parameters m_params; Matcher::Parameters m_defaultParams; + FeatureExtractor::Parameters m_feParams; + FeatureExtractor::Parameters m_defaultFeParams; + double m_secondReferenceFrequency; + + FeatureConditioner::Parameters m_fcParams; + FeatureConditioner::Parameters m_defaultFcParams; + + DistanceMetric::Parameters m_dParams; + DistanceMetric::Parameters m_defaultDParams; + mutable int m_pathOutNo; mutable int m_abOutNo; mutable int m_baOutNo; @@ -90,6 +99,9 @@ mutable int m_abRatioOutNo; mutable int m_aFeaturesOutNo; mutable int m_bFeaturesOutNo; + mutable int m_caFeaturesOutNo; + mutable int m_cbFeaturesOutNo; + mutable int m_overallCostOutNo; #ifdef _WIN32 static HANDLE m_serialisingMutex;
--- a/src/Matcher.cpp Fri Nov 14 10:24:13 2014 +0000 +++ b/src/Matcher.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -21,71 +21,34 @@ #include <cstdlib> #include <cassert> -bool Matcher::silent = true; +using namespace std; //#define DEBUG_MATCHER 1 -Matcher::Matcher(Parameters parameters, Matcher *p) : - params(parameters), - metric(parameters.distanceNorm) +Matcher::Matcher(Parameters parameters, DistanceMetric::Parameters dparams, + Matcher *p) : + m_params(parameters), + m_metric(dparams) { #ifdef DEBUG_MATCHER - cerr << "Matcher::Matcher(" << params.sampleRate << ", " << p << ")" << endl; + cerr << "*** Matcher: hopTime = " << parameters.hopTime + << ", blockTime = " << parameters.blockTime + << ", maxRunCount = " << parameters.maxRunCount + << ", diagonalWeight = " << parameters.diagonalWeight << endl; +#endif + + m_otherMatcher = p; // the first matcher will need this to be set later + m_firstPM = (!p); + m_frameCount = 0; + m_runCount = 0; + m_blockSize = 0; + + m_blockSize = int(m_params.blockTime / m_params.hopTime + 0.5); +#ifdef DEBUG_MATCHER + cerr << "Matcher: m_blockSize = " << m_blockSize << endl; #endif - otherMatcher = p; // the first matcher will need this to be set later - firstPM = (!p); - ltAverage = 0; - frameCount = 0; - runCount = 0; - freqMapSize = 0; - externalFeatureSize = 0; - featureSize = 0; - blockSize = 0; - - blockSize = lrint(params.blockTime / params.hopTime); -#ifdef DEBUG_MATCHER - cerr << "Matcher: blockSize = " << blockSize << endl; -#endif - - distance = 0; - bestPathCost = 0; - distYSizes = 0; - distXSize = 0; - - initialised = false; -} - -Matcher::Matcher(Parameters parameters, Matcher *p, int featureSize) : - params(parameters), - externalFeatureSize(featureSize), - metric(parameters.distanceNorm) -{ -#ifdef DEBUG_MATCHER - cerr << "Matcher::Matcher(" << params.sampleRate << ", " << p << ", " << featureSize << ")" << endl; -#endif - - otherMatcher = p; // the first matcher will need this to be set later - firstPM = (!p); - ltAverage = 0; - frameCount = 0; - runCount = 0; - freqMapSize = 0; - featureSize = 0; - blockSize = 0; - - blockSize = lrint(params.blockTime / params.hopTime); -#ifdef DEBUG_MATCHER - cerr << "Matcher: blockSize = " << blockSize << endl; -#endif - - distance = 0; - bestPathCost = 0; - distYSizes = 0; - distXSize = 0; - - initialised = false; - + m_initialised = false; } Matcher::~Matcher() @@ -93,418 +56,410 @@ #ifdef DEBUG_MATCHER cerr << "Matcher(" << this << ")::~Matcher()" << endl; #endif - - if (initialised) { - - for (int i = 0; i < distXSize; ++i) { - if (distance[i]) { - free(distance[i]); - free(bestPathCost[i]); - } - } - free(distance); - free(bestPathCost); - - free(first); - free(last); - - free(distYSizes); - } } void Matcher::init() { - if (initialised) return; + if (m_initialised) return; - initialised = true; + m_features = featureseq_t(m_blockSize); - if (externalFeatureSize == 0) { - freqMapSize = getFeatureSizeFor(params); - featureSize = freqMapSize; - makeFreqMap(); - } else { - featureSize = externalFeatureSize; + m_distXSize = m_blockSize * 2; + + size(); + + m_frameCount = 0; + m_runCount = 0; + + m_initialised = true; +} + +bool +Matcher::isRowAvailable(int i) +{ + if (i < 0 || i >= int(m_first.size())) return false; + + for (int j = m_first[i]; j < int(m_first[i] + m_bestPathCost[i].size()); ++j) { + if (isAvailable(i, j)) { + return true; + } } - initVector<double>(prevFrame, featureSize); - initVector<double>(newFrame, featureSize); - initMatrix<double>(frames, blockSize, featureSize); - initVector<double>(totalEnergies, blockSize); + return false; +} - int distSize = (params.maxRunCount + 1) * blockSize; +bool +Matcher::isColAvailable(int i) +{ + return m_otherMatcher->isRowAvailable(i); +} - distXSize = blockSize * 2; +bool +Matcher::isInRange(int i, int j) +{ + if (m_firstPM) { + return ((i >= 0) && + (i < int(m_first.size())) && + (j >= m_first[i]) && + (j < int(m_first[i] + m_bestPathCost[i].size()))); + } else { + return m_otherMatcher->isInRange(j, i); + } +} - distance = (unsigned char **)malloc(distXSize * sizeof(unsigned char *)); - bestPathCost = (int **)malloc(distXSize * sizeof(int *)); - distYSizes = (int *)malloc(distXSize * sizeof(int)); +bool +Matcher::isAvailable(int i, int j) +{ + if (m_firstPM) { + if (isInRange(i, j)) { + return (m_bestPathCost[i][j - m_first[i]] >= 0); + } else { + return false; + } + } else { + return m_otherMatcher->isAvailable(j, i); + } +} - for (int i = 0; i < blockSize; ++i) { - distance[i] = (unsigned char *)malloc(distSize * sizeof(unsigned char)); - bestPathCost[i] = (int *)malloc(distSize * sizeof(int)); - distYSizes[i] = distSize; +pair<int, int> +Matcher::getColRange(int i) +{ + if (i < 0 || i >= int(m_first.size())) { + cerr << "ERROR: Matcher::getColRange(" << i << "): Index out of range" + << endl; + throw "Index out of range"; + } else { + return pair<int, int>(m_first[i], m_last[i]); } - for (int i = blockSize; i < distXSize; ++i) { - distance[i] = 0; +} + +pair<int, int> +Matcher::getRowRange(int i) +{ + return m_otherMatcher->getColRange(i); +} + +distance_t +Matcher::getDistance(int i, int j) +{ + if (m_firstPM) { + if (!isInRange(i, j)) { + cerr << "ERROR: Matcher::getDistance(" << i << ", " << j << "): " + << "Location is not in range" << endl; + throw "Distance not available"; + } + distance_t dist = m_distance[i][j - m_first[i]]; + if (dist == InvalidDistance) { + cerr << "ERROR: Matcher::getDistance(" << i << ", " << j << "): " + << "Location is in range, but distance (" + << distance_print_t(dist) + << ") is invalid or has not been set" << endl; + throw "Distance not available"; + } + return dist; + } else { + return m_otherMatcher->getDistance(j, i); } - - first = (int *)malloc(distXSize * sizeof(int)); - last = (int *)malloc(distXSize * sizeof(int)); +} + +void +Matcher::setDistance(int i, int j, distance_t distance) +{ + if (m_firstPM) { + if (!isInRange(i, j)) { + cerr << "ERROR: Matcher::setDistance(" << i << ", " << j << ", " + << distance_print_t(distance) + << "): Location is out of range" << endl; + throw "Indices out of range"; + } + m_distance[i][j - m_first[i]] = distance; + } else { + m_otherMatcher->setDistance(j, i, distance); + } +} - frameCount = 0; - runCount = 0; - ltAverage = 0; +normpathcost_t +Matcher::getNormalisedPathCost(int i, int j) +{ + // normalised for path length. 1+ prevents division by zero here + return normpathcost_t(getPathCost(i, j)) / normpathcost_t(1 + i + j); +} -} // init - +pathcost_t +Matcher::getPathCost(int i, int j) +{ + if (m_firstPM) { + if (!isAvailable(i, j)) { + if (!isInRange(i, j)) { + cerr << "ERROR: Matcher::getPathCost(" << i << ", " << j << "): " + << "Location is not in range" << endl; + } else { + cerr << "ERROR: Matcher::getPathCost(" << i << ", " << j << "): " + << "Location is in range, but pathCost (" + << m_bestPathCost[i][j - m_first[i]] + << ") is invalid or has not been set" << endl; + } + throw "Path cost not available"; + } + return m_bestPathCost[i][j - m_first[i]]; + } else { + return m_otherMatcher->getPathCost(j, i); + } +} + void -Matcher::makeFreqMap() +Matcher::setPathCost(int i, int j, advance_t dir, pathcost_t pathCost) { - initVector<int>(freqMap, params.fftSize/2 + 1); - - if (params.useChromaFrequencyMap) { -#ifdef DEBUG_MATCHER - cerr << "makeFreqMap: calling makeChromaFrequencyMap" << endl; -#endif - makeChromaFrequencyMap(); + if (m_firstPM) { + if (!isInRange(i, j)) { + cerr << "ERROR: Matcher::setPathCost(" << i << ", " << j << ", " + << dir << ", " << pathCost + << "): Location is out of range" << endl; + throw "Indices out of range"; + } + m_advance[i][j - m_first[i]] = dir; + m_bestPathCost[i][j - m_first[i]] = pathCost; } else { -#ifdef DEBUG_MATCHER - cerr << "makeFreqMap: calling makeStandardFrequencyMap" << endl; -#endif - makeStandardFrequencyMap(); - } -} // makeFreqMap() - -int -Matcher::getFeatureSizeFor(Parameters params) -{ - if (params.useChromaFrequencyMap) { - return 13; - } else { - return 84; + if (dir == AdvanceThis) { + dir = AdvanceOther; + } else if (dir == AdvanceOther) { + dir = AdvanceThis; + } + m_otherMatcher->setPathCost(j, i, dir, pathCost); } } void -Matcher::makeStandardFrequencyMap() +Matcher::size() { - double binWidth = params.sampleRate / params.fftSize; - int crossoverBin = (int)(2 / (pow(2, 1/12.0) - 1)); - int crossoverMidi = lrint(log(crossoverBin*binWidth/440.0)/ - log(2.0) * 12 + 69); - // freq = 440 * Math.pow(2, (midi-69)/12.0) / binWidth; - int i = 0; - while (i <= crossoverBin) { - freqMap[i] = i; - ++i; - } - while (i <= params.fftSize/2) { - double midi = log(i*binWidth/440.0) / log(2.0) * 12 + 69; - if (midi > 127) midi = 127; - int target = crossoverBin + lrint(midi) - crossoverMidi; - if (target >= freqMapSize) target = freqMapSize - 1; - freqMap[i++] = target; - } - - if (!silent) { - cerr << "Standard map size: " << freqMapSize - << "; Crossover at: " << crossoverBin << endl; - for (i = 0; i < params.fftSize / 2; i++) - cerr << "freqMap[" << i << "] = " << freqMap[i] << endl; - } -} // makeStandardFrequencyMap() - -void -Matcher::makeChromaFrequencyMap() -{ - double binWidth = params.sampleRate / params.fftSize; - int crossoverBin = (int)(1 / (pow(2, 1/12.0) - 1)); - // freq = 440 * Math.pow(2, (midi-69)/12.0) / binWidth; - int i = 0; - while (i <= crossoverBin) - freqMap[i++] = 0; - while (i <= params.fftSize/2) { - double midi = log(i*binWidth/440.0) / log(2.0) * 12 + 69; - freqMap[i++] = (lrint(midi)) % 12 + 1; - } - if (!silent) { - cerr << "Chroma map size: " << freqMapSize - << "; Crossover at: " << crossoverBin << endl; - for (i = 0; i < params.fftSize / 2; i++) - cerr << "freqMap[" << i << "] = " << freqMap[i] << endl; - } -} // makeChromaFrequencyMap() - -vector<double> -Matcher::consumeFrame(double *reBuffer, double *imBuffer) -{ - if (!initialised) init(); - - vector<double> processedFrame = - processFrameFromFreqData(reBuffer, imBuffer); - - calcAdvance(); - - return processedFrame; + int distSize = (m_params.maxRunCount + 1) * m_blockSize; + m_bestPathCost.resize(m_distXSize, pathcostvec_t(distSize, InvalidPathCost)); + m_distance.resize(m_distXSize, distancevec_t(distSize, InvalidDistance)); + m_advance.resize(m_distXSize, advancevec_t(distSize, AdvanceNone)); + m_first.resize(m_distXSize, 0); + m_last.resize(m_distXSize, 0); } void -Matcher::consumeFeatureVector(std::vector<double> feature) +Matcher::consumeFeatureVector(const feature_t &feature) { - if (!initialised) init(); - int frameIndex = frameCount % blockSize; - frames[frameIndex] = feature; + if (!m_initialised) init(); + int frameIndex = m_frameCount % m_blockSize; + m_features[frameIndex] = feature; calcAdvance(); } -vector<double> -Matcher::processFrameFromFreqData(double *reBuffer, double *imBuffer) -{ - for (int i = 0; i < (int)newFrame.size(); ++i) { - newFrame[i] = 0; - } - double rms = 0; - for (int i = 0; i <= params.fftSize/2; i++) { - double mag = reBuffer[i] * reBuffer[i] + - imBuffer[i] * imBuffer[i]; - rms += mag; - newFrame[freqMap[i]] += mag; - } - rms = sqrt(rms / (params.fftSize/2)); - - int frameIndex = frameCount % blockSize; - - vector<double> processedFrame(freqMapSize, 0.0); - - double totalEnergy = 0; - if (params.useSpectralDifference) { - for (int i = 0; i < freqMapSize; i++) { - totalEnergy += newFrame[i]; - if (newFrame[i] > prevFrame[i]) { - processedFrame[i] = newFrame[i] - prevFrame[i]; - } else { - processedFrame[i] = 0; - } - } - } else { - for (int i = 0; i < freqMapSize; i++) { - processedFrame[i] = newFrame[i]; - totalEnergy += processedFrame[i]; - } - } - totalEnergies[frameIndex] = totalEnergy; - - double decay = frameCount >= 200 ? 0.99: - (frameCount < 100? 0: (frameCount - 100) / 100.0); - - if (ltAverage == 0) - ltAverage = totalEnergy; - else - ltAverage = ltAverage * decay + totalEnergy * (1.0 - decay); - - if (rms <= params.silenceThreshold) - for (int i = 0; i < freqMapSize; i++) - processedFrame[i] = 0; - else if (params.frameNorm == NormaliseFrameToSum1) - for (int i = 0; i < freqMapSize; i++) - processedFrame[i] /= totalEnergy; - else if (params.frameNorm == NormaliseFrameToLTAverage) - for (int i = 0; i < freqMapSize; i++) - processedFrame[i] /= ltAverage; - - vector<double> tmp = prevFrame; - prevFrame = newFrame; - newFrame = tmp; - - frames[frameIndex] = processedFrame; - - if ((frameCount % 100) == 0) { - if (!silent) { - cerr << "Progress:" << frameCount << " " << ltAverage << endl; - } - } - - return processedFrame; -} - void Matcher::calcAdvance() { - int frameIndex = frameCount % blockSize; + int frameIndex = m_frameCount % m_blockSize; - if (frameCount >= distXSize) { -// std::cerr << "Resizing " << distXSize << " -> " << distXSize * 2 << std::endl; - distXSize *= 2; - distance = (unsigned char **)realloc(distance, distXSize * sizeof(unsigned char *)); - bestPathCost = (int **)realloc(bestPathCost, distXSize * sizeof(int *)); - distYSizes = (int *)realloc(distYSizes, distXSize * sizeof(int)); - first = (int *)realloc(first, distXSize * sizeof(int)); - last = (int *)realloc(last, distXSize * sizeof(int)); - - for (int i = distXSize/2; i < distXSize; ++i) { - distance[i] = 0; - } + if (m_frameCount >= m_distXSize) { + m_distXSize *= 2; + size(); } - if (firstPM && (frameCount >= blockSize)) { + if (m_firstPM && (m_frameCount >= m_blockSize)) { - int len = last[frameCount - blockSize] - - first[frameCount - blockSize]; + int len = m_last[m_frameCount - m_blockSize] - + m_first[m_frameCount - m_blockSize]; - // We need to copy distance[frameCount-blockSize] to - // distance[frameCount], and then truncate - // distance[frameCount-blockSize] to its first len elements. + // We need to copy distance[m_frameCount-m_blockSize] to + // distance[m_frameCount], and then truncate + // distance[m_frameCount-m_blockSize] to its first len elements. // Same for bestPathCost. -/* - std::cerr << "Matcher(" << this << "): moving " << distYSizes[frameCount - blockSize] << " from " << frameCount - blockSize << " to " - << frameCount << ", allocating " << len << " for " - << frameCount - blockSize << std::endl; -*/ - distance[frameCount] = distance[frameCount - blockSize]; - distance[frameCount - blockSize] = (unsigned char *) - malloc(len * sizeof(unsigned char)); + distancevec_t dOld(m_distance[m_frameCount - m_blockSize]); + distancevec_t dNew(len, InvalidDistance); + + pathcostvec_t bpcOld(m_bestPathCost[m_frameCount - m_blockSize]); + pathcostvec_t bpcNew(len, InvalidPathCost); + + advancevec_t adOld(m_advance[m_frameCount - m_blockSize]); + advancevec_t adNew(len, AdvanceNone); + for (int i = 0; i < len; ++i) { - distance[frameCount - blockSize][i] = - distance[frameCount][i]; + dNew[i] = dOld[i]; + bpcNew[i] = bpcOld[i]; + adNew[i] = adOld[i]; } + + m_distance[m_frameCount] = dOld; + m_distance[m_frameCount - m_blockSize] = dNew; - bestPathCost[frameCount] = bestPathCost[frameCount - blockSize]; + m_bestPathCost[m_frameCount] = bpcOld; + m_bestPathCost[m_frameCount - m_blockSize] = bpcNew; - bestPathCost[frameCount - blockSize] = (int *) - malloc(len * sizeof(int)); - for (int i = 0; i < len; ++i) { - bestPathCost[frameCount - blockSize][i] = - bestPathCost[frameCount][i]; - } - - distYSizes[frameCount] = distYSizes[frameCount - blockSize]; - distYSizes[frameCount - blockSize] = len; + m_advance[m_frameCount] = adOld; + m_advance[m_frameCount - m_blockSize] = adNew; } - int stop = otherMatcher->frameCount; - int index = stop - blockSize; - if (index < 0) - index = 0; - first[frameCount] = index; - last[frameCount] = stop; + int stop = m_otherMatcher->m_frameCount; + int index = stop - m_blockSize; + if (index < 0) index = 0; - bool overflow = false; - int mn= -1; - int mx= -1; + m_first[m_frameCount] = index; + m_last[m_frameCount] = stop; + for ( ; index < stop; index++) { - int dMN = metric.calcDistanceScaled - (frames[frameIndex], - otherMatcher->frames[index % blockSize], - params.distanceScale); - - if (mx<0) - mx = mn = dMN; - else if (dMN > mx) - mx = dMN; - else if (dMN < mn) - mn = dMN; - if (dMN >= 255) { - overflow = true; - dMN = 255; - } + distance_t distance = m_metric.calcDistance + (m_features[frameIndex], + m_otherMatcher->m_features[index % m_blockSize]); - if ((frameCount == 0) && (index == 0)) // first element - setValue(0, 0, 0, 0, dMN); - else if (frameCount == 0) // first row - setValue(0, index, ADVANCE_OTHER, - getValue(0, index-1, true), dMN); - else if (index == 0) // first column - setValue(frameCount, index, ADVANCE_THIS, - getValue(frameCount - 1, 0, true), dMN); - else if (index == otherMatcher->frameCount - blockSize) { + pathcost_t straightIncrement(distance); + pathcost_t diagIncrement = pathcost_t(distance * m_params.diagonalWeight); + + if ((m_frameCount == 0) && (index == 0)) { // first element + + updateValue(0, 0, AdvanceNone, + 0, + distance); + + } else if (m_frameCount == 0) { // first row + + updateValue(0, index, AdvanceOther, + getPathCost(0, index-1), + distance); + + } else if (index == 0) { // first column + + updateValue(m_frameCount, index, AdvanceThis, + getPathCost(m_frameCount - 1, 0), + distance); + + } else if (index == m_otherMatcher->m_frameCount - m_blockSize) { + // missing value(s) due to cutoff // - no previous value in current row (resp. column) // - no diagonal value if prev. dir. == curr. dirn - int min2 = getValue(frameCount - 1, index, true); - // if ((firstPM && (first[frameCount - 1] == index)) || - // (!firstPM && (last[index-1] < frameCount))) - if (first[frameCount - 1] == index) - setValue(frameCount, index, ADVANCE_THIS, min2, dMN); - else { - int min1 = getValue(frameCount - 1, index - 1, true); - if (min1 + dMN <= min2) - setValue(frameCount, index, ADVANCE_BOTH, min1,dMN); - else - setValue(frameCount, index, ADVANCE_THIS, min2,dMN); + + pathcost_t min2 = getPathCost(m_frameCount - 1, index); + +// cerr << "NOTE: missing value at i = " << m_frameCount << ", j = " +// << index << " (first = " << m_firstPM << ")" << endl; + + // if ((m_firstPM && (first[m_frameCount - 1] == index)) || + // (!m_firstPM && (m_last[index-1] < m_frameCount))) + if (m_first[m_frameCount - 1] == index) { + + updateValue(m_frameCount, index, AdvanceThis, + min2, distance); + + } else { + + pathcost_t min1 = getPathCost(m_frameCount - 1, index - 1); + if (min1 + diagIncrement <= min2 + straightIncrement) { + updateValue(m_frameCount, index, AdvanceBoth, + min1, distance); + } else { + updateValue(m_frameCount, index, AdvanceThis, + min2, distance); + } } + } else { - int min1 = getValue(frameCount, index-1, true); - int min2 = getValue(frameCount - 1, index, true); - int min3 = getValue(frameCount - 1, index-1, true); - if (min1 <= min2) { - if (min3 + dMN <= min1) - setValue(frameCount, index, ADVANCE_BOTH, min3,dMN); - else - setValue(frameCount, index, ADVANCE_OTHER,min1,dMN); + + pathcost_t min1 = getPathCost(m_frameCount, index - 1); + pathcost_t min2 = getPathCost(m_frameCount - 1, index); + pathcost_t min3 = getPathCost(m_frameCount - 1, index - 1); + + pathcost_t cost1 = min1 + straightIncrement; + pathcost_t cost2 = min2 + straightIncrement; + pathcost_t cost3 = min3 + diagIncrement; + + // Choosing is easy if there is a strict cheapest of the + // three. If two or more share the lowest cost, we choose + // in order of preference: cost3 (AdvanceBoth), cost2 + // (AdvanceThis), cost1 (AdvanceOther) if we are the first + // matcher; and cost3 (AdvanceBoth), cost1 (AdvanceOther), + // cost2 (AdvanceThis) if we are the second matcher. That + // is, we always prioritise the diagonal followed by the + // first matcher. + + if (( m_firstPM && (cost1 < cost2)) || + (!m_firstPM && (cost1 <= cost2))) { + if (cost3 <= cost1) { + updateValue(m_frameCount, index, AdvanceBoth, + min3, distance); + } else { + updateValue(m_frameCount, index, AdvanceOther, + min1, distance); + } } else { - if (min3 + dMN <= min2) - setValue(frameCount, index, ADVANCE_BOTH, min3,dMN); - else - setValue(frameCount, index, ADVANCE_THIS, min2,dMN); + if (cost3 <= cost2) { + updateValue(m_frameCount, index, AdvanceBoth, + min3, distance); + } else { + updateValue(m_frameCount, index, AdvanceThis, + min2, distance); + } } } - otherMatcher->last[index]++; + + m_otherMatcher->m_last[index]++; } // loop for row (resp. column) - frameCount++; - runCount++; + m_frameCount++; + m_runCount++; - otherMatcher->runCount = 0; - - if (overflow && !silent) - cerr << "WARNING: overflow in distance metric: " - << "frame " << frameCount << ", val = " << mx << endl; - - if (!silent) - std::cerr << "Frame " << frameCount << ", d = " << (mx-mn) << std::endl; + m_otherMatcher->m_runCount = 0; } -int -Matcher::getValue(int i, int j, bool firstAttempt) +void +Matcher::updateValue(int i, int j, advance_t dir, pathcost_t value, distance_t distance) { - if (firstPM) - return bestPathCost[i][j - first[i]]; - else - return otherMatcher->bestPathCost[j][i - otherMatcher->first[j]]; -} // getValue() + pathcost_t increment = distance; + if (dir == AdvanceBoth) { + increment = pathcost_t(increment * m_params.diagonalWeight); + } -void -Matcher::setValue(int i, int j, int dir, int value, int dMN) -{ - if (firstPM) { - distance[i][j - first[i]] = (unsigned char)((dMN & MASK) | dir); - bestPathCost[i][j - first[i]] = - (value + (dir==ADVANCE_BOTH? dMN*2: dMN)); + pathcost_t newValue = value + increment; + if (MaxPathCost - increment < value) { + cerr << "ERROR: Path cost overflow at i=" << i << ", j=" << j << ": " + << value << " + " << increment << " > " << MaxPathCost << endl; + newValue = MaxPathCost; + } + + if (m_firstPM) { + + setDistance(i, j, distance); + setPathCost(i, j, dir, newValue); + } else { - if (dir == ADVANCE_THIS) - dir = ADVANCE_OTHER; - else if (dir == ADVANCE_OTHER) - dir = ADVANCE_THIS; - int idx = i - otherMatcher->first[j]; - if (idx == (int)otherMatcher->distYSizes[j]) { + + if (dir == AdvanceThis) dir = AdvanceOther; + else if (dir == AdvanceOther) dir = AdvanceThis; + + int idx = i - m_otherMatcher->m_first[j]; + + if (idx < 0 || size_t(idx) == m_otherMatcher->m_distance[j].size()) { // This should never happen, but if we allow arbitrary // pauses in either direction, and arbitrary lengths at // end, it is better than a segmentation fault. - std::cerr << "Emergency resize: " << idx << " -> " << idx * 2 << std::endl; - otherMatcher->distYSizes[j] = idx * 2; - otherMatcher->bestPathCost[j] = - (int *)realloc(otherMatcher->bestPathCost[j], - idx * 2 * sizeof(int)); - otherMatcher->distance[j] = - (unsigned char *)realloc(otherMatcher->distance[j], - idx * 2 * sizeof(unsigned char)); + cerr << "Emergency resize: " << idx << " -> " << idx * 2 << endl; + m_otherMatcher->m_bestPathCost[j].resize(idx * 2, InvalidPathCost); + m_otherMatcher->m_distance[j].resize(idx * 2, InvalidDistance); + m_otherMatcher->m_advance[j].resize(idx * 2, AdvanceNone); } - otherMatcher->distance[j][idx] = (unsigned char)((dMN & MASK) | dir); - otherMatcher->bestPathCost[j][idx] = - (value + (dir==ADVANCE_BOTH? dMN*2: dMN)); + + m_otherMatcher->setDistance(j, i, distance); + m_otherMatcher->setPathCost(j, i, dir, newValue); } -} // setValue() +} +advance_t +Matcher::getAdvance(int i, int j) +{ + if (m_firstPM) { + if (!isInRange(i, j)) { + cerr << "ERROR: Matcher::getAdvance(" << i << ", " << j << "): " + << "Location is not in range" << endl; + throw "Advance not available"; + } + return m_advance[i][j - m_first[i]]; + } else { + return m_otherMatcher->getAdvance(j, i); + } +}
--- a/src/Matcher.h Fri Nov 14 10:24:13 2014 +0000 +++ b/src/Matcher.h Fri Feb 27 09:29:37 2015 +0000 @@ -14,351 +14,249 @@ COPYING included with this distribution for more information. */ -#ifndef _MATCHER_H_ -#define _MATCHER_H_ +#ifndef MATCHER_H +#define MATCHER_H #include <vector> #include <iostream> #include <sstream> #include <cmath> -#define ADVANCE_THIS 1 -#define ADVANCE_OTHER 2 -#define ADVANCE_BOTH 3 -#define MASK 0xfc - #include "DistanceMetric.h" +#include "MatchTypes.h" using std::vector; using std::string; using std::cerr; using std::endl; -/** Represents an audio stream that can be matched to another audio - * stream of the same piece of music. The matching algorithm uses - * dynamic time warping. The distance metric is a Euclidean metric - * on the FFT data with the higher frequencies mapped onto a linear - * scale. +/** Represents an audio feature stream that can be matched to another + * audio stream of the same piece of music. The matching algorithm + * uses dynamic time warping. */ class Matcher { public: - enum FrameNormalisation { - - /** Do not normalise audio frames */ - NoFrameNormalisation, - - /** Normalise each frame of audio to have a sum of 1 */ - NormaliseFrameToSum1, - - /** Normalise each frame of audio by the long-term average - * of the summed energy */ - NormaliseFrameToLTAverage, - }; + static string advanceToString(advance_t a) { + switch (a) { + case AdvanceNone: return "AdvanceNone"; + case AdvanceBoth: return "AdvanceBoth"; + case AdvanceThis: return "AdvanceThis"; + case AdvanceOther: return "AdvanceOther"; + } + return "(unknown)"; + } struct Parameters { - Parameters(float rate_, double hopTime_, int fftSize_) : - sampleRate(rate_), - frameNorm(NormaliseFrameToSum1), - distanceNorm(DistanceMetric::NormaliseDistanceToLogSum), - distanceScale(90.0), - useSpectralDifference(true), - useChromaFrequencyMap(false), + Parameters(double hopTime_) : hopTime(hopTime_), - fftSize(fftSize_), blockTime(10.0), - silenceThreshold(0.01), - decay(0.99), - maxRunCount(3) + maxRunCount(3), + diagonalWeight(2.0) {} - /** Sample rate of audio */ - float sampleRate; - - /** Type of audio frame normalisation */ - FrameNormalisation frameNorm; - - /** Type of distance metric normalisation */ - DistanceMetric::DistanceNormalisation distanceNorm; - - /** Scaling factor for distance metric; must guarantee that the - * final value fits in the data type used, that is, unsigned - * char. - */ - double distanceScale; - - /** Flag indicating whether or not the half-wave rectified - * spectral difference should be used in calculating the - * distance metric for pairs of audio frames, instead of the - * straight spectrum values. */ - bool useSpectralDifference; - - /** Flag indicating whether to use a chroma frequency map (12 - * bins) instead of the default warped spectrogram */ - bool useChromaFrequencyMap; - /** Spacing of audio frames (determines the amount of overlap or * skip between frames). This value is expressed in - * seconds. */ + * seconds. + */ double hopTime; - - /** Size of an FFT frame in samples. Note that the data passed - * in to Matcher is already in the frequency domain, so this - * expresses the size of the frame that the caller will be - * providing. - */ - int fftSize; - + /** The width of the search band (error margin) around the current * match position, measured in seconds. Strictly speaking the * width is measured backwards from the current point, since the * algorithm has to work causally. */ double blockTime; - - /** RMS level below which frame is considered silent */ - double silenceThreshold; - - /** Frame-to-frame decay factor in calculating long-term average */ - double decay; /** Maximum number of frames sequentially processed by this * matcher, without a frame of the other matcher being * processed. */ int maxRunCount; + + /** Weight applied to cost of diagonal step relative to + * horizontal or vertical step. The default of 2.0 means that + * a diagonal is not favoured over horizontal+vertical + * combined, which is good when maintaining gross tracking of + * performances that may have wildly differing speeds but + * which also leads to quite jaggy paths. A more typical + * normal DTW approach for performances with similar speeds + * might use 1.0 or something close to it. + */ + double diagonalWeight; }; -protected: - /** Points to the other performance with which this one is being - * compared. The data for the distance metric and the dynamic - * time warping is shared between the two matchers. In the - * original version, only one of the two performance matchers - * contained the distance metric. (See <code>first</code>) - */ - Matcher *otherMatcher; - - /** Indicates which performance is considered primary (the - * score). This is the performance shown on the vertical axis, - * and referred to as "this" in the codes for the direction of - * DTW steps. */ - bool firstPM; - - /** Configuration parameters */ - Parameters params; - - /** Width of the search band in FFT frames (see <code>blockTime</code>) */ - int blockSize; - - /** The number of frames of audio data which have been read. */ - int frameCount; - - /** Long term average frame energy (in frequency domain - * representation). */ - double ltAverage; - - /** The number of frames sequentially processed by this matcher, - * without a frame of the other matcher being processed. - */ - int runCount; - - /** A mapping function for mapping FFT bins to final frequency - * bins. The mapping is linear (1-1) until the resolution - * reaches 2 points per semitone, then logarithmic with a - * semitone resolution. e.g. for 44.1kHz sampling rate and - * fftSize of 2048 (46ms), bin spacing is 21.5Hz, which is mapped - * linearly for bins 0-34 (0 to 732Hz), and logarithmically for - * the remaining bins (midi notes 79 to 127, bins 35 to 83), - * where all energy above note 127 is mapped into the final - * bin. */ - vector<int> freqMap; - - /** The number of entries in <code>freqMap</code>. */ - int freqMapSize; - - /** The number of values in an externally-supplied feature vector, - * used in preference to freqMap/freqMapSize if constructed with - * the external feature version of the Matcher constructor. If - * this is zero, the internal feature extractor will be used as - * normal. - */ - int externalFeatureSize; - - /** The number of values in the feature vectors actually in - * use. This will be externalFeatureSize if greater than zero, or - * freqMapSize otherwise. - */ - int featureSize; - - /** The most recent frame; used for calculating the frame to frame - * spectral difference. These are therefore frequency warped but - * not yet normalised. */ - vector<double> prevFrame; - vector<double> newFrame; - - /** A block of previously seen frames are stored in this structure - * for calculation of the distance matrix as the new frames are - * read in. One can think of the structure of the array as a - * circular buffer of vectors. These are the frames with all - * applicable processing applied (e.g. spectral difference, - * normalisation), unlike prevFrame and newFrame. The total - * energy of frames[i] is stored in totalEnergies[i]. */ - vector<vector<double> > frames; - - /** The total energy of each frame in the frames block. */ - vector<double> totalEnergies; - - /** The best path cost matrix. */ - int **bestPathCost; - - /** The distance matrix. */ - unsigned char **distance; - - /** The bounds of each row of data in the distance and path cost matrices.*/ - int *first; - int *last; - - /** Height of each column in distance and bestPathCost matrices */ - int *distYSizes; - - /** Width of distance and bestPathCost matrices and first and last vectors */ - int distXSize; - - bool initialised; - - /** Disable or enable debugging output */ - static bool silent; - -public: /** Constructor for Matcher. + * + * A Matcher expects to be provided with feature vectors + * calculated by some external code (for example, a + * FeatureExtractor). Call consumeFeatureVector to provide each + * feature frame. * * @param p The Matcher representing the performance with which * this one is going to be matched. Some information is shared * between the two matchers (currently one possesses the distance * matrix and optimal path matrix). */ - Matcher(Parameters parameters, Matcher *p); + Matcher(Parameters params, DistanceMetric::Parameters dparams, Matcher *p); - /** Constructor for Matcher using externally supplied features. - * A Matcher made using this constructor will not carry out its - * own feature extraction from frequency-domain audio data, but - * instead will accept arbitrary feature frames calculated by - * some external code. - * - * @param p The Matcher representing the performance with which - * this one is going to be matched. Some information is shared - * between the two matchers (currently one possesses the distance - * matrix and optimal path matrix). - * - * @param featureSize Number of values in each feature vector. + /** Destructor for Matcher. */ - Matcher(Parameters parameters, Matcher *p, int featureSize); - ~Matcher(); - /** For debugging, outputs information about the Matcher to - * standard error. - */ - void print(); - /** Adds a link to the Matcher object representing the performance * which is going to be matched to this one. * * @param p the Matcher representing the other performance */ void setOtherMatcher(Matcher *p) { - otherMatcher = p; - } // setOtherMatcher() - - int getFrameCount() { - return frameCount; + m_otherMatcher = p; } - /** - * Return the feature vector size that will be used for the given - * parameters. - */ - static int getFeatureSizeFor(Parameters params); - -protected: - template <typename T> - void initVector(vector<T> &vec, int sz, T dflt = 0) { - vec.clear(); - while ((int)vec.size() < sz) vec.push_back(dflt); + int getBlockSize() { + return m_blockSize; } - template <typename T> - void initMatrix(vector<vector<T> > &mat, int hsz, int vsz, - T dflt = 0, int fillTo = -1) { - mat.clear(); - if (fillTo < 0) fillTo = hsz; - for (int i = 0; i < hsz; ++i) { - mat.push_back(vector<T>()); - if (i < fillTo) { - while ((int)mat[i].size() < vsz) { - mat[i].push_back(dflt); - } - } - } + bool isFillingInitialBlock() { + return m_frameCount < m_blockSize; + } + + bool isOverrunning() { + return m_runCount >= m_params.maxRunCount; + } + + int getFrameCount() { + return m_frameCount; } - void init(); + int getOtherFrameCount() { + return m_otherMatcher->getFrameCount(); + } - void makeFreqMap(); + double getDiagonalWeight() { + return m_params.diagonalWeight; + } + + /** Processes a feature vector frame, presumably calculated from + * audio data by some external code such as a FeatureExtractor. + * Calculates the distance to all frames stored in the + * otherMatcher and stores in the distance matrix, before + * updating the optimal path matrix using the dynamic time + * warping algorithm. + * + * The supplied features must always be of the same size (within + * any pair of Matcher objects). + */ + void consumeFeatureVector(const feature_t &feature); + + /** Tests whether a location is in range in the minimum cost matrix. + * + * @param i the frame number of this Matcher + * @param j the frame number of the other Matcher + * @return true if the location is in range + */ + bool isInRange(int i, int j); - /** Creates a map of FFT frequency bins to comparison bins. Where - * the spacing of FFT bins is less than 0.5 semitones, the - * mapping is one to one. Where the spacing is greater than 0.5 - * semitones, the FFT energy is mapped into semitone-wide - * bins. No scaling is performed; that is the energy is summed - * into the comparison bins. See also consumeFrame() + /** Tests whether any locations in the given row are available. */ - void makeStandardFrequencyMap(); + bool isRowAvailable(int i); - void makeChromaFrequencyMap(); + /** Tests whether any locations in the given column are available. + */ + bool isColAvailable(int i); + + /** Tests whether a location is available in the minimum cost matrix. + * + * @param i the frame number of this Matcher + * @param j the frame number of the other Matcher + * @return true if the location is in range and contains a valid cost + */ + bool isAvailable(int i, int j); - /** Processes a frame of audio data by first computing the STFT - * with a Hamming window, then mapping the frequency bins into a - * part-linear part-logarithmic array, then (optionally) - * computing the half-wave rectified spectral difference from the - * previous frame, then (optionally) normalising to a sum of 1, - * then calculating the distance to all frames stored in the - * otherMatcher and storing them in the distance matrix, and - * finally updating the optimal path matrix using the dynamic - * time warping algorithm. + /** Returns the valid range of columns for the given row, that is, + * the range of frames in the other Matcher for the given frame + * in this Matcher's minimum cost matrix. * - * Return value is the frame (post-processed, with warping, - * rectification, and normalisation as appropriate). + * @param i the frame number of this Matcher + * @return the first, last pair of frame numbers for the other + * Matcher. Note that the last frame is exclusive (last valid + * frame + 1). + */ + std::pair<int, int> getColRange(int i); + + /** Returns the valid range of rows for the given column, that is, + * the range of frames in this Matcher for the given frame in the + * other Matcher's minimum cost matrix. * - * The Matcher must have been constructed using the constructor - * without an external featureSize parameter in order to use this - * function. (Otherwise it will be expecting you to call - * consumeFeatureVector.) + * @param i the frame number of the other Matcher + * @return the first, last pair of frame numbers for this + * Matcher. Note that the last frame is exclusive (last valid + * frame + 1). */ - std::vector<double> consumeFrame(double *reBuffer, double *imBuffer); + std::pair<int, int> getRowRange(int i); + + /** Retrieves a value from the distance matrix. + * + * @param i the frame number of this Matcher + * @param j the frame number of the other Matcher + * @return the distance metric at this location + */ + distance_t getDistance(int i, int j); - /** Processes a feature vector frame (presumably calculated from - * audio data by some external code). As consumeFrame, except - * that it does not calculate a feature from audio data but - * instead uses the supplied feature directly. + /** Sets a value to the distance matrix. * - * The Matcher must have been constructed using the constructor - * that accepts an external featureSize parameter in order to - * use this function. The supplied feature must be of the size - * that was passed to the constructor. + * @param i the frame number of this Matcher + * @param j the frame number of the other Matcher + * @param value the distance metric to set for this location */ - void consumeFeatureVector(std::vector<double> feature); - - /** Retrieves values from the minimum cost matrix. + void setDistance(int i, int j, distance_t distance); + + /** Retrieves a value from the minimum cost matrix. * * @param i the frame number of this Matcher * @param j the frame number of the other Matcher * @return the cost of the minimum cost path to this location */ - int getValue(int i, int j, bool firstAttempt); + pathcost_t getPathCost(int i, int j); - /** Stores entries in the distance matrix and the optimal path matrix. + /** Sets a value and an advance direction to the minimum cost matrix. + * + * @param i the frame number of this Matcher + * @param j the frame number of the other Matcher + * @param dir the direction from which this position is reached with + * minimum cost + * @param value the cost of the minimum cost path to set for this location + */ + void setPathCost(int i, int j, advance_t dir, pathcost_t value); + + /** Retrieves a value from the minimum cost matrix, normalised for + * path length. + * + * @param i the frame number of this Matcher + * @param j the frame number of the other Matcher + * @return the cost of the minimum cost path to this location, + * normalised by the Manhattan distance from 0,0 to i,j + */ + normpathcost_t getNormalisedPathCost(int i, int j); + + /** Retrieves an advance direction from the matrix. + * + * @param i the frame number of this Matcher + * @param j the frame number of the other Matcher + * @return the direction from which this position is reached with + * minimum cost + */ + advance_t getAdvance(int i, int j); + +protected: + /** Create internal structures and reset. */ + void init(); + + /** The distXSize value has changed: resize internal buffers. */ + void size(); + + /** Updates an entry in the distance matrix and the optimal path matrix. * * @param i the frame number of this Matcher * @param j the frame number of the other Matcher @@ -367,17 +265,65 @@ * @param value the cost of the minimum path except the current step * @param dMN the distance cost between the two frames */ - void setValue(int i, int j, int dir, int value, int dMN); + void updateValue(int i, int j, advance_t dir, pathcost_t value, distance_t dMN); - vector<double> processFrameFromFreqData(double *, double *); void calcAdvance(); - DistanceMetric metric; - - friend class MatchFeeder; - friend class MatchFeatureFeeder; - friend class Finder; + /** Points to the other performance with which this one is being + * compared. The data for the distance metric and the dynamic + * time warping is shared between the two matchers. In the + * original version, only one of the two performance matchers + * contained the distance metric. (See <code>first</code>) + */ + Matcher *m_otherMatcher; -}; // class Matcher + /** Indicates which performance is considered primary (the + * score). This is the performance shown on the vertical axis, + * and referred to as "this" in the codes for the direction of + * DTW steps. */ + bool m_firstPM; + + /** Configuration parameters */ + Parameters m_params; + + /** Width of the search band in FFT frames (see <code>blockTime</code>) */ + int m_blockSize; + + /** The number of frames of audio data which have been read. */ + int m_frameCount; + + /** The number of frames sequentially processed by this matcher, + * without a frame of the other matcher being processed. + */ + int m_runCount; + + /** A block of previously seen feature frames is stored in this + * structure for calculation of the distance matrix as the new + * frames are received. One can think of the structure of the + * array as a circular buffer of vectors. */ + featureseq_t m_features; + + /** The best path cost matrix. */ + pathcostmat_t m_bestPathCost; + + /** The distance matrix. */ + distancemat_t m_distance; + + /** The advance direction matrix. */ + advancemat_t m_advance; + + /** The bounds of each row of data in the distance, path cost, and + * advance direction matrices.*/ + vector<int> m_first; + vector<int> m_last; + + /** Width of distance, path cost, and advance direction matrices + * and first and last vectors */ + int m_distXSize; + + bool m_initialised; + + DistanceMetric m_metric; +}; #endif
--- a/src/Path.cpp Fri Nov 14 10:24:13 2014 +0000 +++ b/src/Path.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -19,55 +19,55 @@ int Path::smooth(std::vector<int> &x, std::vector<int> &y, int length) { - if (length == 0) + if (length <= 0) return 0; - while ((int)val.size() < length) { - val.push_back(0); - len.push_back(0); + while (m_val.size() < static_cast<std::vector<int>::size_type>(length)) { + m_val.push_back(0); + m_len.push_back(0); } int p = 0; - val[0] = len[0] = 0; + m_val[0] = m_len[0] = 0; for (int i = 1; i < length; i++) { // H = 1; V = 2; D = 3 int current = x[i] - x[i-1] + 2 * (y[i] - y[i-1]); - if (current == val[p]) { - len[p]++; - } else if ((current == 3) || (val[p] == 0)) { - val[++p] = current; - len[p] = 1; - } else if (val[p] + current == 3) { // 1 + 2 - if (--len[p] == 0) + if (current == m_val[p]) { + m_len[p]++; + } else if ((current == 3) || (m_val[p] == 0)) { + m_val[++p] = current; + m_len[p] = 1; + } else if (m_val[p] + current == 3) { // 1 + 2 + if (--m_len[p] == 0) p--; - if (val[p] == 3) - len[p]++; + if (m_val[p] == 3) + m_len[p]++; else { - val[++p] = 3; - len[p] = 1; + m_val[++p] = 3; + m_len[p] = 1; } - } else { // val[p] == 3 && current != 3 - if ((val[p-1] == current) || - (val[p-1] == 0) || - (len[p] > MAX_RUN_LENGTH)) { - val[++p] = current; - len[p] = 1; + } else { // m_val[p] == 3 && current != 3 + if ((m_val[p-1] == current) || + (m_val[p-1] == 0) || + (m_len[p] > MAX_RUN_LENGTH)) { + m_val[++p] = current; + m_len[p] = 1; } else { - if (--len[p-1] == 0) { - val[p-1] = val[p]; - len[p-1] = len[p]; + if (--m_len[p-1] == 0) { + m_val[p-1] = m_val[p]; + m_len[p-1] = m_len[p]; p--; - if (val[p-1] == 3) { - len[p-1] += len[p]; + if (m_val[p-1] == 3) { + m_len[p-1] += m_len[p]; p--; } } - len[p]++; + m_len[p]++; } } } int i = 1; for (int pp = 1; pp <= p; pp++) { - int dx = val[pp] & 1; - int dy = val[pp] >> 1; - for (int j = len[pp]; j > 0; j--, i++) { + int dx = m_val[pp] & 1; + int dy = m_val[pp] >> 1; + for (int j = m_len[pp]; j > 0; j--, i++) { x[i] = x[i-1] + dx; y[i] = y[i-1] + dy; }
--- a/src/Path.h Fri Nov 14 10:24:13 2014 +0000 +++ b/src/Path.h Fri Feb 27 09:29:37 2015 +0000 @@ -38,8 +38,8 @@ protected: static const int MAX_RUN_LENGTH = 50; - std::vector<int> val; - std::vector<int> len; + std::vector<int> m_val; + std::vector<int> m_len; }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/TestDistanceMetric.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,109 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#include "DistanceMetric.h" + +#include <vector> +#include <iostream> +#include <cmath> + +using namespace std; + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN + +#include <boost/test/unit_test.hpp> + +static feature_t getTestFeature(double m) +{ + feature_t f; + int fd[] = { 0, 1, 2, 3 }; + for (int i = 0; i < 4; ++i) { + f.push_back(featurebin_t(fd[i] * m)); + } + return f; +} + +BOOST_AUTO_TEST_SUITE(TestDistanceMetric) + +BOOST_AUTO_TEST_CASE(scale) +{ + DistanceMetric::Parameters params; + params.scale = 1.0; + DistanceMetric dm(params); + + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(0.0), 0); + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(1.0), 1); + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(2.0), 2); + + if (sizeof(distance_t) == 1) { + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(256.0), MaxDistance); + } else { + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(256.0), 256); + } + + params.scale = 2.0; + dm = DistanceMetric(params); + + if (sizeof(distance_t) == 1) { + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(0.0), 0); + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(1.0), 2); + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(2.0), 4); + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(128.0), MaxDistance); + } else { + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(0.0), 0); + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(1.0), 1); + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(2.0), 2); + BOOST_CHECK_EQUAL(dm.scaleValueIntoDistanceRange(256.0), 256); + } +} + +BOOST_AUTO_TEST_CASE(nonorm) +{ + DistanceMetric::Parameters params; + params.norm = DistanceMetric::NoDistanceNormalisation; + DistanceMetric dm(params); + feature_t + e1 = getTestFeature(1), + e2 = getTestFeature(2), + e0 = getTestFeature(0); + + double noise = 1e-3 * 4; +#ifdef USE_COMPACT_TYPES + noise = 1.0 / params.scale; +#endif + + BOOST_CHECK_EQUAL(dm.calcDistance(e0, e0), dm.scaleValueIntoDistanceRange(0.0 + noise)); + BOOST_CHECK_EQUAL(dm.calcDistance(e1, e0), dm.scaleValueIntoDistanceRange(6.0 + noise)); + BOOST_CHECK_EQUAL(dm.calcDistance(e0, e1), dm.scaleValueIntoDistanceRange(6.0 + noise)); + BOOST_CHECK_EQUAL(dm.calcDistance(e1, e1), dm.scaleValueIntoDistanceRange(0.0 + noise)); + BOOST_CHECK_EQUAL(dm.calcDistance(e1, e2), dm.scaleValueIntoDistanceRange(6.0 + noise)); + BOOST_CHECK_EQUAL(dm.calcDistance(e0, e2), dm.scaleValueIntoDistanceRange(12.0 + noise)); +} + +BOOST_AUTO_TEST_CASE(sum) +{ + DistanceMetric::Parameters params; + params.norm = DistanceMetric::NormaliseDistanceToSum; + DistanceMetric dm(params); + feature_t + e1 = getTestFeature(1), + e2 = getTestFeature(2), + e0 = getTestFeature(0); + + double noise = 1e-3 * 4; +#ifdef USE_COMPACT_TYPES + noise = 1.0 / params.scale; +#endif + + BOOST_CHECK_EQUAL(dm.calcDistance(e0, e0), dm.scaleValueIntoDistanceRange(1.0)); + BOOST_CHECK_EQUAL(dm.calcDistance(e1, e0), dm.scaleValueIntoDistanceRange(1.0)); + BOOST_CHECK_EQUAL(dm.calcDistance(e0, e1), dm.scaleValueIntoDistanceRange(1.0)); + BOOST_CHECK_EQUAL(dm.calcDistance(e1, e1), dm.scaleValueIntoDistanceRange(noise / (12.0 + noise))); + BOOST_CHECK_EQUAL(dm.calcDistance(e1, e2), dm.scaleValueIntoDistanceRange((6.0 + noise) / (18.0 + noise))); + BOOST_CHECK_EQUAL(dm.calcDistance(e0, e2), dm.scaleValueIntoDistanceRange(1.0)); +} + +BOOST_AUTO_TEST_SUITE_END() + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/TestFeatureConditioner.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,176 @@ + +#include "FeatureConditioner.h" + +#include <vector> +#include <iostream> +#include <cmath> + +using namespace std; + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN + +#include <boost/test/unit_test.hpp> + +static feature_t getTestFeature(double m) +{ + feature_t f; + int fd[] = { 0, 1, 2, 3 }; + for (int i = 0; i < 4; ++i) { + f.push_back(featurebin_t(fd[i] * m)); + } + return f; +} + +BOOST_AUTO_TEST_SUITE(TestFeatureConditioner) + +BOOST_AUTO_TEST_CASE(nonorm_features) +{ + FeatureConditioner::Parameters params; + params.norm = FeatureConditioner::NoNormalisation; + params.order = FeatureConditioner::OutputFeatures; + feature_t + e1 = getTestFeature(1), + e2 = getTestFeature(2), + e0 = getTestFeature(0); + + params.silenceThreshold = 1.0; + FeatureConditioner fc(params); + feature_t out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e1.begin(), e1.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e2.begin(), e2.end()); + + params.silenceThreshold = 7.0; + fc = FeatureConditioner(params); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e0.begin(), e0.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e2.begin(), e2.end()); +} + +BOOST_AUTO_TEST_CASE(nonorm_rectderiv) +{ + FeatureConditioner::Parameters params; + params.norm = FeatureConditioner::NoNormalisation; + params.order = FeatureConditioner::OutputRectifiedDerivative; + feature_t + e1 = getTestFeature(1), + e2 = getTestFeature(2), + e0 = getTestFeature(0); + + params.silenceThreshold = 1.0; + FeatureConditioner fc(params); + feature_t out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e1.begin(), e1.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e1.begin(), e1.end()); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e0.begin(), e0.end()); + + params.silenceThreshold = 7.0; + fc = FeatureConditioner(params); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e0.begin(), e0.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e1.begin(), e1.end()); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e0.begin(), e0.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e1.begin(), e1.end()); +} + +BOOST_AUTO_TEST_CASE(nonorm_deriv) +{ + FeatureConditioner::Parameters params; + params.norm = FeatureConditioner::NoNormalisation; + params.order = FeatureConditioner::OutputDerivative; + feature_t + e1 = getTestFeature(1), + e2 = getTestFeature(2), + e3 = getTestFeature(3), + e0 = getTestFeature(0); + + params.silenceThreshold = 1.0; + FeatureConditioner fc(params); + feature_t out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e1.begin(), e1.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e1.begin(), e1.end()); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e1.begin(), e1.end()); + + params.silenceThreshold = 7.0; + fc = FeatureConditioner(params); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e0.begin(), e0.end()); + out = fc.process(e3); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e2.begin(), e2.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e1.begin(), e1.end()); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e0.begin(), e0.end()); +} + +BOOST_AUTO_TEST_CASE(sum1_features) +{ + FeatureConditioner::Parameters params; + params.norm = FeatureConditioner::NormaliseToSum1; + params.order = FeatureConditioner::OutputFeatures; + feature_t + e1 = getTestFeature(1), + e2 = getTestFeature(2), + en = getTestFeature(1.0/6.0), + e0 = getTestFeature(0); + + params.silenceThreshold = 1.0; + FeatureConditioner fc(params); + feature_t out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), en.begin(), en.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), en.begin(), en.end()); + + params.silenceThreshold = 7.0; + fc = FeatureConditioner(params); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e0.begin(), e0.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), en.begin(), en.end()); +} + +BOOST_AUTO_TEST_CASE(sum1_rectderiv) +{ + FeatureConditioner::Parameters params; + params.norm = FeatureConditioner::NormaliseToSum1; + params.order = FeatureConditioner::OutputRectifiedDerivative; + feature_t + e1 = getTestFeature(1), + e2 = getTestFeature(2), + en = getTestFeature(1.0/6.0), + en2 = getTestFeature(1.0/12.0), + e0 = getTestFeature(0); + + params.silenceThreshold = 1.0; + FeatureConditioner fc(params); + feature_t out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), en.begin(), en.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), en2.begin(), en2.end()); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e0.begin(), e0.end()); + + params.silenceThreshold = 7.0; + fc = FeatureConditioner(params); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e0.begin(), e0.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), en2.begin(), en2.end()); + out = fc.process(e1); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), e0.begin(), e0.end()); + out = fc.process(e2); + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), en2.begin(), en2.end()); +} + + +BOOST_AUTO_TEST_SUITE_END() +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/TestFeatureExtractor.cpp Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,206 @@ + +#include "FeatureExtractor.h" + +#include <vector> +#include <iostream> +#include <cmath> + +using namespace std; + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN + +#include <boost/test/unit_test.hpp> + +static int freq2mid(double freq) +{ + return int(round(57.0 + 12.0 * log(freq / 220.) / log(2.))); +} + +static int freq2chroma(double freq) +{ + return freq2mid(freq) % 12; +} + +static int bin2warped(int bin, int rate, int sz) +{ + // see comments in nonchroma below + if (bin <= 33) return bin; + double freq = (double(bin) * rate) / sz; + int mid = freq2mid(freq); + if (mid > 127) mid = 127; + int outbin = mid - 77 + 33; + return outbin; +} + +BOOST_AUTO_TEST_SUITE(TestFeatureExtractor) + +void checkAlternateProcessType(FeatureExtractor &fe, feature_t expected, + vector<double> real, vector<double> imag) +{ + vector<float> in; + for (size_t i = 0; i < real.size(); ++i) { + in.push_back(float(real[i])); + in.push_back(float(imag[i])); + } + feature_t alt = fe.process(&in[0]); + BOOST_CHECK_EQUAL_COLLECTIONS(alt.begin(), alt.end(), + expected.begin(), expected.end()); +} + +BOOST_AUTO_TEST_CASE(chroma) +{ + int szs[] = { 1024, 2048, 4000 }; + int rates[] = { 44100, 48000 }; + + for (int irate = 0; irate < int(sizeof(rates)/sizeof(rates[0])); ++irate) { + + int rate = rates[irate]; + + for (int isz = 0; isz < int(sizeof(szs)/sizeof(szs[0])); ++isz) { + + int sz = szs[isz]; + + int hs = sz / 2 + 1; + int fsz = 13; + + FeatureExtractor::Parameters params(float(rate), sz); + params.useChromaFrequencyMap = true; + params.minFrequency = 0; + FeatureExtractor fe(params); + BOOST_CHECK_EQUAL(fe.getFeatureSize(), fsz); + + for (int bin = 0; bin < hs; ++bin) { + + vector<double> real, imag; + real.resize(hs, 0.0); + imag.resize(hs, 0.0); + + real[bin] += 10.0; + imag[bin] += 10.0; + + // use two input sweeps, so we can test that they are + // properly summed into the output bin + real[hs-bin-1] += 5.0; + imag[hs-bin-1] += 5.0; + + feature_t out = fe.process(real, imag); + + checkAlternateProcessType(fe, out, real, imag); + + // We expect to find all bins are 0 except for: + // + // * two bins of 200 and 50 respectively, if the two input + // bins are distinct and their output chroma are also distinct + // + // * one bin of value 250 (= 10^2 + 5^2), if the two input + // bins are distinct but their output chroma are not + // + // * one bin of value 450 (= 15^2 + 15^2), if the input bins + // are not distinct (the feature extractor sums energies + // rather than magnitudes so as to integrate energy for a + // partial in the face of spectral leakage) + // + // The bin corresponding to each input frequency is + // that of its semitone value (with C=0), except that + // input bins less than the 17th are shepherded into + // the separate bin 0 (see docs in FeatureExtractor.h) + + double cutoff = (17.0 * rate) / sz; + + feature_t expected(fsz); + + double infreq1 = (double(bin) * rate) / sz; + + if (bin == hs-bin-1) { + expected[freq2chroma(infreq1) + 1] += 450; + } else { + if (infreq1 < cutoff) { + expected[0] += 200; + } else { + expected[freq2chroma(infreq1) + 1] += 200; + } + double infreq2 = (double(hs-bin-1) * rate) / sz; + if (infreq2 < cutoff) { + expected[0] += 50; + } else { + expected[freq2chroma(infreq2) + 1] += 50; + } + } + + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), + expected.begin(), expected.end()); + } + } + } +} + +BOOST_AUTO_TEST_CASE(nonchroma) +{ + int rate = 44100; + int sz = 2048; + int hs = sz / 2 + 1; + int fsz = 84; + + FeatureExtractor::Parameters params(float(rate), sz); + params.minFrequency = 0; + FeatureExtractor fe(params); + BOOST_CHECK_EQUAL(fe.getFeatureSize(), fsz); + + for (int bin = 0; bin < hs; ++bin) { + + vector<double> real, imag; + real.resize(hs, 0.0); + imag.resize(hs, 0.0); + + real[bin] += 10.0; + imag[bin] += 10.0; + + // use two input sweeps, so we can test that they are properly + // summed into the output bin + real[hs-bin-1] += 5.0; + imag[hs-bin-1] += 5.0; + + feature_t out = fe.process(real, imag); + + checkAlternateProcessType(fe, out, real, imag); + + // We expect to find all bins are 0 except for: + // + // * two bins of 200 and 50 respectively, if the two input + // bins are distinct and their output bins are also distinct + // + // * one bin of value 250 (= 10^2 + 5^2), if the two input + // bins are distinct but their output bins are not + // + // * one bin of value 450 (= 15^2 + 15^2), if the input bins + // are not distinct (the feature extractor sums energies + // rather than magnitudes so as to integrate energy for a + // partial in the face of spectral leakage) + // + // The first 34 input bins (i.e. up to and including bin 33, + // 733Hz, MIDI pitch 77.something) are mapped linearly, those + // above that and up to MIDI pitch 127 (12544Hz) are mapped + // logarithmically, remaining bins are all mapped into the + // final output bin. + // + // So MIDI pitches up to and including 77 are mapped linearly + // by frequency into 34 bins; those from 78-126 inclusive are + // mapped linearly by MIDI pitch into the next 49 bins; + // everything above goes into the last bin, for 84 bins total. + + feature_t expected(fsz); + + if (bin == hs-bin-1) { + expected[bin2warped(bin, rate, sz)] += 450; + } else { + expected[bin2warped(bin, rate, sz)] += 200; + expected[bin2warped(hs-bin-1, rate, sz)] += 50; + } + + BOOST_CHECK_EQUAL_COLLECTIONS(out.begin(), out.end(), + expected.begin(), expected.end()); + } +} + +BOOST_AUTO_TEST_SUITE_END()
--- a/test/expected.csv Fri Nov 14 10:24:13 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5369 +0,0 @@ -0.000000000,0.02 -0.000000000,0.04 -0.000000000,0.06 -0.000000000,0.08 -0.000000000,0.1 -0.000000000,0.12 -0.000000000,0.14 -0.000000000,0.16 -0.000000000,0.18 -0.000000000,0.2 -0.000000000,0.22 -0.000000000,0.24 -0.000000000,0.26 -0.000000000,0.28 -0.000000000,0.3 -0.000000000,0.32 -0.000000000,0.34 -0.000000000,0.36 -0.000000000,0.38 -0.000000000,0.4 -0.000000000,0.42 -0.000000000,0.44 -0.000000000,0.46 -0.000000000,0.48 -0.000000000,0.5 -0.000000000,0.52 -0.000000000,0.54 -0.000000000,0.56 -0.000000000,0.58 -0.000000000,0.6 -0.000000000,0.62 -0.000000000,0.64 -0.000000000,0.66 -0.000000000,0.68 -0.000000000,0.7 -0.000000000,0.72 -0.000000000,0.74 -0.000000000,0.76 -0.000000000,0.78 -0.000000000,0.8 -0.000000000,0.82 -0.000000000,0.84 -0.000000000,0.86 -0.000000000,0.88 -0.000000000,0.9 -0.000000000,0.92 -0.000000000,0.94 -0.000000000,0.96 -0.000000000,0.98 -0.000000000,1 -0.000000000,1.02 -0.000000000,1.04 -0.000000000,1.06 -0.000000000,1.08 -0.000000000,1.1 -0.000000000,1.12 -0.000000000,1.14 -0.000000000,1.16 -0.000000000,1.18 -0.000000000,1.2 -0.000000000,1.22 -0.000000000,1.24 -0.000000000,1.26 -0.000000000,1.28 -0.000000000,1.3 -0.000000000,1.32 -0.000000000,1.34 -0.000000000,1.36 -0.000000000,1.38 -0.000000000,1.4 -0.000000000,1.42 -0.000000000,1.44 -0.000000000,1.46 -0.000000000,1.48 -0.000000000,1.5 -0.000000000,1.52 -0.000000000,1.54 -0.000000000,1.56 -0.020000000,1.58 -0.040000000,1.6 -0.060000000,1.62 -0.080000000,1.64 -0.100000000,1.66 -0.120000000,1.68 -0.140000000,1.7 -0.160000000,1.72 -0.180000000,1.74 -0.200000000,1.76 -0.220000000,1.78 -0.240000000,1.8 -0.260000000,1.82 -0.280000000,1.84 -0.300000000,1.86 -0.320000000,1.88 -0.340000000,1.9 -0.360000000,1.92 -0.380000000,1.94 -0.400000000,1.96 -0.420000000,1.98 -0.440000000,2 -0.460000000,2.02 -0.480000000,2.04 -0.500000000,2.06 -0.520000000,2.08 -0.540000000,2.1 -0.560000000,2.12 -0.580000000,2.14 -0.600000000,2.16 -0.620000000,2.18 -0.640000000,2.2 -0.660000000,2.22 -0.680000000,2.24 -0.700000000,2.26 -0.720000000,2.28 -0.740000000,2.3 -0.760000000,2.32 -0.780000000,2.34 -0.800000000,2.36 -0.820000000,2.38 -0.840000000,2.4 -0.860000000,2.42 -0.880000000,2.44 -0.900000000,2.46 -0.920000000,2.48 -0.940000000,2.5 -0.960000000,2.52 -0.980000000,2.54 -1.000000000,2.56 -1.020000000,2.58 -1.040000000,2.6 -1.060000000,2.62 -1.080000000,2.64 -1.100000000,2.64 -1.120000000,2.64 -1.140000000,2.66 -1.160000000,2.68 -1.180000000,2.7 -1.200000000,2.72 -1.220000000,2.74 -1.240000000,2.76 -1.260000000,2.78 -1.280000000,2.8 -1.300000000,2.82 -1.320000000,2.84 -1.340000000,2.86 -1.360000000,2.88 -1.380000000,2.9 -1.400000000,2.92 -1.420000000,2.94 -1.440000000,2.96 -1.460000000,2.98 -1.480000000,3 -1.500000000,3.02 -1.520000000,3.04 -1.540000000,3.06 -1.560000000,3.08 -1.580000000,3.1 -1.600000000,3.12 -1.620000000,3.12 -1.640000000,3.12 -1.660000000,3.12 -1.680000000,3.12 -1.700000000,3.12 -1.720000000,3.12 -1.740000000,3.12 -1.760000000,3.12 -1.780000000,3.12 -1.800000000,3.12 -1.820000000,3.14 -1.840000000,3.16 -1.860000000,3.18 -1.880000000,3.2 -1.900000000,3.22 -1.920000000,3.24 -1.940000000,3.26 -1.960000000,3.28 -1.980000000,3.3 -2.000000000,3.32 -2.020000000,3.34 -2.040000000,3.36 -2.060000000,3.38 -2.080000000,3.4 -2.100000000,3.42 -2.120000000,3.44 -2.140000000,3.46 -2.160000000,3.48 -2.180000000,3.5 -2.200000000,3.52 -2.220000000,3.54 -2.240000000,3.56 -2.260000000,3.58 -2.280000000,3.6 -2.300000000,3.62 -2.320000000,3.64 -2.340000000,3.66 -2.360000000,3.68 -2.380000000,3.7 -2.400000000,3.72 -2.420000000,3.74 -2.440000000,3.76 -2.460000000,3.78 -2.480000000,3.8 -2.500000000,3.82 -2.520000000,3.84 -2.540000000,3.86 -2.560000000,3.88 -2.580000000,3.88 -2.600000000,3.88 -2.620000000,3.88 -2.640000000,3.88 -2.660000000,3.88 -2.680000000,3.88 -2.700000000,3.88 -2.720000000,3.88 -2.740000000,3.88 -2.760000000,3.88 -2.780000000,3.88 -2.800000000,3.9 -2.820000000,3.92 -2.840000000,3.94 -2.860000000,3.96 -2.880000000,3.98 -2.900000000,4 -2.920000000,4.02 -2.940000000,4.04 -2.960000000,4.06 -2.980000000,4.08 -3.000000000,4.1 -3.020000000,4.12 -3.040000000,4.14 -3.060000000,4.16 -3.080000000,4.18 -3.100000000,4.2 -3.120000000,4.22 -3.140000000,4.24 -3.160000000,4.26 -3.180000000,4.28 -3.200000000,4.3 -3.220000000,4.32 -3.240000000,4.34 -3.260000000,4.36 -3.280000000,4.38 -3.300000000,4.4 -3.320000000,4.42 -3.340000000,4.44 -3.360000000,4.46 -3.380000000,4.48 -3.400000000,4.5 -3.420000000,4.52 -3.440000000,4.54 -3.460000000,4.56 -3.480000000,4.58 -3.500000000,4.6 -3.520000000,4.62 -3.540000000,4.62 -3.560000000,4.62 -3.580000000,4.62 -3.600000000,4.64 -3.620000000,4.66 -3.640000000,4.68 -3.660000000,4.7 -3.680000000,4.72 -3.700000000,4.74 -3.720000000,4.76 -3.740000000,4.78 -3.760000000,4.8 -3.780000000,4.82 -3.800000000,4.84 -3.820000000,4.86 -3.840000000,4.88 -3.860000000,4.9 -3.880000000,4.9 -3.900000000,4.92 -3.920000000,4.92 -3.940000000,4.92 -3.960000000,4.92 -3.980000000,4.92 -4.000000000,4.92 -4.020000000,4.92 -4.040000000,4.92 -4.060000000,4.92 -4.080000000,4.92 -4.100000000,4.92 -4.120000000,4.92 -4.140000000,4.92 -4.160000000,4.92 -4.180000000,4.92 -4.200000000,4.92 -4.220000000,4.94 -4.240000000,4.96 -4.260000000,4.98 -4.280000000,5 -4.300000000,5.02 -4.320000000,5.04 -4.340000000,5.06 -4.360000000,5.08 -4.380000000,5.1 -4.400000000,5.1 -4.420000000,5.1 -4.440000000,5.12 -4.460000000,5.14 -4.480000000,5.16 -4.500000000,5.18 -4.520000000,5.2 -4.540000000,5.22 -4.560000000,5.24 -4.580000000,5.26 -4.600000000,5.28 -4.620000000,5.3 -4.640000000,5.32 -4.660000000,5.32 -4.680000000,5.32 -4.700000000,5.32 -4.720000000,5.32 -4.740000000,5.34 -4.760000000,5.36 -4.780000000,5.36 -4.800000000,5.36 -4.820000000,5.36 -4.840000000,5.36 -4.860000000,5.38 -4.880000000,5.4 -4.900000000,5.4 -4.920000000,5.42 -4.940000000,5.44 -4.960000000,5.46 -4.980000000,5.48 -5.000000000,5.5 -5.020000000,5.52 -5.040000000,5.54 -5.060000000,5.56 -5.080000000,5.56 -5.100000000,5.58 -5.120000000,5.58 -5.140000000,5.58 -5.160000000,5.6 -5.180000000,5.62 -5.200000000,5.64 -5.220000000,5.66 -5.240000000,5.68 -5.260000000,5.7 -5.280000000,5.72 -5.300000000,5.74 -5.320000000,5.76 -5.340000000,5.78 -5.360000000,5.78 -5.380000000,5.8 -5.400000000,5.82 -5.420000000,5.82 -5.440000000,5.82 -5.460000000,5.82 -5.480000000,5.82 -5.500000000,5.82 -5.520000000,5.84 -5.540000000,5.86 -5.560000000,5.88 -5.580000000,5.9 -5.600000000,5.92 -5.620000000,5.94 -5.640000000,5.96 -5.660000000,5.98 -5.680000000,6 -5.700000000,6.02 -5.720000000,6.04 -5.740000000,6.06 -5.760000000,6.08 -5.780000000,6.1 -5.800000000,6.12 -5.820000000,6.12 -5.840000000,6.12 -5.860000000,6.12 -5.880000000,6.14 -5.900000000,6.16 -5.920000000,6.18 -5.940000000,6.2 -5.960000000,6.22 -5.980000000,6.24 -6.000000000,6.26 -6.020000000,6.28 -6.040000000,6.3 -6.060000000,6.32 -6.080000000,6.34 -6.100000000,6.36 -6.120000000,6.38 -6.140000000,6.4 -6.160000000,6.42 -6.180000000,6.44 -6.200000000,6.46 -6.220000000,6.48 -6.240000000,6.5 -6.260000000,6.52 -6.280000000,6.54 -6.300000000,6.56 -6.320000000,6.58 -6.340000000,6.6 -6.360000000,6.62 -6.380000000,6.64 -6.400000000,6.66 -6.420000000,6.68 -6.440000000,6.7 -6.460000000,6.72 -6.480000000,6.74 -6.500000000,6.76 -6.520000000,6.78 -6.540000000,6.8 -6.560000000,6.82 -6.580000000,6.84 -6.600000000,6.86 -6.620000000,6.88 -6.640000000,6.9 -6.660000000,6.92 -6.680000000,6.94 -6.700000000,6.96 -6.720000000,6.98 -6.740000000,7 -6.760000000,7.02 -6.780000000,7.04 -6.800000000,7.06 -6.820000000,7.08 -6.840000000,7.1 -6.860000000,7.12 -6.880000000,7.14 -6.900000000,7.16 -6.920000000,7.18 -6.940000000,7.2 -6.960000000,7.22 -6.980000000,7.24 -7.000000000,7.26 -7.020000000,7.28 -7.040000000,7.3 -7.060000000,7.32 -7.080000000,7.34 -7.100000000,7.36 -7.120000000,7.38 -7.140000000,7.4 -7.160000000,7.42 -7.180000000,7.44 -7.200000000,7.46 -7.220000000,7.48 -7.240000000,7.5 -7.260000000,7.52 -7.280000000,7.54 -7.300000000,7.56 -7.320000000,7.58 -7.340000000,7.6 -7.360000000,7.62 -7.380000000,7.64 -7.400000000,7.66 -7.420000000,7.68 -7.440000000,7.7 -7.460000000,7.72 -7.480000000,7.74 -7.500000000,7.76 -7.520000000,7.78 -7.540000000,7.8 -7.560000000,7.82 -7.580000000,7.82 -7.600000000,7.82 -7.620000000,7.82 -7.640000000,7.82 -7.660000000,7.82 -7.680000000,7.82 -7.700000000,7.82 -7.720000000,7.82 -7.740000000,7.82 -7.760000000,7.82 -7.780000000,7.82 -7.800000000,7.82 -7.820000000,7.82 -7.840000000,7.82 -7.860000000,7.82 -7.880000000,7.82 -7.900000000,7.82 -7.920000000,7.82 -7.940000000,7.82 -7.960000000,7.82 -7.980000000,7.82 -8.000000000,7.84 -8.020000000,7.84 -8.040000000,7.84 -8.060000000,7.84 -8.080000000,7.84 -8.100000000,7.84 -8.120000000,7.84 -8.140000000,7.84 -8.160000000,7.84 -8.180000000,7.84 -8.200000000,7.86 -8.220000000,7.88 -8.240000000,7.9 -8.260000000,7.92 -8.280000000,7.94 -8.300000000,7.96 -8.320000000,7.98 -8.340000000,7.98 -8.360000000,7.98 -8.380000000,7.98 -8.400000000,7.98 -8.420000000,8 -8.440000000,8.02 -8.460000000,8.04 -8.480000000,8.06 -8.500000000,8.08 -8.520000000,8.1 -8.540000000,8.12 -8.560000000,8.14 -8.580000000,8.16 -8.600000000,8.18 -8.620000000,8.2 -8.640000000,8.2 -8.660000000,8.2 -8.680000000,8.2 -8.700000000,8.2 -8.720000000,8.2 -8.740000000,8.2 -8.760000000,8.22 -8.780000000,8.24 -8.800000000,8.26 -8.820000000,8.26 -8.840000000,8.26 -8.860000000,8.28 -8.880000000,8.28 -8.900000000,8.28 -8.920000000,8.3 -8.940000000,8.3 -8.960000000,8.32 -8.980000000,8.34 -9.000000000,8.36 -9.020000000,8.36 -9.040000000,8.36 -9.060000000,8.36 -9.080000000,8.36 -9.100000000,8.36 -9.120000000,8.36 -9.140000000,8.36 -9.160000000,8.36 -9.180000000,8.36 -9.200000000,8.36 -9.220000000,8.36 -9.240000000,8.36 -9.260000000,8.36 -9.280000000,8.36 -9.300000000,8.36 -9.320000000,8.36 -9.340000000,8.36 -9.360000000,8.36 -9.380000000,8.36 -9.400000000,8.36 -9.420000000,8.36 -9.440000000,8.36 -9.460000000,8.36 -9.480000000,8.36 -9.500000000,8.36 -9.520000000,8.36 -9.540000000,8.36 -9.560000000,8.36 -9.580000000,8.36 -9.600000000,8.36 -9.620000000,8.36 -9.640000000,8.36 -9.660000000,8.36 -9.680000000,8.36 -9.700000000,8.36 -9.720000000,8.36 -9.740000000,8.36 -9.760000000,8.36 -9.780000000,8.36 -9.800000000,8.36 -9.820000000,8.36 -9.840000000,8.36 -9.860000000,8.36 -9.880000000,8.36 -9.900000000,8.36 -9.920000000,8.36 -9.940000000,8.36 -9.960000000,8.36 -9.980000000,8.36 -10.000000000,8.36 -10.020000000,8.36 -10.040000000,8.36 -10.060000000,8.36 -10.080000000,8.36 -10.100000000,8.36 -10.120000000,8.36 -10.140000000,8.36 -10.160000000,8.36 -10.180000000,8.36 -10.200000000,8.36 -10.220000000,8.36 -10.240000000,8.36 -10.260000000,8.36 -10.280000000,8.38 -10.300000000,8.4 -10.320000000,8.42 -10.340000000,8.44 -10.360000000,8.46 -10.380000000,8.48 -10.400000000,8.5 -10.420000000,8.52 -10.440000000,8.54 -10.460000000,8.54 -10.480000000,8.56 -10.500000000,8.56 -10.520000000,8.56 -10.540000000,8.56 -10.560000000,8.56 -10.580000000,8.56 -10.600000000,8.56 -10.620000000,8.56 -10.640000000,8.58 -10.660000000,8.6 -10.680000000,8.6 -10.700000000,8.62 -10.720000000,8.62 -10.740000000,8.62 -10.760000000,8.64 -10.780000000,8.66 -10.800000000,8.68 -10.820000000,8.7 -10.840000000,8.7 -10.860000000,8.7 -10.880000000,8.72 -10.900000000,8.74 -10.920000000,8.76 -10.940000000,8.76 -10.960000000,8.76 -10.980000000,8.78 -11.000000000,8.78 -11.020000000,8.78 -11.040000000,8.8 -11.060000000,8.8 -11.080000000,8.82 -11.100000000,8.82 -11.120000000,8.82 -11.140000000,8.82 -11.160000000,8.82 -11.180000000,8.82 -11.200000000,8.82 -11.220000000,8.82 -11.240000000,8.82 -11.260000000,8.82 -11.280000000,8.82 -11.300000000,8.82 -11.320000000,8.82 -11.340000000,8.82 -11.360000000,8.82 -11.380000000,8.82 -11.400000000,8.82 -11.420000000,8.82 -11.440000000,8.84 -11.460000000,8.84 -11.480000000,8.84 -11.500000000,8.84 -11.520000000,8.84 -11.540000000,8.84 -11.560000000,8.84 -11.580000000,8.84 -11.600000000,8.84 -11.620000000,8.84 -11.640000000,8.86 -11.660000000,8.86 -11.680000000,8.86 -11.700000000,8.88 -11.720000000,8.88 -11.740000000,8.88 -11.760000000,8.88 -11.780000000,8.88 -11.800000000,8.88 -11.820000000,8.88 -11.840000000,8.88 -11.860000000,8.88 -11.880000000,8.88 -11.900000000,8.88 -11.920000000,8.88 -11.940000000,8.88 -11.960000000,8.88 -11.980000000,8.88 -12.000000000,8.88 -12.020000000,8.88 -12.040000000,8.88 -12.060000000,8.88 -12.080000000,8.88 -12.100000000,8.88 -12.120000000,8.88 -12.140000000,8.88 -12.160000000,8.88 -12.180000000,8.88 -12.200000000,8.88 -12.220000000,8.88 -12.240000000,8.88 -12.260000000,8.88 -12.280000000,8.88 -12.300000000,8.88 -12.320000000,8.88 -12.340000000,8.88 -12.360000000,8.88 -12.380000000,8.88 -12.400000000,8.88 -12.420000000,8.88 -12.440000000,8.88 -12.460000000,8.88 -12.480000000,8.88 -12.500000000,8.88 -12.520000000,8.88 -12.540000000,8.9 -12.560000000,8.92 -12.580000000,8.94 -12.600000000,8.96 -12.620000000,8.98 -12.640000000,8.98 -12.660000000,9 -12.680000000,9 -12.700000000,9 -12.720000000,9 -12.740000000,9 -12.760000000,9 -12.780000000,9 -12.800000000,9 -12.820000000,9 -12.840000000,9 -12.860000000,9 -12.880000000,9 -12.900000000,9.02 -12.920000000,9.04 -12.940000000,9.06 -12.960000000,9.08 -12.980000000,9.1 -13.000000000,9.12 -13.020000000,9.14 -13.040000000,9.16 -13.060000000,9.18 -13.080000000,9.2 -13.100000000,9.22 -13.120000000,9.24 -13.140000000,9.26 -13.160000000,9.28 -13.180000000,9.3 -13.200000000,9.3 -13.220000000,9.32 -13.240000000,9.34 -13.260000000,9.36 -13.280000000,9.38 -13.300000000,9.38 -13.320000000,9.38 -13.340000000,9.38 -13.360000000,9.4 -13.380000000,9.42 -13.400000000,9.44 -13.420000000,9.46 -13.440000000,9.48 -13.460000000,9.5 -13.480000000,9.52 -13.500000000,9.52 -13.520000000,9.54 -13.540000000,9.56 -13.560000000,9.58 -13.580000000,9.58 -13.600000000,9.58 -13.620000000,9.58 -13.640000000,9.58 -13.660000000,9.58 -13.680000000,9.58 -13.700000000,9.58 -13.720000000,9.58 -13.740000000,9.6 -13.760000000,9.62 -13.780000000,9.62 -13.800000000,9.62 -13.820000000,9.64 -13.840000000,9.66 -13.860000000,9.68 -13.880000000,9.68 -13.900000000,9.68 -13.920000000,9.68 -13.940000000,9.68 -13.960000000,9.68 -13.980000000,9.68 -14.000000000,9.68 -14.020000000,9.68 -14.040000000,9.68 -14.060000000,9.7 -14.080000000,9.72 -14.100000000,9.74 -14.120000000,9.74 -14.140000000,9.74 -14.160000000,9.74 -14.180000000,9.74 -14.200000000,9.74 -14.220000000,9.74 -14.240000000,9.76 -14.260000000,9.76 -14.280000000,9.76 -14.300000000,9.78 -14.320000000,9.8 -14.340000000,9.8 -14.360000000,9.8 -14.380000000,9.82 -14.400000000,9.84 -14.420000000,9.84 -14.440000000,9.84 -14.460000000,9.84 -14.480000000,9.84 -14.500000000,9.84 -14.520000000,9.84 -14.540000000,9.84 -14.560000000,9.84 -14.580000000,9.84 -14.600000000,9.84 -14.620000000,9.84 -14.640000000,9.84 -14.660000000,9.84 -14.680000000,9.84 -14.700000000,9.84 -14.720000000,9.84 -14.740000000,9.84 -14.760000000,9.84 -14.780000000,9.84 -14.800000000,9.84 -14.820000000,9.84 -14.840000000,9.86 -14.860000000,9.86 -14.880000000,9.86 -14.900000000,9.86 -14.920000000,9.86 -14.940000000,9.86 -14.960000000,9.86 -14.980000000,9.86 -15.000000000,9.86 -15.020000000,9.86 -15.040000000,9.86 -15.060000000,9.86 -15.080000000,9.86 -15.100000000,9.88 -15.120000000,9.88 -15.140000000,9.88 -15.160000000,9.88 -15.180000000,9.88 -15.200000000,9.88 -15.220000000,9.88 -15.240000000,9.9 -15.260000000,9.92 -15.280000000,9.92 -15.300000000,9.92 -15.320000000,9.92 -15.340000000,9.94 -15.360000000,9.96 -15.380000000,9.98 -15.400000000,10 -15.420000000,10.02 -15.440000000,10.04 -15.460000000,10.04 -15.480000000,10.04 -15.500000000,10.04 -15.520000000,10.04 -15.540000000,10.04 -15.560000000,10.04 -15.580000000,10.04 -15.600000000,10.04 -15.620000000,10.04 -15.640000000,10.04 -15.660000000,10.04 -15.680000000,10.04 -15.700000000,10.04 -15.720000000,10.04 -15.740000000,10.04 -15.760000000,10.04 -15.780000000,10.04 -15.800000000,10.04 -15.820000000,10.04 -15.840000000,10.04 -15.860000000,10.04 -15.880000000,10.06 -15.900000000,10.08 -15.920000000,10.1 -15.940000000,10.12 -15.960000000,10.14 -15.980000000,10.16 -16.000000000,10.18 -16.020000000,10.2 -16.040000000,10.22 -16.060000000,10.24 -16.080000000,10.26 -16.100000000,10.28 -16.120000000,10.3 -16.140000000,10.32 -16.160000000,10.34 -16.180000000,10.34 -16.200000000,10.36 -16.220000000,10.38 -16.240000000,10.4 -16.260000000,10.42 -16.280000000,10.44 -16.300000000,10.46 -16.320000000,10.46 -16.340000000,10.46 -16.360000000,10.46 -16.380000000,10.46 -16.400000000,10.46 -16.420000000,10.46 -16.440000000,10.46 -16.460000000,10.46 -16.480000000,10.46 -16.500000000,10.46 -16.520000000,10.46 -16.540000000,10.46 -16.560000000,10.48 -16.580000000,10.5 -16.600000000,10.52 -16.620000000,10.54 -16.640000000,10.56 -16.660000000,10.58 -16.680000000,10.6 -16.700000000,10.62 -16.720000000,10.64 -16.740000000,10.66 -16.760000000,10.66 -16.780000000,10.68 -16.800000000,10.68 -16.820000000,10.7 -16.840000000,10.7 -16.860000000,10.7 -16.880000000,10.7 -16.900000000,10.7 -16.920000000,10.7 -16.940000000,10.7 -16.960000000,10.7 -16.980000000,10.7 -17.000000000,10.7 -17.020000000,10.7 -17.040000000,10.7 -17.060000000,10.7 -17.080000000,10.7 -17.100000000,10.7 -17.120000000,10.7 -17.140000000,10.7 -17.160000000,10.72 -17.180000000,10.74 -17.200000000,10.76 -17.220000000,10.76 -17.240000000,10.76 -17.260000000,10.78 -17.280000000,10.8 -17.300000000,10.82 -17.320000000,10.84 -17.340000000,10.86 -17.360000000,10.88 -17.380000000,10.9 -17.400000000,10.92 -17.420000000,10.94 -17.440000000,10.96 -17.460000000,10.98 -17.480000000,11 -17.500000000,11.02 -17.520000000,11.02 -17.540000000,11.02 -17.560000000,11.02 -17.580000000,11.02 -17.600000000,11.02 -17.620000000,11.02 -17.640000000,11.02 -17.660000000,11.02 -17.680000000,11.02 -17.700000000,11.02 -17.720000000,11.02 -17.740000000,11.04 -17.760000000,11.06 -17.780000000,11.08 -17.800000000,11.08 -17.820000000,11.1 -17.840000000,11.12 -17.860000000,11.12 -17.880000000,11.12 -17.900000000,11.14 -17.920000000,11.16 -17.940000000,11.18 -17.960000000,11.2 -17.980000000,11.22 -18.000000000,11.24 -18.020000000,11.26 -18.040000000,11.28 -18.060000000,11.3 -18.080000000,11.32 -18.100000000,11.34 -18.120000000,11.36 -18.140000000,11.38 -18.160000000,11.4 -18.180000000,11.42 -18.200000000,11.44 -18.220000000,11.46 -18.240000000,11.48 -18.260000000,11.5 -18.280000000,11.52 -18.300000000,11.54 -18.320000000,11.56 -18.340000000,11.58 -18.360000000,11.58 -18.380000000,11.58 -18.400000000,11.58 -18.420000000,11.58 -18.440000000,11.58 -18.460000000,11.58 -18.480000000,11.6 -18.500000000,11.62 -18.520000000,11.64 -18.540000000,11.66 -18.560000000,11.68 -18.580000000,11.68 -18.600000000,11.7 -18.620000000,11.7 -18.640000000,11.7 -18.660000000,11.72 -18.680000000,11.72 -18.700000000,11.72 -18.720000000,11.72 -18.740000000,11.74 -18.760000000,11.74 -18.780000000,11.74 -18.800000000,11.76 -18.820000000,11.78 -18.840000000,11.8 -18.860000000,11.8 -18.880000000,11.82 -18.900000000,11.82 -18.920000000,11.82 -18.940000000,11.82 -18.960000000,11.84 -18.980000000,11.84 -19.000000000,11.84 -19.020000000,11.84 -19.040000000,11.84 -19.060000000,11.86 -19.080000000,11.88 -19.100000000,11.9 -19.120000000,11.92 -19.140000000,11.94 -19.160000000,11.96 -19.180000000,11.98 -19.200000000,12 -19.220000000,12.02 -19.240000000,12.04 -19.260000000,12.06 -19.280000000,12.08 -19.300000000,12.1 -19.320000000,12.12 -19.340000000,12.14 -19.360000000,12.16 -19.380000000,12.16 -19.400000000,12.18 -19.420000000,12.18 -19.440000000,12.2 -19.460000000,12.22 -19.480000000,12.24 -19.500000000,12.24 -19.520000000,12.24 -19.540000000,12.24 -19.560000000,12.26 -19.580000000,12.28 -19.600000000,12.3 -19.620000000,12.32 -19.640000000,12.34 -19.660000000,12.34 -19.680000000,12.36 -19.700000000,12.36 -19.720000000,12.36 -19.740000000,12.36 -19.760000000,12.36 -19.780000000,12.36 -19.800000000,12.36 -19.820000000,12.38 -19.840000000,12.4 -19.860000000,12.4 -19.880000000,12.42 -19.900000000,12.44 -19.920000000,12.46 -19.940000000,12.46 -19.960000000,12.48 -19.980000000,12.5 -20.000000000,12.5 -20.020000000,12.5 -20.040000000,12.5 -20.060000000,12.5 -20.080000000,12.52 -20.100000000,12.54 -20.120000000,12.56 -20.140000000,12.58 -20.160000000,12.6 -20.180000000,12.6 -20.200000000,12.62 -20.220000000,12.62 -20.240000000,12.64 -20.260000000,12.66 -20.280000000,12.68 -20.300000000,12.7 -20.320000000,12.72 -20.340000000,12.74 -20.360000000,12.74 -20.380000000,12.74 -20.400000000,12.74 -20.420000000,12.74 -20.440000000,12.74 -20.460000000,12.74 -20.480000000,12.74 -20.500000000,12.74 -20.520000000,12.74 -20.540000000,12.74 -20.560000000,12.74 -20.580000000,12.74 -20.600000000,12.74 -20.620000000,12.74 -20.640000000,12.74 -20.660000000,12.76 -20.680000000,12.78 -20.700000000,12.8 -20.720000000,12.82 -20.740000000,12.84 -20.760000000,12.86 -20.780000000,12.86 -20.800000000,12.86 -20.820000000,12.86 -20.840000000,12.86 -20.860000000,12.86 -20.880000000,12.86 -20.900000000,12.86 -20.920000000,12.86 -20.940000000,12.86 -20.960000000,12.86 -20.980000000,12.86 -21.000000000,12.86 -21.020000000,12.86 -21.040000000,12.86 -21.060000000,12.86 -21.080000000,12.86 -21.100000000,12.86 -21.120000000,12.86 -21.140000000,12.86 -21.160000000,12.86 -21.180000000,12.86 -21.200000000,12.86 -21.220000000,12.86 -21.240000000,12.86 -21.260000000,12.86 -21.280000000,12.86 -21.300000000,12.86 -21.320000000,12.86 -21.340000000,12.86 -21.360000000,12.86 -21.380000000,12.86 -21.400000000,12.88 -21.420000000,12.9 -21.440000000,12.92 -21.460000000,12.94 -21.480000000,12.96 -21.500000000,12.98 -21.520000000,13 -21.540000000,13 -21.560000000,13 -21.580000000,13.02 -21.600000000,13.02 -21.620000000,13.04 -21.640000000,13.04 -21.660000000,13.06 -21.680000000,13.06 -21.700000000,13.06 -21.720000000,13.06 -21.740000000,13.06 -21.760000000,13.08 -21.780000000,13.08 -21.800000000,13.08 -21.820000000,13.08 -21.840000000,13.08 -21.860000000,13.08 -21.880000000,13.08 -21.900000000,13.1 -21.920000000,13.12 -21.940000000,13.14 -21.960000000,13.16 -21.980000000,13.18 -22.000000000,13.2 -22.020000000,13.22 -22.040000000,13.24 -22.060000000,13.26 -22.080000000,13.28 -22.100000000,13.3 -22.120000000,13.32 -22.140000000,13.34 -22.160000000,13.36 -22.180000000,13.36 -22.200000000,13.36 -22.220000000,13.36 -22.240000000,13.36 -22.260000000,13.36 -22.280000000,13.36 -22.300000000,13.36 -22.320000000,13.36 -22.340000000,13.36 -22.360000000,13.36 -22.380000000,13.36 -22.400000000,13.36 -22.420000000,13.36 -22.440000000,13.36 -22.460000000,13.36 -22.480000000,13.36 -22.500000000,13.38 -22.520000000,13.4 -22.540000000,13.42 -22.560000000,13.44 -22.580000000,13.46 -22.600000000,13.48 -22.620000000,13.5 -22.640000000,13.52 -22.660000000,13.54 -22.680000000,13.56 -22.700000000,13.56 -22.720000000,13.58 -22.740000000,13.6 -22.760000000,13.62 -22.780000000,13.64 -22.800000000,13.66 -22.820000000,13.68 -22.840000000,13.7 -22.860000000,13.7 -22.880000000,13.7 -22.900000000,13.72 -22.920000000,13.74 -22.940000000,13.76 -22.960000000,13.78 -22.980000000,13.78 -23.000000000,13.78 -23.020000000,13.8 -23.040000000,13.8 -23.060000000,13.8 -23.080000000,13.82 -23.100000000,13.82 -23.120000000,13.82 -23.140000000,13.84 -23.160000000,13.86 -23.180000000,13.88 -23.200000000,13.9 -23.220000000,13.92 -23.240000000,13.94 -23.260000000,13.96 -23.280000000,13.98 -23.300000000,14 -23.320000000,14 -23.340000000,14.02 -23.360000000,14.02 -23.380000000,14.02 -23.400000000,14.04 -23.420000000,14.06 -23.440000000,14.08 -23.460000000,14.1 -23.480000000,14.12 -23.500000000,14.14 -23.520000000,14.16 -23.540000000,14.16 -23.560000000,14.18 -23.580000000,14.18 -23.600000000,14.18 -23.620000000,14.18 -23.640000000,14.18 -23.660000000,14.18 -23.680000000,14.2 -23.700000000,14.22 -23.720000000,14.24 -23.740000000,14.26 -23.760000000,14.28 -23.780000000,14.3 -23.800000000,14.3 -23.820000000,14.3 -23.840000000,14.32 -23.860000000,14.34 -23.880000000,14.34 -23.900000000,14.34 -23.920000000,14.36 -23.940000000,14.38 -23.960000000,14.4 -23.980000000,14.42 -24.000000000,14.44 -24.020000000,14.46 -24.040000000,14.48 -24.060000000,14.5 -24.080000000,14.52 -24.100000000,14.54 -24.120000000,14.56 -24.140000000,14.56 -24.160000000,14.56 -24.180000000,14.58 -24.200000000,14.6 -24.220000000,14.62 -24.240000000,14.64 -24.260000000,14.66 -24.280000000,14.68 -24.300000000,14.7 -24.320000000,14.72 -24.340000000,14.74 -24.360000000,14.76 -24.380000000,14.76 -24.400000000,14.76 -24.420000000,14.76 -24.440000000,14.76 -24.460000000,14.76 -24.480000000,14.76 -24.500000000,14.76 -24.520000000,14.76 -24.540000000,14.76 -24.560000000,14.76 -24.580000000,14.76 -24.600000000,14.76 -24.620000000,14.76 -24.640000000,14.76 -24.660000000,14.76 -24.680000000,14.76 -24.700000000,14.76 -24.720000000,14.76 -24.740000000,14.76 -24.760000000,14.76 -24.780000000,14.76 -24.800000000,14.76 -24.820000000,14.76 -24.840000000,14.78 -24.860000000,14.8 -24.880000000,14.82 -24.900000000,14.84 -24.920000000,14.86 -24.940000000,14.88 -24.960000000,14.9 -24.980000000,14.92 -25.000000000,14.94 -25.020000000,14.94 -25.040000000,14.94 -25.060000000,14.96 -25.080000000,14.96 -25.100000000,14.96 -25.120000000,14.96 -25.140000000,14.96 -25.160000000,14.96 -25.180000000,14.98 -25.200000000,15 -25.220000000,15.02 -25.240000000,15.04 -25.260000000,15.06 -25.280000000,15.08 -25.300000000,15.1 -25.320000000,15.12 -25.340000000,15.14 -25.360000000,15.16 -25.380000000,15.16 -25.400000000,15.16 -25.420000000,15.16 -25.440000000,15.16 -25.460000000,15.16 -25.480000000,15.16 -25.500000000,15.18 -25.520000000,15.2 -25.540000000,15.22 -25.560000000,15.24 -25.580000000,15.26 -25.600000000,15.26 -25.620000000,15.28 -25.640000000,15.3 -25.660000000,15.32 -25.680000000,15.34 -25.700000000,15.36 -25.720000000,15.38 -25.740000000,15.4 -25.760000000,15.42 -25.780000000,15.44 -25.800000000,15.46 -25.820000000,15.48 -25.840000000,15.5 -25.860000000,15.5 -25.880000000,15.5 -25.900000000,15.5 -25.920000000,15.5 -25.940000000,15.5 -25.960000000,15.5 -25.980000000,15.5 -26.000000000,15.5 -26.020000000,15.5 -26.040000000,15.5 -26.060000000,15.5 -26.080000000,15.5 -26.100000000,15.5 -26.120000000,15.5 -26.140000000,15.5 -26.160000000,15.52 -26.180000000,15.54 -26.200000000,15.56 -26.220000000,15.58 -26.240000000,15.58 -26.260000000,15.6 -26.280000000,15.6 -26.300000000,15.62 -26.320000000,15.64 -26.340000000,15.66 -26.360000000,15.68 -26.380000000,15.7 -26.400000000,15.72 -26.420000000,15.74 -26.440000000,15.76 -26.460000000,15.78 -26.480000000,15.8 -26.500000000,15.8 -26.520000000,15.82 -26.540000000,15.84 -26.560000000,15.84 -26.580000000,15.84 -26.600000000,15.84 -26.620000000,15.84 -26.640000000,15.86 -26.660000000,15.88 -26.680000000,15.9 -26.700000000,15.92 -26.720000000,15.94 -26.740000000,15.96 -26.760000000,15.96 -26.780000000,15.96 -26.800000000,15.96 -26.820000000,15.98 -26.840000000,16 -26.860000000,16.02 -26.880000000,16.04 -26.900000000,16.06 -26.920000000,16.08 -26.940000000,16.1 -26.960000000,16.12 -26.980000000,16.14 -27.000000000,16.16 -27.020000000,16.18 -27.040000000,16.2 -27.060000000,16.2 -27.080000000,16.2 -27.100000000,16.2 -27.120000000,16.2 -27.140000000,16.2 -27.160000000,16.2 -27.180000000,16.2 -27.200000000,16.2 -27.220000000,16.2 -27.240000000,16.2 -27.260000000,16.2 -27.280000000,16.2 -27.300000000,16.2 -27.320000000,16.2 -27.340000000,16.2 -27.360000000,16.22 -27.380000000,16.24 -27.400000000,16.26 -27.420000000,16.28 -27.440000000,16.3 -27.460000000,16.32 -27.480000000,16.34 -27.500000000,16.36 -27.520000000,16.38 -27.540000000,16.4 -27.560000000,16.42 -27.580000000,16.44 -27.600000000,16.46 -27.620000000,16.48 -27.640000000,16.5 -27.660000000,16.52 -27.680000000,16.54 -27.700000000,16.56 -27.720000000,16.58 -27.740000000,16.6 -27.760000000,16.62 -27.780000000,16.64 -27.800000000,16.66 -27.820000000,16.68 -27.840000000,16.7 -27.860000000,16.72 -27.880000000,16.74 -27.900000000,16.76 -27.920000000,16.76 -27.940000000,16.76 -27.960000000,16.78 -27.980000000,16.8 -28.000000000,16.82 -28.020000000,16.84 -28.040000000,16.86 -28.060000000,16.88 -28.080000000,16.9 -28.100000000,16.92 -28.120000000,16.94 -28.140000000,16.94 -28.160000000,16.96 -28.180000000,16.96 -28.200000000,16.96 -28.220000000,16.96 -28.240000000,16.96 -28.260000000,16.96 -28.280000000,16.98 -28.300000000,16.98 -28.320000000,16.98 -28.340000000,16.98 -28.360000000,16.98 -28.380000000,16.98 -28.400000000,16.98 -28.420000000,16.98 -28.440000000,16.98 -28.460000000,16.98 -28.480000000,16.98 -28.500000000,17 -28.520000000,17.02 -28.540000000,17.04 -28.560000000,17.06 -28.580000000,17.08 -28.600000000,17.1 -28.620000000,17.12 -28.640000000,17.12 -28.660000000,17.12 -28.680000000,17.12 -28.700000000,17.12 -28.720000000,17.12 -28.740000000,17.12 -28.760000000,17.12 -28.780000000,17.12 -28.800000000,17.12 -28.820000000,17.14 -28.840000000,17.16 -28.860000000,17.18 -28.880000000,17.2 -28.900000000,17.22 -28.920000000,17.24 -28.940000000,17.26 -28.960000000,17.28 -28.980000000,17.3 -29.000000000,17.32 -29.020000000,17.34 -29.040000000,17.36 -29.060000000,17.38 -29.080000000,17.4 -29.100000000,17.42 -29.120000000,17.44 -29.140000000,17.46 -29.160000000,17.48 -29.180000000,17.5 -29.200000000,17.52 -29.220000000,17.54 -29.240000000,17.56 -29.260000000,17.58 -29.280000000,17.6 -29.300000000,17.62 -29.320000000,17.64 -29.340000000,17.66 -29.360000000,17.68 -29.380000000,17.7 -29.400000000,17.72 -29.420000000,17.74 -29.440000000,17.76 -29.460000000,17.78 -29.480000000,17.8 -29.500000000,17.82 -29.520000000,17.84 -29.540000000,17.86 -29.560000000,17.86 -29.580000000,17.86 -29.600000000,17.86 -29.620000000,17.86 -29.640000000,17.86 -29.660000000,17.86 -29.680000000,17.86 -29.700000000,17.86 -29.720000000,17.88 -29.740000000,17.9 -29.760000000,17.92 -29.780000000,17.94 -29.800000000,17.96 -29.820000000,17.98 -29.840000000,18 -29.860000000,18.02 -29.880000000,18.04 -29.900000000,18.06 -29.920000000,18.08 -29.940000000,18.1 -29.960000000,18.12 -29.980000000,18.14 -30.000000000,18.16 -30.020000000,18.18 -30.040000000,18.2 -30.060000000,18.22 -30.080000000,18.24 -30.100000000,18.26 -30.120000000,18.28 -30.140000000,18.3 -30.160000000,18.32 -30.180000000,18.34 -30.200000000,18.36 -30.220000000,18.38 -30.240000000,18.4 -30.260000000,18.42 -30.280000000,18.44 -30.300000000,18.46 -30.320000000,18.48 -30.340000000,18.5 -30.360000000,18.52 -30.380000000,18.54 -30.400000000,18.56 -30.420000000,18.58 -30.440000000,18.6 -30.460000000,18.62 -30.480000000,18.64 -30.500000000,18.66 -30.520000000,18.68 -30.540000000,18.7 -30.560000000,18.72 -30.580000000,18.74 -30.600000000,18.76 -30.620000000,18.78 -30.640000000,18.8 -30.660000000,18.82 -30.680000000,18.84 -30.700000000,18.86 -30.720000000,18.88 -30.740000000,18.9 -30.760000000,18.92 -30.780000000,18.94 -30.800000000,18.96 -30.820000000,18.98 -30.840000000,19 -30.860000000,19.02 -30.880000000,19.04 -30.900000000,19.04 -30.920000000,19.04 -30.940000000,19.04 -30.960000000,19.04 -30.980000000,19.04 -31.000000000,19.04 -31.020000000,19.04 -31.040000000,19.06 -31.060000000,19.06 -31.080000000,19.06 -31.100000000,19.06 -31.120000000,19.06 -31.140000000,19.06 -31.160000000,19.06 -31.180000000,19.06 -31.200000000,19.08 -31.220000000,19.1 -31.240000000,19.1 -31.260000000,19.1 -31.280000000,19.12 -31.300000000,19.14 -31.320000000,19.16 -31.340000000,19.18 -31.360000000,19.2 -31.380000000,19.22 -31.400000000,19.24 -31.420000000,19.26 -31.440000000,19.28 -31.460000000,19.3 -31.480000000,19.32 -31.500000000,19.34 -31.520000000,19.36 -31.540000000,19.38 -31.560000000,19.4 -31.580000000,19.42 -31.600000000,19.44 -31.620000000,19.46 -31.640000000,19.48 -31.660000000,19.5 -31.680000000,19.52 -31.700000000,19.54 -31.720000000,19.56 -31.740000000,19.58 -31.760000000,19.6 -31.780000000,19.62 -31.800000000,19.64 -31.820000000,19.64 -31.840000000,19.64 -31.860000000,19.64 -31.880000000,19.66 -31.900000000,19.68 -31.920000000,19.7 -31.940000000,19.7 -31.960000000,19.7 -31.980000000,19.7 -32.000000000,19.72 -32.020000000,19.74 -32.040000000,19.76 -32.060000000,19.78 -32.080000000,19.78 -32.100000000,19.78 -32.120000000,19.78 -32.140000000,19.78 -32.160000000,19.78 -32.180000000,19.78 -32.200000000,19.78 -32.220000000,19.78 -32.240000000,19.78 -32.260000000,19.78 -32.280000000,19.78 -32.300000000,19.78 -32.320000000,19.78 -32.340000000,19.78 -32.360000000,19.8 -32.380000000,19.82 -32.400000000,19.84 -32.420000000,19.86 -32.440000000,19.88 -32.460000000,19.88 -32.480000000,19.9 -32.500000000,19.92 -32.520000000,19.92 -32.540000000,19.92 -32.560000000,19.92 -32.580000000,19.92 -32.600000000,19.92 -32.620000000,19.92 -32.640000000,19.92 -32.660000000,19.92 -32.680000000,19.92 -32.700000000,19.92 -32.720000000,19.94 -32.740000000,19.96 -32.760000000,19.98 -32.780000000,20 -32.800000000,20.02 -32.820000000,20.04 -32.840000000,20.06 -32.860000000,20.08 -32.880000000,20.1 -32.900000000,20.12 -32.920000000,20.14 -32.940000000,20.16 -32.960000000,20.18 -32.980000000,20.2 -33.000000000,20.22 -33.020000000,20.24 -33.040000000,20.26 -33.060000000,20.28 -33.080000000,20.3 -33.100000000,20.32 -33.120000000,20.34 -33.140000000,20.36 -33.160000000,20.38 -33.180000000,20.4 -33.200000000,20.42 -33.220000000,20.44 -33.240000000,20.46 -33.260000000,20.48 -33.280000000,20.5 -33.300000000,20.52 -33.320000000,20.54 -33.340000000,20.56 -33.360000000,20.58 -33.380000000,20.6 -33.400000000,20.6 -33.420000000,20.62 -33.440000000,20.64 -33.460000000,20.66 -33.480000000,20.68 -33.500000000,20.7 -33.520000000,20.72 -33.540000000,20.72 -33.560000000,20.72 -33.580000000,20.74 -33.600000000,20.76 -33.620000000,20.78 -33.640000000,20.8 -33.660000000,20.82 -33.680000000,20.84 -33.700000000,20.86 -33.720000000,20.88 -33.740000000,20.9 -33.760000000,20.92 -33.780000000,20.92 -33.800000000,20.92 -33.820000000,20.94 -33.840000000,20.94 -33.860000000,20.96 -33.880000000,20.98 -33.900000000,21 -33.920000000,21.02 -33.940000000,21.04 -33.960000000,21.06 -33.980000000,21.08 -34.000000000,21.1 -34.020000000,21.12 -34.040000000,21.12 -34.060000000,21.14 -34.080000000,21.14 -34.100000000,21.14 -34.120000000,21.14 -34.140000000,21.14 -34.160000000,21.16 -34.180000000,21.18 -34.200000000,21.2 -34.220000000,21.22 -34.240000000,21.24 -34.260000000,21.26 -34.280000000,21.28 -34.300000000,21.3 -34.320000000,21.3 -34.340000000,21.3 -34.360000000,21.3 -34.380000000,21.3 -34.400000000,21.3 -34.420000000,21.32 -34.440000000,21.34 -34.460000000,21.36 -34.480000000,21.36 -34.500000000,21.36 -34.520000000,21.36 -34.540000000,21.38 -34.560000000,21.4 -34.580000000,21.4 -34.600000000,21.4 -34.620000000,21.4 -34.640000000,21.4 -34.660000000,21.4 -34.680000000,21.4 -34.700000000,21.4 -34.720000000,21.4 -34.740000000,21.4 -34.760000000,21.4 -34.780000000,21.42 -34.800000000,21.42 -34.820000000,21.44 -34.840000000,21.46 -34.860000000,21.46 -34.880000000,21.46 -34.900000000,21.46 -34.920000000,21.46 -34.940000000,21.46 -34.960000000,21.46 -34.980000000,21.46 -35.000000000,21.46 -35.020000000,21.46 -35.040000000,21.46 -35.060000000,21.46 -35.080000000,21.46 -35.100000000,21.46 -35.120000000,21.46 -35.140000000,21.46 -35.160000000,21.46 -35.180000000,21.46 -35.200000000,21.46 -35.220000000,21.46 -35.240000000,21.46 -35.260000000,21.46 -35.280000000,21.46 -35.300000000,21.46 -35.320000000,21.46 -35.340000000,21.46 -35.360000000,21.48 -35.380000000,21.5 -35.400000000,21.52 -35.420000000,21.54 -35.440000000,21.56 -35.460000000,21.58 -35.480000000,21.6 -35.500000000,21.6 -35.520000000,21.6 -35.540000000,21.6 -35.560000000,21.62 -35.580000000,21.62 -35.600000000,21.62 -35.620000000,21.62 -35.640000000,21.62 -35.660000000,21.62 -35.680000000,21.62 -35.700000000,21.62 -35.720000000,21.62 -35.740000000,21.62 -35.760000000,21.62 -35.780000000,21.62 -35.800000000,21.62 -35.820000000,21.62 -35.840000000,21.62 -35.860000000,21.62 -35.880000000,21.62 -35.900000000,21.62 -35.920000000,21.62 -35.940000000,21.62 -35.960000000,21.64 -35.980000000,21.64 -36.000000000,21.64 -36.020000000,21.64 -36.040000000,21.64 -36.060000000,21.64 -36.080000000,21.64 -36.100000000,21.64 -36.120000000,21.64 -36.140000000,21.66 -36.160000000,21.68 -36.180000000,21.68 -36.200000000,21.68 -36.220000000,21.68 -36.240000000,21.68 -36.260000000,21.68 -36.280000000,21.68 -36.300000000,21.7 -36.320000000,21.7 -36.340000000,21.72 -36.360000000,21.74 -36.380000000,21.76 -36.400000000,21.76 -36.420000000,21.76 -36.440000000,21.76 -36.460000000,21.76 -36.480000000,21.76 -36.500000000,21.76 -36.520000000,21.76 -36.540000000,21.76 -36.560000000,21.76 -36.580000000,21.76 -36.600000000,21.76 -36.620000000,21.76 -36.640000000,21.76 -36.660000000,21.76 -36.680000000,21.76 -36.700000000,21.76 -36.720000000,21.76 -36.740000000,21.76 -36.760000000,21.76 -36.780000000,21.76 -36.800000000,21.76 -36.820000000,21.76 -36.840000000,21.78 -36.860000000,21.8 -36.880000000,21.82 -36.900000000,21.84 -36.920000000,21.86 -36.940000000,21.88 -36.960000000,21.9 -36.980000000,21.92 -37.000000000,21.94 -37.020000000,21.96 -37.040000000,21.98 -37.060000000,22 -37.080000000,22.02 -37.100000000,22.04 -37.120000000,22.06 -37.140000000,22.06 -37.160000000,22.06 -37.180000000,22.06 -37.200000000,22.06 -37.220000000,22.06 -37.240000000,22.06 -37.260000000,22.06 -37.280000000,22.06 -37.300000000,22.06 -37.320000000,22.06 -37.340000000,22.06 -37.360000000,22.06 -37.380000000,22.06 -37.400000000,22.06 -37.420000000,22.06 -37.440000000,22.06 -37.460000000,22.06 -37.480000000,22.08 -37.500000000,22.1 -37.520000000,22.12 -37.540000000,22.14 -37.560000000,22.16 -37.580000000,22.18 -37.600000000,22.18 -37.620000000,22.18 -37.640000000,22.18 -37.660000000,22.18 -37.680000000,22.18 -37.700000000,22.18 -37.720000000,22.2 -37.740000000,22.2 -37.760000000,22.22 -37.780000000,22.22 -37.800000000,22.24 -37.820000000,22.26 -37.840000000,22.28 -37.860000000,22.28 -37.880000000,22.28 -37.900000000,22.28 -37.920000000,22.3 -37.940000000,22.32 -37.960000000,22.34 -37.980000000,22.36 -38.000000000,22.36 -38.020000000,22.36 -38.040000000,22.38 -38.060000000,22.4 -38.080000000,22.4 -38.100000000,22.4 -38.120000000,22.4 -38.140000000,22.4 -38.160000000,22.42 -38.180000000,22.44 -38.200000000,22.44 -38.220000000,22.44 -38.240000000,22.44 -38.260000000,22.44 -38.280000000,22.46 -38.300000000,22.48 -38.320000000,22.48 -38.340000000,22.48 -38.360000000,22.5 -38.380000000,22.5 -38.400000000,22.52 -38.420000000,22.54 -38.440000000,22.54 -38.460000000,22.54 -38.480000000,22.54 -38.500000000,22.54 -38.520000000,22.56 -38.540000000,22.58 -38.560000000,22.6 -38.580000000,22.62 -38.600000000,22.64 -38.620000000,22.66 -38.640000000,22.68 -38.660000000,22.7 -38.680000000,22.72 -38.700000000,22.74 -38.720000000,22.76 -38.740000000,22.78 -38.760000000,22.8 -38.780000000,22.82 -38.800000000,22.84 -38.820000000,22.84 -38.840000000,22.84 -38.860000000,22.84 -38.880000000,22.84 -38.900000000,22.84 -38.920000000,22.84 -38.940000000,22.84 -38.960000000,22.84 -38.980000000,22.84 -39.000000000,22.84 -39.020000000,22.86 -39.040000000,22.88 -39.060000000,22.9 -39.080000000,22.92 -39.100000000,22.94 -39.120000000,22.96 -39.140000000,22.98 -39.160000000,23 -39.180000000,23.02 -39.200000000,23.04 -39.220000000,23.06 -39.240000000,23.08 -39.260000000,23.1 -39.280000000,23.12 -39.300000000,23.14 -39.320000000,23.16 -39.340000000,23.18 -39.360000000,23.2 -39.380000000,23.22 -39.400000000,23.24 -39.420000000,23.26 -39.440000000,23.28 -39.460000000,23.3 -39.480000000,23.32 -39.500000000,23.34 -39.520000000,23.36 -39.540000000,23.38 -39.560000000,23.4 -39.580000000,23.42 -39.600000000,23.44 -39.620000000,23.46 -39.640000000,23.48 -39.660000000,23.5 -39.680000000,23.52 -39.700000000,23.54 -39.720000000,23.56 -39.740000000,23.58 -39.760000000,23.6 -39.780000000,23.62 -39.800000000,23.64 -39.820000000,23.66 -39.840000000,23.68 -39.860000000,23.7 -39.880000000,23.72 -39.900000000,23.74 -39.920000000,23.76 -39.940000000,23.78 -39.960000000,23.8 -39.980000000,23.82 -40.000000000,23.84 -40.020000000,23.86 -40.040000000,23.88 -40.060000000,23.9 -40.080000000,23.92 -40.100000000,23.94 -40.100000000,23.96 -40.100000000,23.98 -40.120000000,24 -40.120000000,24.02 -40.120000000,24.04 -40.120000000,24.06 -40.120000000,24.08 -40.120000000,24.1 -40.120000000,24.12 -40.120000000,24.14 -40.120000000,24.16 -40.120000000,24.18 -40.120000000,24.2 -40.120000000,24.22 -40.140000000,24.24 -40.160000000,24.26 -40.180000000,24.28 -40.200000000,24.3 -40.220000000,24.32 -40.220000000,24.34 -40.220000000,24.36 -40.220000000,24.38 -40.220000000,24.4 -40.220000000,24.42 -40.220000000,24.44 -40.220000000,24.46 -40.220000000,24.48 -40.220000000,24.5 -40.220000000,24.52 -40.240000000,24.54 -40.260000000,24.56 -40.280000000,24.58 -40.280000000,24.6 -40.280000000,24.62 -40.300000000,24.64 -40.320000000,24.66 -40.320000000,24.68 -40.320000000,24.7 -40.320000000,24.72 -40.320000000,24.74 -40.320000000,24.76 -40.320000000,24.78 -40.320000000,24.8 -40.320000000,24.82 -40.320000000,24.84 -40.320000000,24.86 -40.320000000,24.88 -40.320000000,24.9 -40.320000000,24.92 -40.320000000,24.94 -40.320000000,24.96 -40.320000000,24.98 -40.320000000,25 -40.320000000,25.02 -40.320000000,25.04 -40.320000000,25.06 -40.320000000,25.08 -40.340000000,25.1 -40.340000000,25.12 -40.340000000,25.14 -40.340000000,25.16 -40.340000000,25.18 -40.340000000,25.2 -40.340000000,25.22 -40.340000000,25.24 -40.340000000,25.26 -40.340000000,25.28 -40.340000000,25.3 -40.340000000,25.32 -40.340000000,25.34 -40.340000000,25.36 -40.340000000,25.38 -40.340000000,25.4 -40.340000000,25.42 -40.340000000,25.44 -40.340000000,25.46 -40.340000000,25.48 -40.340000000,25.5 -40.340000000,25.52 -40.340000000,25.54 -40.340000000,25.56 -40.340000000,25.58 -40.340000000,25.6 -40.340000000,25.62 -40.340000000,25.64 -40.340000000,25.66 -40.340000000,25.68 -40.340000000,25.7 -40.340000000,25.72 -40.340000000,25.74 -40.340000000,25.76 -40.340000000,25.78 -40.360000000,25.8 -40.380000000,25.82 -40.400000000,25.84 -40.420000000,25.86 -40.440000000,25.88 -40.460000000,25.9 -40.480000000,25.92 -40.500000000,25.94 -40.500000000,25.96 -40.500000000,25.98 -40.520000000,26 -40.540000000,26.02 -40.560000000,26.04 -40.580000000,26.06 -40.600000000,26.08 -40.620000000,26.1 -40.640000000,26.12 -40.660000000,26.14 -40.680000000,26.16 -40.680000000,26.18 -40.680000000,26.2 -40.680000000,26.22 -40.680000000,26.24 -40.680000000,26.26 -40.680000000,26.28 -40.680000000,26.3 -40.700000000,26.32 -40.720000000,26.34 -40.740000000,26.36 -40.740000000,26.38 -40.740000000,26.4 -40.740000000,26.42 -40.740000000,26.44 -40.740000000,26.46 -40.740000000,26.48 -40.740000000,26.5 -40.740000000,26.52 -40.760000000,26.54 -40.780000000,26.56 -40.800000000,26.58 -40.820000000,26.6 -40.820000000,26.62 -40.820000000,26.64 -40.820000000,26.66 -40.820000000,26.68 -40.820000000,26.7 -40.820000000,26.72 -40.820000000,26.74 -40.820000000,26.76 -40.820000000,26.78 -40.820000000,26.8 -40.820000000,26.82 -40.820000000,26.84 -40.820000000,26.86 -40.820000000,26.88 -40.820000000,26.9 -40.820000000,26.92 -40.820000000,26.94 -40.820000000,26.96 -40.820000000,26.98 -40.820000000,27 -40.820000000,27.02 -40.820000000,27.04 -40.820000000,27.06 -40.820000000,27.08 -40.820000000,27.1 -40.820000000,27.12 -40.820000000,27.14 -40.840000000,27.16 -40.840000000,27.18 -40.840000000,27.2 -40.840000000,27.22 -40.840000000,27.24 -40.840000000,27.26 -40.840000000,27.28 -40.840000000,27.3 -40.840000000,27.32 -40.840000000,27.34 -40.840000000,27.36 -40.840000000,27.38 -40.840000000,27.4 -40.840000000,27.42 -40.840000000,27.44 -40.840000000,27.46 -40.840000000,27.48 -40.840000000,27.5 -40.840000000,27.52 -40.840000000,27.54 -40.840000000,27.56 -40.840000000,27.58 -40.840000000,27.6 -40.840000000,27.62 -40.840000000,27.64 -40.840000000,27.66 -40.840000000,27.68 -40.840000000,27.7 -40.840000000,27.72 -40.840000000,27.74 -40.860000000,27.76 -40.860000000,27.78 -40.860000000,27.8 -40.860000000,27.82 -40.860000000,27.84 -40.860000000,27.86 -40.860000000,27.88 -40.860000000,27.9 -40.860000000,27.92 -40.860000000,27.94 -40.860000000,27.96 -40.860000000,27.98 -40.860000000,28 -40.860000000,28.02 -40.860000000,28.04 -40.860000000,28.06 -40.860000000,28.08 -40.860000000,28.1 -40.860000000,28.12 -40.860000000,28.14 -40.860000000,28.16 -40.860000000,28.18 -40.860000000,28.2 -40.860000000,28.22 -40.860000000,28.24 -40.860000000,28.26 -40.860000000,28.28 -40.860000000,28.3 -40.860000000,28.32 -40.860000000,28.34 -40.860000000,28.36 -40.860000000,28.38 -40.860000000,28.4 -40.880000000,28.42 -40.900000000,28.44 -40.920000000,28.46 -40.940000000,28.48 -40.960000000,28.5 -40.980000000,28.52 -41.000000000,28.54 -41.020000000,28.56 -41.040000000,28.58 -41.040000000,28.6 -41.040000000,28.62 -41.040000000,28.64 -41.040000000,28.66 -41.040000000,28.68 -41.040000000,28.7 -41.060000000,28.72 -41.080000000,28.74 -41.100000000,28.76 -41.120000000,28.78 -41.140000000,28.8 -41.160000000,28.82 -41.180000000,28.84 -41.200000000,28.86 -41.220000000,28.88 -41.240000000,28.9 -41.260000000,28.92 -41.280000000,28.94 -41.300000000,28.96 -41.320000000,28.98 -41.340000000,29 -41.360000000,29.02 -41.380000000,29.04 -41.400000000,29.06 -41.400000000,29.08 -41.400000000,29.1 -41.400000000,29.12 -41.400000000,29.14 -41.420000000,29.16 -41.440000000,29.18 -41.440000000,29.2 -41.440000000,29.22 -41.460000000,29.24 -41.460000000,29.26 -41.480000000,29.28 -41.500000000,29.3 -41.500000000,29.32 -41.520000000,29.34 -41.520000000,29.36 -41.520000000,29.38 -41.520000000,29.4 -41.520000000,29.42 -41.520000000,29.44 -41.520000000,29.46 -41.520000000,29.48 -41.520000000,29.5 -41.520000000,29.52 -41.540000000,29.54 -41.560000000,29.56 -41.580000000,29.58 -41.580000000,29.6 -41.580000000,29.62 -41.580000000,29.64 -41.580000000,29.66 -41.580000000,29.68 -41.580000000,29.7 -41.580000000,29.72 -41.580000000,29.74 -41.600000000,29.76 -41.620000000,29.78 -41.640000000,29.8 -41.660000000,29.82 -41.680000000,29.84 -41.700000000,29.86 -41.720000000,29.88 -41.740000000,29.9 -41.740000000,29.92 -41.760000000,29.94 -41.780000000,29.96 -41.800000000,29.98 -41.820000000,30 -41.840000000,30.02 -41.860000000,30.04 -41.860000000,30.06 -41.860000000,30.08 -41.860000000,30.1 -41.860000000,30.12 -41.860000000,30.14 -41.860000000,30.16 -41.860000000,30.18 -41.860000000,30.2 -41.860000000,30.22 -41.880000000,30.24 -41.880000000,30.26 -41.880000000,30.28 -41.880000000,30.3 -41.880000000,30.32 -41.880000000,30.34 -41.880000000,30.36 -41.880000000,30.38 -41.880000000,30.4 -41.880000000,30.42 -41.900000000,30.44 -41.920000000,30.46 -41.920000000,30.48 -41.920000000,30.5 -41.920000000,30.52 -41.920000000,30.54 -41.920000000,30.56 -41.920000000,30.58 -41.920000000,30.6 -41.920000000,30.62 -41.920000000,30.64 -41.920000000,30.66 -41.920000000,30.68 -41.920000000,30.7 -41.920000000,30.72 -41.920000000,30.74 -41.940000000,30.76 -41.940000000,30.78 -41.960000000,30.8 -41.980000000,30.82 -42.000000000,30.84 -42.020000000,30.86 -42.040000000,30.88 -42.060000000,30.9 -42.060000000,30.92 -42.060000000,30.94 -42.060000000,30.96 -42.060000000,30.98 -42.060000000,31 -42.060000000,31.02 -42.060000000,31.04 -42.060000000,31.06 -42.060000000,31.08 -42.060000000,31.1 -42.060000000,31.12 -42.060000000,31.14 -42.060000000,31.16 -42.060000000,31.18 -42.060000000,31.2 -42.060000000,31.22 -42.060000000,31.24 -42.060000000,31.26 -42.060000000,31.28 -42.060000000,31.3 -42.060000000,31.32 -42.060000000,31.34 -42.060000000,31.36 -42.060000000,31.38 -42.060000000,31.4 -42.080000000,31.42 -42.100000000,31.44 -42.120000000,31.46 -42.140000000,31.48 -42.160000000,31.5 -42.180000000,31.52 -42.200000000,31.54 -42.220000000,31.56 -42.240000000,31.58 -42.260000000,31.6 -42.280000000,31.62 -42.300000000,31.64 -42.320000000,31.66 -42.340000000,31.68 -42.360000000,31.7 -42.380000000,31.72 -42.400000000,31.74 -42.420000000,31.76 -42.440000000,31.78 -42.460000000,31.8 -42.480000000,31.82 -42.500000000,31.84 -42.520000000,31.86 -42.540000000,31.88 -42.560000000,31.9 -42.580000000,31.92 -42.600000000,31.94 -42.620000000,31.96 -42.640000000,31.98 -42.660000000,32 -42.680000000,32.02 -42.700000000,32.04 -42.720000000,32.06 -42.740000000,32.08 -42.760000000,32.1 -42.780000000,32.12 -42.800000000,32.14 -42.820000000,32.16 -42.840000000,32.18 -42.860000000,32.2 -42.880000000,32.22 -42.900000000,32.24 -42.920000000,32.26 -42.940000000,32.28 -42.960000000,32.3 -42.980000000,32.32 -43.000000000,32.34 -43.020000000,32.36 -43.040000000,32.38 -43.060000000,32.4 -43.080000000,32.42 -43.100000000,32.42 -43.120000000,32.44 -43.140000000,32.46 -43.160000000,32.46 -43.180000000,32.46 -43.200000000,32.46 -43.220000000,32.46 -43.240000000,32.46 -43.260000000,32.46 -43.280000000,32.46 -43.300000000,32.46 -43.320000000,32.46 -43.340000000,32.46 -43.360000000,32.46 -43.380000000,32.46 -43.400000000,32.46 -43.420000000,32.48 -43.440000000,32.5 -43.460000000,32.52 -43.480000000,32.52 -43.500000000,32.52 -43.520000000,32.52 -43.540000000,32.52 -43.560000000,32.52 -43.580000000,32.52 -43.600000000,32.52 -43.620000000,32.52 -43.640000000,32.52 -43.660000000,32.52 -43.680000000,32.52 -43.700000000,32.52 -43.720000000,32.52 -43.740000000,32.52 -43.760000000,32.52 -43.780000000,32.52 -43.800000000,32.52 -43.820000000,32.52 -43.840000000,32.52 -43.860000000,32.52 -43.880000000,32.52 -43.900000000,32.52 -43.920000000,32.52 -43.940000000,32.52 -43.960000000,32.52 -43.980000000,32.52 -44.000000000,32.52 -44.020000000,32.52 -44.040000000,32.52 -44.060000000,32.52 -44.080000000,32.52 -44.100000000,32.52 -44.120000000,32.52 -44.140000000,32.52 -44.160000000,32.52 -44.180000000,32.52 -44.200000000,32.52 -44.220000000,32.52 -44.240000000,32.52 -44.260000000,32.52 -44.280000000,32.52 -44.300000000,32.52 -44.320000000,32.52 -44.340000000,32.52 -44.360000000,32.52 -44.380000000,32.52 -44.400000000,32.52 -44.420000000,32.52 -44.440000000,32.52 -44.460000000,32.54 -44.480000000,32.56 -44.500000000,32.58 -44.520000000,32.58 -44.540000000,32.58 -44.560000000,32.58 -44.580000000,32.6 -44.600000000,32.6 -44.620000000,32.6 -44.640000000,32.6 -44.660000000,32.6 -44.680000000,32.6 -44.700000000,32.62 -44.720000000,32.64 -44.740000000,32.66 -44.760000000,32.68 -44.780000000,32.7 -44.800000000,32.72 -44.820000000,32.74 -44.840000000,32.76 -44.860000000,32.78 -44.880000000,32.8 -44.900000000,32.82 -44.920000000,32.82 -44.940000000,32.82 -44.960000000,32.84 -44.980000000,32.86 -45.000000000,32.88 -45.020000000,32.88 -45.040000000,32.88 -45.060000000,32.88 -45.080000000,32.88 -45.100000000,32.88 -45.120000000,32.88 -45.140000000,32.9 -45.160000000,32.92 -45.180000000,32.92 -45.200000000,32.92 -45.220000000,32.92 -45.240000000,32.92 -45.260000000,32.92 -45.280000000,32.92 -45.300000000,32.92 -45.320000000,32.92 -45.340000000,32.92 -45.360000000,32.94 -45.380000000,32.94 -45.400000000,32.94 -45.420000000,32.94 -45.440000000,32.96 -45.460000000,32.96 -45.480000000,32.96 -45.500000000,32.96 -45.520000000,32.96 -45.540000000,32.96 -45.560000000,32.96 -45.580000000,32.96 -45.600000000,32.96 -45.620000000,32.96 -45.640000000,32.98 -45.660000000,32.98 -45.680000000,32.98 -45.700000000,33 -45.720000000,33.02 -45.740000000,33.02 -45.760000000,33.04 -45.780000000,33.06 -45.800000000,33.08 -45.820000000,33.1 -45.840000000,33.12 -45.860000000,33.14 -45.880000000,33.16 -45.900000000,33.18 -45.920000000,33.2 -45.940000000,33.22 -45.960000000,33.24 -45.980000000,33.26 -46.000000000,33.28 -46.020000000,33.28 -46.040000000,33.28 -46.060000000,33.28 -46.080000000,33.28 -46.100000000,33.28 -46.120000000,33.28 -46.140000000,33.28 -46.160000000,33.28 -46.180000000,33.3 -46.200000000,33.3 -46.220000000,33.3 -46.240000000,33.3 -46.260000000,33.3 -46.280000000,33.3 -46.300000000,33.3 -46.320000000,33.3 -46.340000000,33.3 -46.360000000,33.3 -46.380000000,33.3 -46.400000000,33.3 -46.420000000,33.3 -46.440000000,33.3 -46.460000000,33.3 -46.480000000,33.3 -46.500000000,33.3 -46.520000000,33.3 -46.540000000,33.3 -46.560000000,33.3 -46.580000000,33.3 -46.600000000,33.3 -46.620000000,33.3 -46.640000000,33.3 -46.660000000,33.3 -46.680000000,33.3 -46.700000000,33.3 -46.720000000,33.3 -46.740000000,33.3 -46.760000000,33.3 -46.780000000,33.3 -46.800000000,33.3 -46.820000000,33.3 -46.840000000,33.3 -46.860000000,33.3 -46.880000000,33.3 -46.900000000,33.3 -46.920000000,33.3 -46.940000000,33.3 -46.960000000,33.32 -46.980000000,33.34 -47.000000000,33.36 -47.020000000,33.38 -47.040000000,33.4 -47.060000000,33.4 -47.080000000,33.4 -47.100000000,33.4 -47.120000000,33.42 -47.140000000,33.44 -47.160000000,33.44 -47.180000000,33.44 -47.200000000,33.44 -47.220000000,33.44 -47.240000000,33.44 -47.260000000,33.44 -47.280000000,33.44 -47.300000000,33.44 -47.320000000,33.46 -47.340000000,33.46 -47.360000000,33.46 -47.380000000,33.46 -47.400000000,33.46 -47.420000000,33.46 -47.440000000,33.46 -47.460000000,33.46 -47.480000000,33.46 -47.500000000,33.46 -47.520000000,33.46 -47.540000000,33.46 -47.560000000,33.48 -47.580000000,33.5 -47.600000000,33.5 -47.620000000,33.5 -47.640000000,33.5 -47.660000000,33.5 -47.680000000,33.5 -47.700000000,33.5 -47.720000000,33.5 -47.740000000,33.5 -47.760000000,33.52 -47.780000000,33.52 -47.800000000,33.52 -47.820000000,33.54 -47.840000000,33.54 -47.860000000,33.56 -47.880000000,33.58 -47.900000000,33.6 -47.920000000,33.62 -47.940000000,33.64 -47.960000000,33.66 -47.980000000,33.68 -48.000000000,33.7 -48.020000000,33.72 -48.040000000,33.74 -48.060000000,33.76 -48.080000000,33.78 -48.100000000,33.8 -48.120000000,33.82 -48.140000000,33.84 -48.160000000,33.86 -48.180000000,33.88 -48.200000000,33.9 -48.220000000,33.92 -48.240000000,33.94 -48.260000000,33.96 -48.280000000,33.98 -48.300000000,34 -48.320000000,34.02 -48.340000000,34.04 -48.360000000,34.06 -48.380000000,34.08 -48.400000000,34.1 -48.420000000,34.12 -48.440000000,34.14 -48.460000000,34.16 -48.480000000,34.18 -48.500000000,34.2 -48.520000000,34.22 -48.540000000,34.24 -48.560000000,34.26 -48.580000000,34.28 -48.600000000,34.3 -48.620000000,34.32 -48.640000000,34.34 -48.660000000,34.36 -48.680000000,34.38 -48.700000000,34.4 -48.720000000,34.42 -48.740000000,34.44 -48.760000000,34.46 -48.780000000,34.48 -48.800000000,34.5 -48.820000000,34.52 -48.840000000,34.54 -48.860000000,34.56 -48.860000000,34.58 -48.860000000,34.6 -48.860000000,34.62 -48.860000000,34.64 -48.860000000,34.66 -48.860000000,34.68 -48.860000000,34.7 -48.860000000,34.72 -48.860000000,34.74 -48.860000000,34.76 -48.860000000,34.78 -48.860000000,34.8 -48.860000000,34.82 -48.860000000,34.84 -48.860000000,34.86 -48.860000000,34.88 -48.860000000,34.9 -48.860000000,34.92 -48.860000000,34.94 -48.860000000,34.96 -48.860000000,34.98 -48.860000000,35 -48.860000000,35.02 -48.860000000,35.04 -48.860000000,35.06 -48.860000000,35.08 -48.860000000,35.1 -48.860000000,35.12 -48.860000000,35.14 -48.860000000,35.16 -48.860000000,35.18 -48.860000000,35.2 -48.860000000,35.22 -48.860000000,35.24 -48.860000000,35.26 -48.860000000,35.28 -48.860000000,35.3 -48.860000000,35.32 -48.860000000,35.34 -48.860000000,35.36 -48.860000000,35.38 -48.860000000,35.4 -48.860000000,35.42 -48.860000000,35.44 -48.860000000,35.46 -48.860000000,35.48 -48.860000000,35.5 -48.860000000,35.52 -48.860000000,35.54 -48.860000000,35.56 -48.860000000,35.58 -48.860000000,35.6 -48.860000000,35.62 -48.860000000,35.64 -48.860000000,35.66 -48.860000000,35.68 -48.860000000,35.7 -48.860000000,35.72 -48.860000000,35.74 -48.860000000,35.76 -48.860000000,35.78 -48.860000000,35.8 -48.860000000,35.82 -48.860000000,35.84 -48.860000000,35.86 -48.860000000,35.88 -48.860000000,35.9 -48.860000000,35.92 -48.860000000,35.94 -48.860000000,35.96 -48.860000000,35.98 -48.860000000,36 -48.860000000,36.02 -48.860000000,36.04 -48.860000000,36.06 -48.860000000,36.08 -48.860000000,36.1 -48.860000000,36.12 -48.860000000,36.14 -48.860000000,36.16 -48.860000000,36.18 -48.860000000,36.2 -48.860000000,36.22 -48.860000000,36.24 -48.860000000,36.26 -48.860000000,36.28 -48.860000000,36.3 -48.860000000,36.32 -48.860000000,36.34 -48.860000000,36.36 -48.860000000,36.38 -48.860000000,36.4 -48.860000000,36.42 -48.860000000,36.44 -48.860000000,36.46 -48.860000000,36.48 -48.860000000,36.5 -48.860000000,36.52 -48.860000000,36.54 -48.860000000,36.56 -48.860000000,36.58 -48.860000000,36.6 -48.860000000,36.62 -48.860000000,36.64 -48.860000000,36.66 -48.860000000,36.68 -48.860000000,36.7 -48.860000000,36.72 -48.860000000,36.74 -48.860000000,36.76 -48.860000000,36.78 -48.860000000,36.8 -48.860000000,36.82 -48.860000000,36.84 -48.860000000,36.86 -48.860000000,36.88 -48.860000000,36.9 -48.860000000,36.92 -48.860000000,36.94 -48.860000000,36.96 -48.860000000,36.98 -48.860000000,37 -48.860000000,37.02 -48.860000000,37.04 -48.860000000,37.06 -48.860000000,37.08 -48.860000000,37.1 -48.860000000,37.12 -48.860000000,37.14 -48.860000000,37.16 -48.860000000,37.18 -48.860000000,37.2 -48.860000000,37.22 -48.860000000,37.24 -48.860000000,37.26 -48.860000000,37.28 -48.860000000,37.3 -48.860000000,37.32 -48.860000000,37.34 -48.860000000,37.36 -48.860000000,37.38 -48.860000000,37.4 -48.860000000,37.42 -48.860000000,37.44 -48.860000000,37.46 -48.860000000,37.48 -48.860000000,37.5 -48.860000000,37.52 -48.860000000,37.54 -48.860000000,37.56 -48.860000000,37.58 -48.860000000,37.6 -48.860000000,37.62 -48.860000000,37.64 -48.860000000,37.66 -48.860000000,37.68 -48.860000000,37.7 -48.860000000,37.72 -48.860000000,37.74 -48.860000000,37.76 -48.860000000,37.78 -48.860000000,37.8 -48.860000000,37.82 -48.860000000,37.84 -48.860000000,37.86 -48.860000000,37.88 -48.860000000,37.9 -48.860000000,37.92 -48.860000000,37.94 -48.860000000,37.96 -48.860000000,37.98 -48.860000000,38 -48.860000000,38.02 -48.860000000,38.04 -48.860000000,38.06 -48.860000000,38.08 -48.860000000,38.1 -48.860000000,38.12 -48.860000000,38.14 -48.860000000,38.16 -48.860000000,38.18 -48.860000000,38.2 -48.860000000,38.22 -48.860000000,38.24 -48.860000000,38.26 -48.860000000,38.28 -48.860000000,38.3 -48.860000000,38.32 -48.860000000,38.34 -48.860000000,38.36 -48.860000000,38.38 -48.860000000,38.4 -48.860000000,38.42 -48.860000000,38.44 -48.860000000,38.46 -48.860000000,38.48 -48.860000000,38.5 -48.860000000,38.52 -48.860000000,38.54 -48.860000000,38.56 -48.860000000,38.58 -48.860000000,38.6 -48.860000000,38.62 -48.860000000,38.64 -48.860000000,38.66 -48.860000000,38.68 -48.860000000,38.7 -48.860000000,38.72 -48.860000000,38.74 -48.860000000,38.76 -48.860000000,38.78 -48.860000000,38.8 -48.860000000,38.82 -48.860000000,38.84 -48.860000000,38.86 -48.860000000,38.88 -48.860000000,38.9 -48.860000000,38.92 -48.860000000,38.94 -48.860000000,38.96 -48.860000000,38.98 -48.860000000,39 -48.860000000,39.02 -48.860000000,39.04 -48.860000000,39.06 -48.860000000,39.08 -48.860000000,39.1 -48.860000000,39.12 -48.860000000,39.14 -48.860000000,39.16 -48.860000000,39.18 -48.860000000,39.2 -48.860000000,39.22 -48.860000000,39.24 -48.860000000,39.26 -48.860000000,39.28 -48.860000000,39.3 -48.860000000,39.32 -48.860000000,39.34 -48.860000000,39.36 -48.860000000,39.38 -48.860000000,39.4 -48.860000000,39.42 -48.860000000,39.44 -48.860000000,39.46 -48.860000000,39.48 -48.860000000,39.5 -48.860000000,39.52 -48.860000000,39.54 -48.860000000,39.56 -48.860000000,39.58 -48.860000000,39.6 -48.860000000,39.62 -48.860000000,39.64 -48.860000000,39.66 -48.860000000,39.68 -48.860000000,39.7 -48.860000000,39.72 -48.860000000,39.74 -48.860000000,39.76 -48.860000000,39.78 -48.860000000,39.8 -48.860000000,39.82 -48.860000000,39.84 -48.860000000,39.86 -48.860000000,39.88 -48.860000000,39.9 -48.860000000,39.92 -48.860000000,39.94 -48.860000000,39.96 -48.860000000,39.98 -48.860000000,40 -48.860000000,40.02 -48.860000000,40.04 -48.860000000,40.06 -48.860000000,40.08 -48.860000000,40.1 -48.860000000,40.12 -48.860000000,40.14 -48.860000000,40.16 -48.860000000,40.18 -48.860000000,40.2 -48.860000000,40.22 -48.860000000,40.24 -48.860000000,40.26 -48.860000000,40.28 -48.860000000,40.3 -48.860000000,40.32 -48.860000000,40.34 -48.860000000,40.36 -48.860000000,40.38 -48.860000000,40.4 -48.860000000,40.42 -48.860000000,40.44 -48.860000000,40.46 -48.860000000,40.48 -48.860000000,40.5 -48.860000000,40.52 -48.860000000,40.54 -48.860000000,40.56 -48.860000000,40.58 -48.860000000,40.6 -48.860000000,40.62 -48.860000000,40.64 -48.860000000,40.66 -48.860000000,40.68 -48.860000000,40.7 -48.860000000,40.72 -48.860000000,40.74 -48.860000000,40.76 -48.860000000,40.78 -48.860000000,40.8 -48.860000000,40.82 -48.860000000,40.84 -48.860000000,40.86 -48.860000000,40.88 -48.860000000,40.9 -48.860000000,40.92 -48.860000000,40.94 -48.860000000,40.96 -48.860000000,40.98 -48.860000000,41 -48.860000000,41.02 -48.860000000,41.04 -48.860000000,41.06 -48.860000000,41.08 -48.860000000,41.1 -48.860000000,41.12 -48.860000000,41.14 -48.860000000,41.16 -48.860000000,41.18 -48.860000000,41.2 -48.860000000,41.22 -48.860000000,41.24 -48.860000000,41.26 -48.860000000,41.28 -48.860000000,41.3 -48.860000000,41.32 -48.860000000,41.34 -48.860000000,41.36 -48.860000000,41.38 -48.860000000,41.4 -48.860000000,41.42 -48.860000000,41.44 -48.860000000,41.46 -48.860000000,41.48 -48.860000000,41.5 -48.860000000,41.52 -48.860000000,41.54 -48.860000000,41.56 -48.860000000,41.58 -48.860000000,41.6 -48.860000000,41.62 -48.860000000,41.64 -48.860000000,41.66 -48.860000000,41.68 -48.860000000,41.7 -48.860000000,41.72 -48.860000000,41.74 -48.860000000,41.76 -48.860000000,41.78 -48.860000000,41.8 -48.860000000,41.82 -48.860000000,41.84 -48.860000000,41.86 -48.860000000,41.88 -48.860000000,41.9 -48.860000000,41.92 -48.860000000,41.94 -48.860000000,41.96 -48.860000000,41.98 -48.860000000,42 -48.860000000,42.02 -48.860000000,42.04 -48.860000000,42.06 -48.860000000,42.08 -48.860000000,42.1 -48.860000000,42.12 -48.860000000,42.14 -48.860000000,42.16 -48.860000000,42.18 -48.860000000,42.2 -48.860000000,42.22 -48.860000000,42.24 -48.860000000,42.26 -48.860000000,42.28 -48.860000000,42.3 -48.860000000,42.32 -48.860000000,42.34 -48.860000000,42.36 -48.860000000,42.38 -48.860000000,42.4 -48.860000000,42.42 -48.860000000,42.44 -48.860000000,42.46 -48.860000000,42.48 -48.860000000,42.5 -48.860000000,42.52 -48.860000000,42.54 -48.860000000,42.56 -48.860000000,42.58 -48.860000000,42.6 -48.860000000,42.62 -48.860000000,42.64 -48.860000000,42.66 -48.860000000,42.68 -48.860000000,42.7 -48.860000000,42.72 -48.860000000,42.74 -48.860000000,42.76 -48.860000000,42.78 -48.860000000,42.8 -48.860000000,42.82 -48.860000000,42.84 -48.860000000,42.86 -48.860000000,42.88 -48.860000000,42.9 -48.860000000,42.92 -48.860000000,42.94 -48.860000000,42.96 -48.860000000,42.98 -48.860000000,43 -48.860000000,43.02 -48.860000000,43.04 -48.860000000,43.06 -48.860000000,43.08 -48.860000000,43.1 -48.860000000,43.12 -48.860000000,43.14 -48.860000000,43.16 -48.860000000,43.18 -48.860000000,43.2 -48.860000000,43.22 -48.860000000,43.24 -48.860000000,43.26 -48.860000000,43.28 -48.860000000,43.3 -48.860000000,43.32 -48.860000000,43.34 -48.860000000,43.36 -48.860000000,43.38 -48.860000000,43.4 -48.860000000,43.42 -48.860000000,43.44 -48.860000000,43.46 -48.860000000,43.48 -48.860000000,43.5 -48.860000000,43.52 -48.860000000,43.54 -48.860000000,43.56 -48.860000000,43.58 -48.860000000,43.6 -48.860000000,43.62 -48.860000000,43.64 -48.860000000,43.66 -48.860000000,43.68 -48.860000000,43.7 -48.860000000,43.72 -48.860000000,43.74 -48.860000000,43.76 -48.860000000,43.78 -48.860000000,43.8 -48.860000000,43.82 -48.860000000,43.84 -48.860000000,43.86 -48.860000000,43.88 -48.860000000,43.9 -48.860000000,43.92 -48.860000000,43.94 -48.860000000,43.96 -48.860000000,43.98 -48.860000000,44 -48.860000000,44.02 -48.860000000,44.04 -48.860000000,44.06 -48.860000000,44.08 -48.860000000,44.1 -48.860000000,44.12 -48.860000000,44.14 -48.860000000,44.16 -48.860000000,44.18 -48.860000000,44.2 -48.860000000,44.22 -48.860000000,44.24 -48.860000000,44.26 -48.860000000,44.28 -48.860000000,44.3 -48.860000000,44.32 -48.860000000,44.34 -48.860000000,44.36 -48.860000000,44.38 -48.860000000,44.4 -48.860000000,44.42 -48.860000000,44.44 -48.860000000,44.46 -48.860000000,44.48 -48.860000000,44.5 -48.860000000,44.52 -48.860000000,44.54 -48.860000000,44.56 -48.860000000,44.58 -48.860000000,44.6 -48.860000000,44.62 -48.860000000,44.64 -48.860000000,44.66 -48.860000000,44.68 -48.860000000,44.7 -48.860000000,44.72 -48.860000000,44.74 -48.860000000,44.76 -48.860000000,44.78 -48.860000000,44.8 -48.860000000,44.82 -48.860000000,44.84 -48.860000000,44.86 -48.860000000,44.88 -48.860000000,44.9 -48.860000000,44.92 -48.860000000,44.94 -48.860000000,44.96 -48.860000000,44.98 -48.860000000,45 -48.860000000,45.02 -48.860000000,45.04 -48.860000000,45.06 -48.860000000,45.08 -48.860000000,45.1 -48.860000000,45.12 -48.860000000,45.14 -48.860000000,45.16 -48.860000000,45.18 -48.860000000,45.2 -48.860000000,45.22 -48.860000000,45.24 -48.860000000,45.26 -48.860000000,45.28 -48.860000000,45.3 -48.860000000,45.32 -48.860000000,45.34 -48.860000000,45.36 -48.860000000,45.38 -48.860000000,45.4 -48.860000000,45.42 -48.860000000,45.44 -48.860000000,45.46 -48.860000000,45.48 -48.860000000,45.5 -48.860000000,45.52 -48.860000000,45.54 -48.860000000,45.56 -48.860000000,45.58 -48.860000000,45.6 -48.860000000,45.62 -48.860000000,45.64 -48.860000000,45.66 -48.860000000,45.68 -48.860000000,45.7 -48.860000000,45.72 -48.860000000,45.74 -48.860000000,45.76 -48.860000000,45.78 -48.860000000,45.8 -48.860000000,45.82 -48.860000000,45.84 -48.860000000,45.86 -48.860000000,45.88 -48.860000000,45.9 -48.860000000,45.92 -48.860000000,45.94 -48.860000000,45.96 -48.860000000,45.98 -48.860000000,46 -48.860000000,46.02 -48.860000000,46.04 -48.860000000,46.06 -48.860000000,46.08 -48.860000000,46.1 -48.860000000,46.12 -48.860000000,46.14 -48.860000000,46.16 -48.860000000,46.18 -48.860000000,46.2 -48.860000000,46.22 -48.860000000,46.24 -48.860000000,46.26 -48.860000000,46.28 -48.860000000,46.3 -48.860000000,46.32 -48.860000000,46.34 -48.860000000,46.36 -48.860000000,46.38 -48.860000000,46.4 -48.860000000,46.42 -48.860000000,46.44 -48.860000000,46.46 -48.860000000,46.48 -48.860000000,46.5 -48.860000000,46.52 -48.860000000,46.54 -48.860000000,46.56 -48.860000000,46.58 -48.860000000,46.6 -48.860000000,46.62 -48.860000000,46.64 -48.860000000,46.66 -48.860000000,46.68 -48.860000000,46.7 -48.860000000,46.72 -48.860000000,46.74 -48.860000000,46.76 -48.860000000,46.78 -48.860000000,46.8 -48.860000000,46.82 -48.860000000,46.84 -48.860000000,46.86 -48.860000000,46.88 -48.860000000,46.9 -48.860000000,46.92 -48.860000000,46.94 -48.860000000,46.96 -48.860000000,46.98 -48.860000000,47 -48.860000000,47.02 -48.860000000,47.04 -48.860000000,47.06 -48.860000000,47.08 -48.860000000,47.1 -48.860000000,47.12 -48.860000000,47.14 -48.860000000,47.16 -48.860000000,47.18 -48.860000000,47.2 -48.860000000,47.22 -48.860000000,47.24 -48.860000000,47.26 -48.860000000,47.28 -48.860000000,47.3 -48.860000000,47.32 -48.860000000,47.34 -48.860000000,47.36 -48.860000000,47.38 -48.860000000,47.4 -48.860000000,47.42 -48.860000000,47.44 -48.860000000,47.46 -48.860000000,47.48 -48.860000000,47.5 -48.860000000,47.52 -48.860000000,47.54 -48.860000000,47.56 -48.860000000,47.58 -48.860000000,47.6 -48.860000000,47.62 -48.860000000,47.64 -48.860000000,47.66 -48.860000000,47.68 -48.860000000,47.7 -48.860000000,47.72 -48.860000000,47.74 -48.860000000,47.76 -48.860000000,47.78 -48.860000000,47.8 -48.860000000,47.82 -48.860000000,47.84 -48.860000000,47.86 -48.860000000,47.88 -48.860000000,47.9 -48.860000000,47.92 -48.860000000,47.94 -48.860000000,47.96 -48.860000000,47.98 -48.860000000,48 -48.860000000,48.02 -48.860000000,48.04 -48.860000000,48.06 -48.860000000,48.08 -48.860000000,48.1 -48.860000000,48.12 -48.860000000,48.14 -48.860000000,48.16 -48.860000000,48.18 -48.860000000,48.2 -48.860000000,48.22 -48.860000000,48.24 -48.860000000,48.26 -48.860000000,48.28 -48.860000000,48.3 -48.860000000,48.32 -48.860000000,48.34 -48.860000000,48.36 -48.860000000,48.38 -48.860000000,48.4 -48.860000000,48.42 -48.860000000,48.44 -48.860000000,48.46 -48.860000000,48.48 -48.860000000,48.5 -48.860000000,48.52 -48.860000000,48.54 -48.860000000,48.56 -48.860000000,48.58 -48.860000000,48.6 -48.860000000,48.62 -48.860000000,48.64 -48.860000000,48.66 -48.860000000,48.68 -48.860000000,48.7 -48.860000000,48.72 -48.860000000,48.74 -48.860000000,48.76 -48.860000000,48.78 -48.860000000,48.8 -48.860000000,48.82 -48.860000000,48.84 -48.860000000,48.86 -48.860000000,48.88 -48.860000000,48.9 -48.860000000,48.92 -48.860000000,48.94 -48.860000000,48.96 -48.860000000,48.98 -48.860000000,49 -48.860000000,49.02 -48.860000000,49.04 -48.860000000,49.06 -48.860000000,49.08 -48.860000000,49.1 -48.860000000,49.12 -48.860000000,49.14 -48.860000000,49.16 -48.860000000,49.18 -48.860000000,49.2 -48.860000000,49.22 -48.860000000,49.24 -48.860000000,49.26 -48.860000000,49.28 -48.860000000,49.3 -48.860000000,49.32 -48.860000000,49.34 -48.860000000,49.36 -48.860000000,49.38 -48.860000000,49.4 -48.860000000,49.42 -48.860000000,49.44 -48.860000000,49.46 -48.860000000,49.48 -48.860000000,49.5 -48.860000000,49.52 -48.860000000,49.54 -48.860000000,49.56 -48.860000000,49.58 -48.860000000,49.6 -48.860000000,49.62 -48.860000000,49.64 -48.860000000,49.66 -48.860000000,49.68 -48.860000000,49.7 -48.860000000,49.72 -48.860000000,49.74 -48.860000000,49.76 -48.860000000,49.78 -48.860000000,49.8 -48.860000000,49.82 -48.860000000,49.84 -48.860000000,49.86 -48.860000000,49.88 -48.860000000,49.9 -48.860000000,49.92 -48.860000000,49.94 -48.860000000,49.96 -48.860000000,49.98 -48.860000000,50 -48.860000000,50.02 -48.860000000,50.04 -48.860000000,50.06 -48.860000000,50.08 -48.860000000,50.1 -48.860000000,50.12 -48.860000000,50.14 -48.860000000,50.16 -48.860000000,50.18 -48.860000000,50.2 -48.860000000,50.22 -48.860000000,50.24 -48.860000000,50.26 -48.860000000,50.28 -48.860000000,50.3 -48.860000000,50.32 -48.860000000,50.34 -48.860000000,50.36 -48.860000000,50.38 -48.860000000,50.4 -48.860000000,50.42 -48.860000000,50.44 -48.860000000,50.46 -48.860000000,50.48 -48.860000000,50.5 -48.860000000,50.52 -48.860000000,50.54 -48.860000000,50.56 -48.860000000,50.58 -48.860000000,50.6 -48.860000000,50.62 -48.860000000,50.64 -48.860000000,50.66 -48.860000000,50.68 -48.860000000,50.7 -48.860000000,50.72 -48.860000000,50.74 -48.860000000,50.76 -48.860000000,50.78 -48.860000000,50.8 -48.860000000,50.82 -48.860000000,50.84 -48.860000000,50.86 -48.860000000,50.88 -48.860000000,50.9 -48.860000000,50.92 -48.860000000,50.94 -48.860000000,50.96 -48.860000000,50.98 -48.860000000,51 -48.860000000,51.02 -48.860000000,51.04 -48.860000000,51.06 -48.860000000,51.08 -48.860000000,51.1 -48.860000000,51.12 -48.860000000,51.14 -48.860000000,51.16 -48.860000000,51.18 -48.860000000,51.2 -48.860000000,51.22 -48.860000000,51.24 -48.860000000,51.26 -48.860000000,51.28 -48.860000000,51.3 -48.860000000,51.32 -48.860000000,51.34 -48.860000000,51.36 -48.860000000,51.38 -48.860000000,51.4 -48.860000000,51.42 -48.860000000,51.44 -48.860000000,51.46 -48.860000000,51.48 -48.860000000,51.5 -48.860000000,51.52 -48.860000000,51.54 -48.860000000,51.56 -48.860000000,51.58 -48.860000000,51.6 -48.860000000,51.62 -48.860000000,51.64 -48.860000000,51.66 -48.860000000,51.68 -48.860000000,51.7 -48.860000000,51.72 -48.860000000,51.74 -48.860000000,51.76 -48.860000000,51.78 -48.860000000,51.8 -48.860000000,51.82 -48.860000000,51.84 -48.860000000,51.86 -48.860000000,51.88 -48.860000000,51.9 -48.860000000,51.92 -48.860000000,51.94 -48.860000000,51.96 -48.860000000,51.98 -48.860000000,52 -48.860000000,52.02 -48.860000000,52.04 -48.860000000,52.06 -48.860000000,52.08 -48.860000000,52.1 -48.860000000,52.12 -48.860000000,52.14 -48.860000000,52.16 -48.860000000,52.18 -48.860000000,52.2 -48.860000000,52.22 -48.860000000,52.24 -48.860000000,52.26 -48.860000000,52.28 -48.860000000,52.3 -48.860000000,52.32 -48.860000000,52.34 -48.860000000,52.36 -48.860000000,52.38 -48.860000000,52.4 -48.860000000,52.42 -48.860000000,52.44 -48.860000000,52.46 -48.860000000,52.48 -48.860000000,52.5 -48.860000000,52.52 -48.860000000,52.54 -48.860000000,52.56 -48.860000000,52.58 -48.860000000,52.6 -48.860000000,52.62 -48.860000000,52.64 -48.860000000,52.66 -48.860000000,52.68 -48.860000000,52.7 -48.860000000,52.72 -48.860000000,52.74 -48.860000000,52.76 -48.860000000,52.78 -48.860000000,52.8 -48.860000000,52.82 -48.860000000,52.84 -48.860000000,52.86 -48.860000000,52.88 -48.860000000,52.9 -48.860000000,52.92 -48.860000000,52.94 -48.860000000,52.96 -48.860000000,52.98 -48.860000000,53 -48.860000000,53.02 -48.860000000,53.04 -48.860000000,53.06 -48.860000000,53.08 -48.860000000,53.1 -48.860000000,53.12 -48.860000000,53.14 -48.860000000,53.16 -48.860000000,53.18 -48.860000000,53.2 -48.860000000,53.22 -48.860000000,53.24 -48.860000000,53.26 -48.860000000,53.28 -48.860000000,53.3 -48.860000000,53.32 -48.860000000,53.34 -48.860000000,53.36 -48.860000000,53.38 -48.860000000,53.4 -48.860000000,53.42 -48.860000000,53.44 -48.860000000,53.46 -48.860000000,53.48 -48.860000000,53.5 -48.860000000,53.52 -48.860000000,53.54 -48.860000000,53.56 -48.860000000,53.58 -48.860000000,53.6 -48.860000000,53.62 -48.860000000,53.64 -48.860000000,53.66 -48.860000000,53.68 -48.860000000,53.7 -48.860000000,53.72 -48.860000000,53.74 -48.860000000,53.76 -48.860000000,53.78 -48.860000000,53.8 -48.860000000,53.82 -48.860000000,53.84 -48.860000000,53.86 -48.860000000,53.88 -48.860000000,53.9 -48.860000000,53.92 -48.860000000,53.94 -48.860000000,53.96 -48.860000000,53.98 -48.860000000,54 -48.860000000,54.02 -48.860000000,54.04 -48.860000000,54.06 -48.860000000,54.08 -48.860000000,54.1 -48.860000000,54.12 -48.860000000,54.14 -48.860000000,54.16 -48.860000000,54.18 -48.860000000,54.2 -48.860000000,54.22 -48.860000000,54.24 -48.860000000,54.26 -48.860000000,54.28 -48.860000000,54.3 -48.860000000,54.32 -48.860000000,54.34 -48.860000000,54.36 -48.860000000,54.38 -48.860000000,54.4 -48.860000000,54.42 -48.860000000,54.44 -48.860000000,54.46 -48.860000000,54.48 -48.860000000,54.5 -48.860000000,54.52 -48.860000000,54.54 -48.860000000,54.56 -48.860000000,54.58 -48.860000000,54.6 -48.860000000,54.62 -48.860000000,54.64 -48.860000000,54.66 -48.860000000,54.68 -48.860000000,54.7 -48.860000000,54.72 -48.860000000,54.74 -48.860000000,54.76 -48.860000000,54.78 -48.860000000,54.8 -48.860000000,54.82 -48.860000000,54.84 -48.860000000,54.86 -48.860000000,54.88 -48.860000000,54.9 -48.860000000,54.92 -48.860000000,54.94 -48.860000000,54.96 -48.860000000,54.98 -48.860000000,55 -48.860000000,55.02 -48.860000000,55.04 -48.860000000,55.06 -48.860000000,55.08 -48.860000000,55.1 -48.860000000,55.12 -48.860000000,55.14 -48.860000000,55.16 -48.860000000,55.18 -48.860000000,55.2 -48.860000000,55.22 -48.860000000,55.24 -48.860000000,55.26 -48.860000000,55.28 -48.860000000,55.3 -48.860000000,55.32 -48.860000000,55.34 -48.860000000,55.36 -48.860000000,55.38 -48.860000000,55.4 -48.860000000,55.42 -48.860000000,55.44 -48.860000000,55.46 -48.860000000,55.48 -48.860000000,55.5 -48.860000000,55.52 -48.860000000,55.54 -48.860000000,55.56 -48.860000000,55.58 -48.860000000,55.6 -48.860000000,55.62 -48.860000000,55.64 -48.860000000,55.66 -48.860000000,55.68 -48.860000000,55.7 -48.860000000,55.72 -48.860000000,55.74 -48.860000000,55.76 -48.860000000,55.78 -48.860000000,55.8 -48.860000000,55.82 -48.860000000,55.84 -48.860000000,55.86 -48.860000000,55.88 -48.860000000,55.9 -48.860000000,55.92 -48.860000000,55.94 -48.860000000,55.96 -48.860000000,55.98 -48.860000000,56 -48.860000000,56.02 -48.860000000,56.04 -48.860000000,56.06 -48.860000000,56.08 -48.860000000,56.1 -48.860000000,56.12 -48.860000000,56.14 -48.860000000,56.16 -48.860000000,56.18 -48.860000000,56.2 -48.860000000,56.22 -48.860000000,56.24 -48.860000000,56.26 -48.860000000,56.28 -48.860000000,56.3 -48.860000000,56.32 -48.860000000,56.34 -48.860000000,56.36 -48.860000000,56.38 -48.860000000,56.4 -48.860000000,56.42 -48.860000000,56.44 -48.860000000,56.46 -48.860000000,56.48 -48.860000000,56.5 -48.860000000,56.52 -48.860000000,56.54 -48.860000000,56.56 -48.860000000,56.58 -48.860000000,56.6 -48.860000000,56.62 -48.860000000,56.64 -48.860000000,56.66 -48.860000000,56.68 -48.860000000,56.7 -48.860000000,56.72 -48.860000000,56.74 -48.860000000,56.76 -48.860000000,56.78 -48.860000000,56.8 -48.860000000,56.82 -48.860000000,56.84 -48.860000000,56.86 -48.860000000,56.88 -48.860000000,56.9 -48.860000000,56.92 -48.860000000,56.94 -48.860000000,56.96 -48.860000000,56.98 -48.860000000,57 -48.860000000,57.02 -48.860000000,57.04 -48.860000000,57.06 -48.860000000,57.08 -48.860000000,57.1 -48.860000000,57.12 -48.860000000,57.14 -48.860000000,57.16 -48.860000000,57.18 -48.860000000,57.2 -48.860000000,57.22 -48.860000000,57.24 -48.860000000,57.26 -48.860000000,57.28 -48.860000000,57.3 -48.860000000,57.32 -48.860000000,57.34 -48.860000000,57.36 -48.860000000,57.38 -48.860000000,57.4 -48.860000000,57.42 -48.860000000,57.44 -48.860000000,57.46 -48.860000000,57.48 -48.860000000,57.5 -48.860000000,57.52 -48.860000000,57.54 -48.860000000,57.56 -48.860000000,57.58 -48.860000000,57.6 -48.860000000,57.62 -48.860000000,57.64 -48.860000000,57.66 -48.860000000,57.68 -48.860000000,57.7 -48.860000000,57.72 -48.860000000,57.74 -48.860000000,57.76 -48.860000000,57.78 -48.860000000,57.8 -48.860000000,57.82 -48.860000000,57.84 -48.860000000,57.86 -48.860000000,57.88 -48.860000000,57.9 -48.860000000,57.92 -48.860000000,57.94 -48.860000000,57.96 -48.860000000,57.98 -48.860000000,58 -48.860000000,58.02 -48.860000000,58.04 -48.860000000,58.06 -48.860000000,58.08 -48.860000000,58.1 -48.860000000,58.12 -48.860000000,58.14 -48.860000000,58.16 -48.860000000,58.18 -48.860000000,58.2 -48.860000000,58.22 -48.860000000,58.24 -48.860000000,58.26 -48.860000000,58.28 -48.860000000,58.3 -48.860000000,58.32 -48.860000000,58.34 -48.860000000,58.36 -48.860000000,58.38 -48.860000000,58.4 -48.860000000,58.42 -48.860000000,58.44 -48.860000000,58.46 -48.860000000,58.48 -48.860000000,58.5 -48.860000000,58.52 -48.860000000,58.54 -48.860000000,58.56 -48.860000000,58.58 -48.860000000,58.6 -48.860000000,58.62 -48.860000000,58.64 -48.860000000,58.66 -48.860000000,58.68 -48.860000000,58.7 -48.860000000,58.72 -48.860000000,58.74 -48.860000000,58.76 -48.860000000,58.78 -48.860000000,58.8 -48.860000000,58.82 -48.860000000,58.84 -48.860000000,58.86 -48.860000000,58.88 -48.860000000,58.9 -48.860000000,58.92 -48.860000000,58.94 -48.860000000,58.96 -48.860000000,58.98 -48.860000000,59 -48.860000000,59.02 -48.860000000,59.04 -48.860000000,59.06 -48.860000000,59.08 -48.860000000,59.1 -48.860000000,59.12 -48.860000000,59.14 -48.860000000,59.16 -48.860000000,59.18 -48.860000000,59.2 -48.860000000,59.22 -48.860000000,59.24 -48.860000000,59.26 -48.860000000,59.28 -48.860000000,59.3 -48.860000000,59.32 -48.860000000,59.34 -48.860000000,59.36 -48.860000000,59.38 -48.860000000,59.4 -48.860000000,59.42 -48.860000000,59.44 -48.860000000,59.46 -48.860000000,59.48 -48.860000000,59.5 -48.860000000,59.52 -48.860000000,59.54 -48.860000000,59.56 -48.860000000,59.58 -48.860000000,59.6 -48.860000000,59.62 -48.860000000,59.64 -48.860000000,59.66 -48.860000000,59.68 -48.860000000,59.7 -48.860000000,59.72 -48.860000000,59.74 -48.860000000,59.76 -48.860000000,59.78 -48.860000000,59.8 -48.860000000,59.82 -48.860000000,59.84 -48.860000000,59.86 -48.860000000,59.88 -48.860000000,59.9 -48.860000000,59.92 -48.860000000,59.94 -48.860000000,59.96 -48.860000000,59.98 -48.860000000,60 -48.860000000,60.02 -48.860000000,60.04 -48.860000000,60.06 -48.860000000,60.08 -48.860000000,60.1 -48.860000000,60.12 -48.860000000,60.14 -48.860000000,60.16 -48.860000000,60.18 -48.860000000,60.2 -48.860000000,60.22 -48.860000000,60.24 -48.860000000,60.26 -48.860000000,60.28 -48.860000000,60.3 -48.860000000,60.32 -48.860000000,60.34 -48.860000000,60.36 -48.860000000,60.38 -48.860000000,60.4 -48.860000000,60.42 -48.860000000,60.44 -48.860000000,60.46 -48.860000000,60.48 -48.860000000,60.5 -48.860000000,60.52 -48.860000000,60.54 -48.860000000,60.56 -48.860000000,60.58 -48.860000000,60.6 -48.860000000,60.62 -48.860000000,60.64 -48.860000000,60.66 -48.860000000,60.68 -48.860000000,60.7 -48.860000000,60.72 -48.860000000,60.74 -48.860000000,60.76 -48.860000000,60.78 -48.860000000,60.8 -48.860000000,60.82 -48.860000000,60.84 -48.860000000,60.86 -48.860000000,60.88 -48.860000000,60.9 -48.860000000,60.92 -48.860000000,60.94 -48.860000000,60.96 -48.860000000,60.98 -48.860000000,61 -48.860000000,61.02 -48.860000000,61.04 -48.860000000,61.06 -48.860000000,61.08 -48.860000000,61.1 -48.860000000,61.12 -48.860000000,61.14 -48.860000000,61.16 -48.860000000,61.18 -48.860000000,61.2 -48.860000000,61.22 -48.860000000,61.24 -48.860000000,61.26 -48.860000000,61.28 -48.860000000,61.3 -48.860000000,61.32 -48.860000000,61.34 -48.860000000,61.36 -48.860000000,61.38 -48.860000000,61.4 -48.860000000,61.42 -48.860000000,61.44 -48.860000000,61.46 -48.860000000,61.48 -48.860000000,61.5 -48.860000000,61.52 -48.860000000,61.54 -48.880000000,61.56 -48.900000000,61.58 -48.920000000,61.6 -48.940000000,61.62 -48.960000000,61.64 -48.980000000,61.66 -49.000000000,61.68 -49.020000000,61.7 -49.040000000,61.72 -49.060000000,61.74 -49.080000000,61.76 -49.100000000,61.78 -49.120000000,61.8 -49.140000000,61.82 -49.160000000,61.84 -49.180000000,61.86 -49.200000000,61.88 -49.220000000,61.9 -49.240000000,61.92 -49.260000000,61.94 -49.280000000,61.96 -49.300000000,61.98 -49.320000000,62 -49.340000000,62.02 -49.360000000,62.04 -49.380000000,62.06 -49.400000000,62.08 -49.420000000,62.1 -49.440000000,62.12 -49.460000000,62.14 -49.480000000,62.16 -49.500000000,62.18 -49.520000000,62.2 -49.540000000,62.22 -49.560000000,62.24 -49.580000000,62.26 -49.600000000,62.28 -49.620000000,62.3 -49.640000000,62.32 -49.660000000,62.34 -49.680000000,62.36 -49.700000000,62.38 -49.720000000,62.4 -49.740000000,62.42 -49.760000000,62.44 -49.780000000,62.46 -49.800000000,62.48 -49.820000000,62.5 -49.840000000,62.52 -49.860000000,62.54 -49.880000000,62.56 -49.900000000,62.56 -49.920000000,62.56 -49.940000000,62.56 -49.960000000,62.56 -49.980000000,62.56 -50.000000000,62.56 -50.020000000,62.56 -50.040000000,62.56 -50.060000000,62.56 -50.080000000,62.56 -50.100000000,62.56 -50.120000000,62.56 -50.140000000,62.56 -50.160000000,62.56 -50.180000000,62.56 -50.200000000,62.56 -50.220000000,62.56 -50.240000000,62.56 -50.260000000,62.56 -50.280000000,62.56 -50.300000000,62.56 -50.320000000,62.56 -50.340000000,62.56 -50.360000000,62.56 -50.380000000,62.56 -50.400000000,62.56 -50.420000000,62.56 -50.440000000,62.56 -50.460000000,62.56 -50.480000000,62.56 -50.500000000,62.56 -50.520000000,62.56 -50.540000000,62.56 -50.560000000,62.56 -50.580000000,62.56 -50.600000000,62.56 -50.620000000,62.56 -50.640000000,62.56 -50.660000000,62.56 -50.680000000,62.56 -50.700000000,62.56 -50.720000000,62.56 -50.740000000,62.56 -50.760000000,62.56 -50.780000000,62.56 -50.800000000,62.56 -50.820000000,62.56 -50.840000000,62.56 -50.860000000,62.56 -50.880000000,62.56 -50.900000000,62.56 -50.920000000,62.56 -50.940000000,62.56 -50.960000000,62.56 -50.980000000,62.56 -51.000000000,62.56 -51.020000000,62.56 -51.040000000,62.56 -51.060000000,62.56 -51.080000000,62.56 -51.100000000,62.56 -51.120000000,62.56 -51.140000000,62.56 -51.160000000,62.56 -51.180000000,62.56 -51.200000000,62.56 -51.220000000,62.56 -51.240000000,62.56 -51.260000000,62.56 -51.280000000,62.56 -51.300000000,62.56 -51.320000000,62.56 -51.340000000,62.56 -51.360000000,62.56 -51.380000000,62.56 -51.400000000,62.56 -51.420000000,62.56 -51.440000000,62.56 -51.460000000,62.56 -51.480000000,62.56 -51.500000000,62.56 -51.520000000,62.56 -51.540000000,62.56 -51.560000000,62.56 -51.580000000,62.56 -51.600000000,62.56 -51.620000000,62.56 -51.640000000,62.56 -51.660000000,62.56 -51.680000000,62.56 -51.700000000,62.56 -51.720000000,62.56 -51.740000000,62.56 -51.760000000,62.56 -51.780000000,62.56 -51.800000000,62.56 -51.820000000,62.56 -51.840000000,62.56 -51.860000000,62.56 -51.880000000,62.56 -51.900000000,62.56 -51.920000000,62.56 -51.940000000,62.56 -51.960000000,62.56 -51.980000000,62.56 -52.000000000,62.56 -52.020000000,62.56 -52.040000000,62.56 -52.060000000,62.56 -52.080000000,62.56 -52.100000000,62.56 -52.120000000,62.56 -52.140000000,62.56 -52.160000000,62.56 -52.180000000,62.56 -52.200000000,62.56 -52.220000000,62.56 -52.240000000,62.56 -52.260000000,62.56 -52.280000000,62.56 -52.300000000,62.56 -52.320000000,62.56 -52.340000000,62.56 -52.360000000,62.56 -52.380000000,62.56 -52.400000000,62.56 -52.420000000,62.56 -52.440000000,62.56 -52.460000000,62.56 -52.480000000,62.56 -52.500000000,62.56 -52.520000000,62.56 -52.540000000,62.56 -52.560000000,62.56 -52.580000000,62.56 -52.600000000,62.56 -52.620000000,62.56 -52.640000000,62.56 -52.660000000,62.56 -52.680000000,62.56 -52.700000000,62.56 -52.720000000,62.56 -52.740000000,62.56 -52.760000000,62.56 -52.780000000,62.56 -52.800000000,62.56 -52.820000000,62.56 -52.840000000,62.56 -52.860000000,62.56 -52.880000000,62.56 -52.900000000,62.56 -52.920000000,62.56 -52.940000000,62.56 -52.960000000,62.56 -52.980000000,62.56 -53.000000000,62.56 -53.020000000,62.56 -53.040000000,62.56 -53.060000000,62.56 -53.080000000,62.56 -53.100000000,62.56 -53.120000000,62.56 -53.140000000,62.56 -53.160000000,62.56 -53.180000000,62.56 -53.200000000,62.56 -53.220000000,62.56 -53.240000000,62.56 -53.260000000,62.56 -53.280000000,62.56 -53.300000000,62.56 -53.320000000,62.56 -53.340000000,62.56 -53.360000000,62.56 -53.380000000,62.56 -53.400000000,62.56 -53.420000000,62.56 -53.440000000,62.56 -53.460000000,62.56 -53.480000000,62.56 -53.500000000,62.56 -53.520000000,62.56 -53.540000000,62.56 -53.560000000,62.56 -53.580000000,62.56 -53.600000000,62.56 -53.620000000,62.56 -53.640000000,62.56 -53.660000000,62.56 -53.680000000,62.56 -53.700000000,62.56 -53.720000000,62.56 -53.740000000,62.56 -53.760000000,62.56 -53.780000000,62.56 -53.800000000,62.56 -53.820000000,62.56 -53.840000000,62.56 -53.860000000,62.56 -53.880000000,62.56 -53.900000000,62.56 -53.920000000,62.56 -53.940000000,62.56 -53.960000000,62.56 -53.980000000,62.56 -54.000000000,62.56 -54.020000000,62.56 -54.040000000,62.56 -54.060000000,62.56 -54.080000000,62.56 -54.100000000,62.56 -54.120000000,62.56 -54.140000000,62.56 -54.160000000,62.56 -54.180000000,62.56 -54.200000000,62.56 -54.220000000,62.56 -54.240000000,62.56 -54.260000000,62.56 -54.280000000,62.56 -54.300000000,62.56 -54.320000000,62.56 -54.340000000,62.56 -54.360000000,62.56 -54.380000000,62.56 -54.400000000,62.56 -54.420000000,62.56 -54.440000000,62.56 -54.460000000,62.56 -54.480000000,62.56 -54.500000000,62.56 -54.520000000,62.56 -54.540000000,62.56 -54.560000000,62.56 -54.580000000,62.56 -54.600000000,62.56 -54.620000000,62.56 -54.640000000,62.56 -54.660000000,62.56 -54.680000000,62.56 -54.700000000,62.56 -54.720000000,62.56 -54.740000000,62.56 -54.760000000,62.56 -54.780000000,62.56 -54.800000000,62.56 -54.820000000,62.56 -54.840000000,62.56 -54.860000000,62.56 -54.880000000,62.56 -54.900000000,62.56 -54.920000000,62.56 -54.940000000,62.56 -54.960000000,62.56 -54.980000000,62.56 -55.000000000,62.56 -55.020000000,62.56 -55.040000000,62.56 -55.060000000,62.56 -55.080000000,62.56 -55.100000000,62.56 -55.120000000,62.56 -55.140000000,62.56 -55.160000000,62.56 -55.180000000,62.56 -55.200000000,62.56 -55.220000000,62.56 -55.240000000,62.56 -55.260000000,62.56 -55.280000000,62.56 -55.300000000,62.56 -55.320000000,62.56 -55.340000000,62.56 -55.360000000,62.56 -55.380000000,62.56 -55.400000000,62.56 -55.420000000,62.56 -55.440000000,62.56 -55.460000000,62.56 -55.480000000,62.56 -55.500000000,62.56 -55.520000000,62.56 -55.540000000,62.56 -55.560000000,62.56 -55.580000000,62.56 -55.600000000,62.56 -55.620000000,62.56 -55.640000000,62.56 -55.660000000,62.56 -55.680000000,62.56 -55.700000000,62.56 -55.720000000,62.56 -55.740000000,62.56 -55.760000000,62.56 -55.780000000,62.56 -55.800000000,62.56 -55.820000000,62.56 -55.840000000,62.56 -55.860000000,62.56 -55.880000000,62.56 -55.900000000,62.56 -55.920000000,62.56 -55.940000000,62.56 -55.960000000,62.56 -55.980000000,62.56 -56.000000000,62.56 -56.020000000,62.56 -56.040000000,62.56 -56.060000000,62.56 -56.080000000,62.56 -56.100000000,62.56 -56.120000000,62.56 -56.140000000,62.56 -56.160000000,62.56 -56.180000000,62.56 -56.200000000,62.56 -56.220000000,62.56 -56.240000000,62.56 -56.260000000,62.56 -56.280000000,62.56 -56.300000000,62.56 -56.320000000,62.56 -56.340000000,62.56 -56.360000000,62.56 -56.380000000,62.56 -56.400000000,62.56 -56.420000000,62.56 -56.440000000,62.56 -56.460000000,62.56 -56.480000000,62.56 -56.500000000,62.56 -56.520000000,62.56 -56.540000000,62.56 -56.560000000,62.56 -56.580000000,62.56 -56.600000000,62.56 -56.620000000,62.56 -56.640000000,62.56 -56.660000000,62.56 -56.680000000,62.56 -56.700000000,62.56 -56.720000000,62.56 -56.740000000,62.56 -56.760000000,62.56 -56.780000000,62.56 -56.800000000,62.56 -56.820000000,62.56 -56.840000000,62.56 -56.860000000,62.56 -56.880000000,62.56 -56.900000000,62.56 -56.920000000,62.56 -56.940000000,62.56 -56.960000000,62.56 -56.980000000,62.56 -57.000000000,62.56 -57.020000000,62.56 -57.040000000,62.56 -57.060000000,62.56 -57.080000000,62.56 -57.100000000,62.56 -57.120000000,62.56 -57.140000000,62.56 -57.160000000,62.56 -57.180000000,62.56 -57.200000000,62.56 -57.220000000,62.56 -57.240000000,62.56 -57.260000000,62.56 -57.280000000,62.56 -57.300000000,62.56 -57.320000000,62.56 -57.340000000,62.56 -57.360000000,62.56 -57.380000000,62.56 -57.400000000,62.56 -57.420000000,62.56 -57.440000000,62.56 -57.460000000,62.56 -57.480000000,62.56 -57.500000000,62.56 -57.520000000,62.56 -57.540000000,62.56 -57.560000000,62.56 -57.580000000,62.56 -57.600000000,62.56 -57.620000000,62.56 -57.640000000,62.56 -57.660000000,62.56 -57.680000000,62.56 -57.700000000,62.56 -57.720000000,62.56 -57.740000000,62.56 -57.760000000,62.56 -57.780000000,62.56 -57.800000000,62.56 -57.820000000,62.56 -57.840000000,62.56 -57.860000000,62.56 -57.880000000,62.56 -57.900000000,62.56 -57.920000000,62.56 -57.940000000,62.56 -57.960000000,62.56 -57.980000000,62.56 -58.000000000,62.56 -58.020000000,62.56 -58.040000000,62.56 -58.060000000,62.56 -58.080000000,62.56 -58.100000000,62.56 -58.120000000,62.56 -58.140000000,62.56 -58.160000000,62.56 -58.180000000,62.56 -58.200000000,62.56 -58.220000000,62.56 -58.240000000,62.56 -58.260000000,62.56 -58.280000000,62.56 -58.300000000,62.56 -58.320000000,62.56 -58.340000000,62.56 -58.360000000,62.56 -58.380000000,62.56 -58.400000000,62.56 -58.420000000,62.56 -58.440000000,62.56 -58.460000000,62.56 -58.480000000,62.56 -58.500000000,62.56 -58.520000000,62.56 -58.540000000,62.56 -58.560000000,62.56 -58.580000000,62.56 -58.600000000,62.56 -58.620000000,62.56 -58.640000000,62.56 -58.660000000,62.56 -58.680000000,62.56 -58.700000000,62.56 -58.720000000,62.56 -58.740000000,62.56 -58.760000000,62.56 -58.780000000,62.56 -58.800000000,62.56 -58.820000000,62.56 -58.840000000,62.56 -58.860000000,62.56 -58.880000000,62.56 -58.900000000,62.56 -58.920000000,62.56 -58.940000000,62.56 -58.960000000,62.56 -58.980000000,62.56 -59.000000000,62.56 -59.020000000,62.56 -59.040000000,62.56 -59.060000000,62.56 -59.080000000,62.56 -59.100000000,62.56 -59.120000000,62.56 -59.140000000,62.56 -59.160000000,62.56 -59.180000000,62.56 -59.200000000,62.56 -59.220000000,62.56 -59.240000000,62.56 -59.260000000,62.56 -59.280000000,62.56 -59.300000000,62.56 -59.320000000,62.56 -59.340000000,62.56 -59.360000000,62.56 -59.380000000,62.56 -59.400000000,62.56 -59.420000000,62.56 -59.440000000,62.56 -59.460000000,62.56 -59.480000000,62.56 -59.500000000,62.56 -59.520000000,62.56 -59.540000000,62.56 -59.560000000,62.56 -59.580000000,62.56 -59.600000000,62.56 -59.620000000,62.56 -59.640000000,62.56 -59.660000000,62.56 -59.680000000,62.56 -59.700000000,62.56 -59.720000000,62.56 -59.740000000,62.56 -59.760000000,62.56 -59.780000000,62.56 -59.800000000,62.58 -59.820000000,62.6 -59.840000000,62.62 -59.860000000,62.64 -59.880000000,62.66 -59.900000000,62.68 -59.920000000,62.7 -59.940000000,62.72 -59.960000000,62.74 -59.980000000,62.76 -60.000000000,62.78 -60.020000000,62.8 -60.040000000,62.82 -60.060000000,62.84 -60.080000000,62.86 -60.100000000,62.88 -60.120000000,62.9 -60.140000000,62.92 -60.160000000,62.94 -60.180000000,62.96 -60.200000000,62.98 -60.220000000,63 -60.240000000,63.02 -60.260000000,63.04 -60.280000000,63.06 -60.300000000,63.08 -60.320000000,63.1 -60.340000000,63.12 -60.360000000,63.14 -60.380000000,63.16 -60.400000000,63.18 -60.420000000,63.2 -60.440000000,63.22 -60.460000000,63.24 -60.480000000,63.26 -60.500000000,63.28 -60.520000000,63.3 -60.540000000,63.32 -60.560000000,63.34 -60.580000000,63.36 -60.600000000,63.38 -60.620000000,63.4 -60.640000000,63.42 -60.660000000,63.44 -60.680000000,63.46 -60.700000000,63.48 -60.720000000,63.5 -60.740000000,63.52 -60.760000000,63.54 -60.780000000,63.56 -60.800000000,63.58 -60.800000000,63.6 -60.800000000,63.62 -60.800000000,63.64 -60.800000000,63.66 -60.800000000,63.68 -60.800000000,63.7 -60.800000000,63.72 -60.800000000,63.74 -60.800000000,63.76 -60.800000000,63.78 -60.800000000,63.8 -60.800000000,63.82 -60.800000000,63.84 -60.800000000,63.86 -60.800000000,63.88 -60.800000000,63.9 -60.800000000,63.92 -60.800000000,63.94 -60.800000000,63.96 -60.800000000,63.98 -60.800000000,64 -60.800000000,64.02 -60.800000000,64.04 -60.800000000,64.06 -60.800000000,64.08 -60.800000000,64.1 -60.800000000,64.12 -60.800000000,64.14 -60.800000000,64.16 -60.800000000,64.18 -60.800000000,64.2 -60.800000000,64.22 -60.800000000,64.24 -60.800000000,64.26 -60.800000000,64.28 -60.800000000,64.3 -60.800000000,64.32 -60.800000000,64.34 -60.800000000,64.36 -60.800000000,64.38 -60.800000000,64.4 -60.800000000,64.42 -60.800000000,64.44 -60.800000000,64.46 -60.800000000,64.48 -60.800000000,64.5 -60.800000000,64.52 -60.800000000,64.54 -60.800000000,64.56 -60.800000000,64.58 -60.800000000,64.6 -60.800000000,64.62 -60.800000000,64.64 -60.800000000,64.66 -60.800000000,64.68 -60.800000000,64.7 -60.800000000,64.72 -60.800000000,64.74 -60.800000000,64.76 -60.800000000,64.78 -60.800000000,64.8 -60.800000000,64.82 -60.800000000,64.84 -60.800000000,64.86 -60.800000000,64.88 -60.800000000,64.9 -60.800000000,64.92 -60.800000000,64.94 -60.800000000,64.96 -60.800000000,64.98 -60.800000000,65 -60.800000000,65.02 -60.800000000,65.04 -60.800000000,65.06 -60.800000000,65.08 -60.800000000,65.1 -60.800000000,65.12 -60.800000000,65.14 -60.800000000,65.16 -60.800000000,65.18 -60.800000000,65.2 -60.800000000,65.22 -60.800000000,65.24 -60.800000000,65.26 -60.800000000,65.28 -60.800000000,65.3 -60.800000000,65.32 -60.800000000,65.34 -60.800000000,65.36 -60.800000000,65.38 -60.800000000,65.4 -60.800000000,65.42 -60.800000000,65.44 -60.800000000,65.46 -60.800000000,65.48 -60.800000000,65.5 -60.800000000,65.52 -60.800000000,65.54 -60.800000000,65.56 -60.800000000,65.58 -60.800000000,65.6 -60.800000000,65.62 -60.800000000,65.64 -60.800000000,65.66 -60.800000000,65.68 -60.800000000,65.7 -60.800000000,65.72 -60.800000000,65.74 -60.800000000,65.76 -60.800000000,65.78 -60.800000000,65.8 -60.800000000,65.82 -60.800000000,65.84 -60.800000000,65.86 -60.800000000,65.88 -60.800000000,65.9 -60.800000000,65.92 -60.800000000,65.94 -60.800000000,65.96 -60.800000000,65.98 -60.800000000,66 -60.800000000,66.02 -60.800000000,66.04 -60.800000000,66.06 -60.800000000,66.08 -60.800000000,66.1 -60.800000000,66.12 -60.800000000,66.14 -60.800000000,66.16 -60.800000000,66.18 -60.800000000,66.2 -60.800000000,66.22 -60.800000000,66.24 -60.800000000,66.26 -60.800000000,66.28 -60.800000000,66.3 -60.800000000,66.32 -60.800000000,66.34 -60.800000000,66.36 -60.800000000,66.38 -60.800000000,66.4 -60.800000000,66.42 -60.800000000,66.44 -60.800000000,66.46 -60.800000000,66.48 -60.800000000,66.5 -60.800000000,66.52 -60.800000000,66.54 -60.800000000,66.56 -60.800000000,66.58 -60.800000000,66.6 -60.800000000,66.62 -60.800000000,66.64 -60.800000000,66.66 -60.800000000,66.68 -60.800000000,66.7 -60.800000000,66.72 -60.800000000,66.74 -60.800000000,66.76 -60.800000000,66.78 -60.800000000,66.8 -60.800000000,66.82 -60.800000000,66.84 -60.800000000,66.86 -60.800000000,66.88 -60.800000000,66.9 -60.800000000,66.92 -60.800000000,66.94 -60.800000000,66.96 -60.800000000,66.98 -60.800000000,67 -60.800000000,67.02 -60.800000000,67.04 -60.800000000,67.06 -60.800000000,67.08 -60.800000000,67.1 -60.800000000,67.12 -60.800000000,67.14 -60.800000000,67.16 -60.800000000,67.18 -60.800000000,67.2 -60.800000000,67.22 -60.800000000,67.24 -60.800000000,67.26 -60.800000000,67.28 -60.800000000,67.3 -60.800000000,67.32 -60.800000000,67.34 -60.800000000,67.36 -60.800000000,67.38 -60.800000000,67.4 -60.800000000,67.42 -60.800000000,67.44 -60.800000000,67.46 -60.800000000,67.48 -60.800000000,67.5 -60.800000000,67.52 -60.800000000,67.54 -60.800000000,67.56 -60.800000000,67.58 -60.800000000,67.6 -60.800000000,67.62 -60.800000000,67.64 -60.800000000,67.66 -60.800000000,67.68 -60.800000000,67.7 -60.800000000,67.72 -60.800000000,67.74 -60.800000000,67.76 -60.800000000,67.78 -60.800000000,67.8 -60.800000000,67.82 -60.800000000,67.84 -60.800000000,67.86 -60.800000000,67.88 -60.800000000,67.9 -60.800000000,67.92 -60.800000000,67.94 -60.800000000,67.96 -60.800000000,67.98 -60.800000000,68 -60.800000000,68.02 -60.800000000,68.04 -60.800000000,68.06 -60.800000000,68.08 -60.800000000,68.1 -60.800000000,68.12 -60.800000000,68.14 -60.800000000,68.16 -60.800000000,68.18 -60.800000000,68.2 -60.800000000,68.22 -60.800000000,68.24 -60.800000000,68.26 -60.800000000,68.28 -60.800000000,68.3 -60.800000000,68.32 -60.800000000,68.34 -60.800000000,68.36 -60.800000000,68.38 -60.800000000,68.4 -60.800000000,68.42 -60.800000000,68.44 -60.800000000,68.46 -60.800000000,68.48 -60.800000000,68.5 -60.800000000,68.52 -60.800000000,68.54 -60.800000000,68.56 -60.800000000,68.58 -60.800000000,68.6 -60.800000000,68.62 -60.800000000,68.64 -60.800000000,68.66 -60.800000000,68.68 -60.800000000,68.7 -60.800000000,68.72 -60.800000000,68.74 -60.800000000,68.76 -60.800000000,68.78 -60.800000000,68.8 -60.800000000,68.82 -60.800000000,68.84 -60.800000000,68.86 -60.800000000,68.88 -60.800000000,68.9 -60.800000000,68.92 -60.800000000,68.94 -60.800000000,68.96 -60.800000000,68.98 -60.800000000,69 -60.800000000,69.02 -60.800000000,69.04 -60.800000000,69.06 -60.800000000,69.08 -60.800000000,69.1 -60.800000000,69.12 -60.800000000,69.14 -60.800000000,69.16 -60.800000000,69.18 -60.800000000,69.2 -60.800000000,69.22 -60.800000000,69.24 -60.800000000,69.26 -60.800000000,69.28 -60.800000000,69.3 -60.800000000,69.32 -60.800000000,69.34 -60.800000000,69.36 -60.800000000,69.38 -60.800000000,69.4 -60.800000000,69.42 -60.800000000,69.44 -60.800000000,69.46 -60.800000000,69.48 -60.800000000,69.5 -60.800000000,69.52 -60.800000000,69.54 -60.800000000,69.56 -60.800000000,69.58 -60.800000000,69.6 -60.800000000,69.62 -60.800000000,69.64 -60.800000000,69.66 -60.800000000,69.68 -60.800000000,69.7 -60.800000000,69.72 -60.800000000,69.74 -60.800000000,69.76 -60.800000000,69.78 -60.800000000,69.8 -60.800000000,69.82 -60.800000000,69.84 -60.800000000,69.86 -60.800000000,69.88 -60.800000000,69.9 -60.800000000,69.92 -60.800000000,69.94 -60.800000000,69.96 -60.800000000,69.98 -60.800000000,70 -60.800000000,70.02 -60.800000000,70.04 -60.800000000,70.06 -60.800000000,70.08 -60.800000000,70.1 -60.800000000,70.12 -60.800000000,70.14 -60.800000000,70.16 -60.800000000,70.18 -60.800000000,70.2 -60.800000000,70.22 -60.800000000,70.24 -60.800000000,70.26 -60.800000000,70.28 -60.800000000,70.3 -60.800000000,70.32 -60.800000000,70.34 -60.800000000,70.36 -60.800000000,70.38 -60.800000000,70.4 -60.800000000,70.42 -60.800000000,70.44 -60.800000000,70.46 -60.800000000,70.48 -60.800000000,70.5 -60.800000000,70.52 -60.800000000,70.54 -60.800000000,70.56 -60.800000000,70.58 -60.800000000,70.6 -60.800000000,70.62 -60.800000000,70.64 -60.800000000,70.66 -60.800000000,70.68 -60.800000000,70.7 -60.800000000,70.72 -60.800000000,70.74 -60.800000000,70.76 -60.800000000,70.78 -60.800000000,70.8 -60.800000000,70.82 -60.800000000,70.84 -60.800000000,70.86 -60.800000000,70.88 -60.800000000,70.9 -60.800000000,70.92 -60.800000000,70.94 -60.800000000,70.96 -60.800000000,70.98 -60.800000000,71 -60.800000000,71.02 -60.800000000,71.04 -60.800000000,71.06 -60.800000000,71.08 -60.800000000,71.1 -60.800000000,71.12 -60.800000000,71.14 -60.800000000,71.16 -60.800000000,71.18 -60.800000000,71.2 -60.800000000,71.22 -60.800000000,71.24 -60.800000000,71.26 -60.800000000,71.28 -60.800000000,71.3 -60.800000000,71.32 -60.800000000,71.34 -60.800000000,71.36 -60.800000000,71.38 -60.800000000,71.4 -60.800000000,71.42 -60.800000000,71.44 -60.800000000,71.46 -60.800000000,71.48 -60.800000000,71.5 -60.800000000,71.52 -60.800000000,71.54 -60.800000000,71.56 -60.800000000,71.58 -60.800000000,71.6 -60.800000000,71.62 -60.800000000,71.64 -60.800000000,71.66 -60.800000000,71.68 -60.800000000,71.7 -60.800000000,71.72 -60.800000000,71.74 -60.800000000,71.76 -60.800000000,71.78 -60.800000000,71.8 -60.800000000,71.82 -60.800000000,71.84 -60.800000000,71.86 -60.800000000,71.88 -60.800000000,71.9 -60.800000000,71.92 -60.800000000,71.94 -60.800000000,71.96 -60.800000000,71.98 -60.800000000,72 -60.800000000,72.02 -60.800000000,72.04 -60.800000000,72.06 -60.800000000,72.08 -60.800000000,72.1 -60.800000000,72.12 -60.800000000,72.14 -60.800000000,72.16 -60.800000000,72.18 -60.800000000,72.2 -60.800000000,72.22 -60.800000000,72.24 -60.800000000,72.26 -60.800000000,72.28 -60.800000000,72.3 -60.800000000,72.32 -60.800000000,72.34 -60.800000000,72.36 -60.800000000,72.38 -60.800000000,72.4 -60.800000000,72.42 -60.800000000,72.44 -60.800000000,72.46 -60.800000000,72.48 -60.800000000,72.5 -60.800000000,72.52 -60.800000000,72.54 -60.800000000,72.56 -60.800000000,72.58 -60.800000000,72.6 -60.800000000,72.62 -60.800000000,72.64 -60.800000000,72.66 -60.800000000,72.68 -60.800000000,72.7 -60.800000000,72.72 -60.800000000,72.74 -60.800000000,72.76 -60.800000000,72.78 -60.800000000,72.8 -60.800000000,72.82 -60.800000000,72.84 -60.800000000,72.86 -60.800000000,72.88 -60.800000000,72.9 -60.800000000,72.92 -60.800000000,72.94 -60.800000000,72.96 -60.800000000,72.98 -60.800000000,73 -60.800000000,73.02 -60.800000000,73.04 -60.800000000,73.06 -60.800000000,73.08 -60.800000000,73.1 -60.800000000,73.12 -60.800000000,73.14 -60.800000000,73.16 -60.800000000,73.18 -60.800000000,73.2 -60.800000000,73.22 -60.800000000,73.24 -60.800000000,73.26 -60.800000000,73.28 -60.800000000,73.3 -60.800000000,73.32 -60.800000000,73.34 -60.800000000,73.36 -60.800000000,73.38 -60.800000000,73.4 -60.800000000,73.42 -60.800000000,73.44 -60.800000000,73.46 -60.800000000,73.48 -60.800000000,73.5 -60.800000000,73.52 -60.800000000,73.54 -60.800000000,73.56 -60.800000000,73.58 -60.800000000,73.6 -60.800000000,73.62 -60.800000000,73.64 -60.800000000,73.66 -60.800000000,73.68 -60.800000000,73.7 -60.800000000,73.72 -60.800000000,73.74 -60.800000000,73.76 -60.800000000,73.78 -60.800000000,73.8 -60.800000000,73.82 -60.800000000,73.84 -60.800000000,73.86 -60.800000000,73.88 -60.800000000,73.9 -60.800000000,73.92 -60.820000000,73.94 -60.840000000,73.96 -60.860000000,73.98 -60.880000000,74 -60.900000000,74.02 -60.920000000,74.04 -60.940000000,74.06 -60.960000000,74.08 -60.980000000,74.1 -61.000000000,74.12 -61.020000000,74.14 -61.040000000,74.16 -61.060000000,74.18 -61.080000000,74.2 -61.100000000,74.22 -61.120000000,74.24 -61.140000000,74.26 -61.160000000,74.28 -61.180000000,74.3 -61.200000000,74.32 -61.220000000,74.34 -61.240000000,74.36 -61.260000000,74.38 -61.280000000,74.4 -61.300000000,74.42 -61.320000000,74.44 -61.340000000,74.46 -61.360000000,74.48 -61.380000000,74.5 -61.400000000,74.52 -61.420000000,74.54 -61.440000000,74.56 -61.460000000,74.58 -61.480000000,74.6 -61.500000000,74.62 -61.520000000,74.64 -61.540000000,74.66 -61.560000000,74.68 -61.580000000,74.7 -61.600000000,74.72 -61.620000000,74.74 -61.640000000,74.76 -61.660000000,74.78 -61.680000000,74.8 -61.700000000,74.82 -61.720000000,74.84 -61.740000000,74.86 -61.760000000,74.88 -61.780000000,74.9 -61.800000000,74.92 -61.820000000,74.94 -61.840000000,74.94 -61.860000000,74.94 -61.880000000,74.94 -61.900000000,74.94 -61.920000000,74.94 -61.940000000,74.94 -61.960000000,74.94 -61.980000000,74.94 -62.000000000,74.94 -62.020000000,74.94 -62.040000000,74.94 -62.060000000,74.94 -62.080000000,74.94 -62.100000000,74.94 -62.120000000,74.94 -62.140000000,74.94 -62.160000000,74.94 -62.180000000,74.94 -62.200000000,74.94 -62.220000000,74.94 -62.240000000,74.94 -62.260000000,74.94 -62.280000000,74.94 -62.300000000,74.94 -62.320000000,74.94 -62.340000000,74.94 -62.360000000,74.94 -62.380000000,74.94 -62.400000000,74.94 -62.420000000,74.94 -62.440000000,74.94 -62.460000000,74.94 -62.480000000,74.94 -62.500000000,74.94 -62.520000000,74.94 -62.540000000,74.94 -62.560000000,74.94 -62.580000000,74.94 -62.600000000,74.94 -62.620000000,74.94 -62.640000000,74.94 -62.660000000,74.94 -62.680000000,74.94 -62.700000000,74.94 -62.720000000,74.94 -62.740000000,74.94 -62.760000000,74.94 -62.780000000,74.94 -62.800000000,74.94 -62.820000000,74.94 -62.840000000,74.94 -62.860000000,74.94 -62.880000000,74.94 -62.900000000,74.94 -62.920000000,74.94 -62.940000000,74.94 -62.960000000,74.94 -62.980000000,74.94 -63.000000000,74.94
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/old/checksymmetry.sh Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,40 @@ +#!/bin/bash + +# Test that aligning A-B gives the same results as aligning B-A + +mydir=$(dirname "$0") + +sonic-annotator --minversion 1.1 || exit 1 + +file1="$1" +file2="$2" + +usage() { + echo "Usage: $0 a.wav b.wav" + exit 2 +} + +test -n "$file1" || usage +test -f "$file1" || usage +test -n "$file2" || usage +test -f "$file2" || usage + +VAMP_PATH="${mydir}/../.." \ + sonic-annotator \ + -d vamp:match-vamp-plugin:match:a_b \ + --multiplex \ + "$file1" \ + "$file2" \ + -w csv --csv-stdout 2>/dev/null | sed 's/^"[^"]*"//' > /tmp/1_$$ || exit 1 + +VAMP_PATH="${mydir}/../.." \ + sonic-annotator \ + -d vamp:match-vamp-plugin:match:b_a \ + --multiplex \ + "$file2" \ + "$file1" \ + -w csv --csv-stdout 2>/dev/null | sed 's/^"[^"]*"//' > /tmp/2_$$ || exit 1 + +sdiff -w 78 /tmp/1_$$ /tmp/2_$$ && echo Passed + +rm /tmp/1_$$ /tmp/2_$$
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/old/expected.csv Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,5369 @@ +0.000000000,0.02 +0.000000000,0.04 +0.000000000,0.06 +0.000000000,0.08 +0.000000000,0.1 +0.000000000,0.12 +0.000000000,0.14 +0.000000000,0.16 +0.000000000,0.18 +0.000000000,0.2 +0.000000000,0.22 +0.000000000,0.24 +0.000000000,0.26 +0.000000000,0.28 +0.000000000,0.3 +0.000000000,0.32 +0.000000000,0.34 +0.000000000,0.36 +0.000000000,0.38 +0.000000000,0.4 +0.000000000,0.42 +0.000000000,0.44 +0.000000000,0.46 +0.000000000,0.48 +0.000000000,0.5 +0.000000000,0.52 +0.000000000,0.54 +0.000000000,0.56 +0.000000000,0.58 +0.000000000,0.6 +0.000000000,0.62 +0.000000000,0.64 +0.000000000,0.66 +0.000000000,0.68 +0.000000000,0.7 +0.000000000,0.72 +0.000000000,0.74 +0.000000000,0.76 +0.000000000,0.78 +0.000000000,0.8 +0.000000000,0.82 +0.000000000,0.84 +0.000000000,0.86 +0.000000000,0.88 +0.000000000,0.9 +0.000000000,0.92 +0.000000000,0.94 +0.000000000,0.96 +0.000000000,0.98 +0.000000000,1 +0.000000000,1.02 +0.000000000,1.04 +0.000000000,1.06 +0.000000000,1.08 +0.000000000,1.1 +0.000000000,1.12 +0.000000000,1.14 +0.000000000,1.16 +0.000000000,1.18 +0.000000000,1.2 +0.000000000,1.22 +0.000000000,1.24 +0.000000000,1.26 +0.000000000,1.28 +0.000000000,1.3 +0.000000000,1.32 +0.000000000,1.34 +0.000000000,1.36 +0.000000000,1.38 +0.000000000,1.4 +0.000000000,1.42 +0.000000000,1.44 +0.000000000,1.46 +0.000000000,1.48 +0.000000000,1.5 +0.000000000,1.52 +0.000000000,1.54 +0.000000000,1.56 +0.020000000,1.58 +0.040000000,1.6 +0.060000000,1.62 +0.080000000,1.64 +0.100000000,1.66 +0.120000000,1.68 +0.140000000,1.7 +0.160000000,1.72 +0.180000000,1.74 +0.200000000,1.76 +0.220000000,1.78 +0.240000000,1.8 +0.260000000,1.82 +0.280000000,1.84 +0.300000000,1.86 +0.320000000,1.88 +0.340000000,1.9 +0.360000000,1.92 +0.380000000,1.94 +0.400000000,1.96 +0.420000000,1.98 +0.440000000,2 +0.460000000,2.02 +0.480000000,2.04 +0.500000000,2.06 +0.520000000,2.08 +0.540000000,2.1 +0.560000000,2.12 +0.580000000,2.14 +0.600000000,2.16 +0.620000000,2.18 +0.640000000,2.2 +0.660000000,2.22 +0.680000000,2.24 +0.700000000,2.26 +0.720000000,2.28 +0.740000000,2.3 +0.760000000,2.32 +0.780000000,2.34 +0.800000000,2.36 +0.820000000,2.38 +0.840000000,2.4 +0.860000000,2.42 +0.880000000,2.44 +0.900000000,2.46 +0.920000000,2.48 +0.940000000,2.5 +0.960000000,2.52 +0.980000000,2.54 +1.000000000,2.56 +1.020000000,2.58 +1.040000000,2.6 +1.060000000,2.62 +1.080000000,2.64 +1.100000000,2.64 +1.120000000,2.64 +1.140000000,2.66 +1.160000000,2.68 +1.180000000,2.7 +1.200000000,2.72 +1.220000000,2.74 +1.240000000,2.76 +1.260000000,2.78 +1.280000000,2.8 +1.300000000,2.82 +1.320000000,2.84 +1.340000000,2.86 +1.360000000,2.88 +1.380000000,2.9 +1.400000000,2.92 +1.420000000,2.94 +1.440000000,2.96 +1.460000000,2.98 +1.480000000,3 +1.500000000,3.02 +1.520000000,3.04 +1.540000000,3.06 +1.560000000,3.08 +1.580000000,3.1 +1.600000000,3.12 +1.620000000,3.12 +1.640000000,3.12 +1.660000000,3.12 +1.680000000,3.12 +1.700000000,3.12 +1.720000000,3.12 +1.740000000,3.12 +1.760000000,3.12 +1.780000000,3.12 +1.800000000,3.12 +1.820000000,3.14 +1.840000000,3.16 +1.860000000,3.18 +1.880000000,3.2 +1.900000000,3.22 +1.920000000,3.24 +1.940000000,3.26 +1.960000000,3.28 +1.980000000,3.3 +2.000000000,3.32 +2.020000000,3.34 +2.040000000,3.36 +2.060000000,3.38 +2.080000000,3.4 +2.100000000,3.42 +2.120000000,3.44 +2.140000000,3.46 +2.160000000,3.48 +2.180000000,3.5 +2.200000000,3.52 +2.220000000,3.54 +2.240000000,3.56 +2.260000000,3.58 +2.280000000,3.6 +2.300000000,3.62 +2.320000000,3.64 +2.340000000,3.66 +2.360000000,3.68 +2.380000000,3.7 +2.400000000,3.72 +2.420000000,3.74 +2.440000000,3.76 +2.460000000,3.78 +2.480000000,3.8 +2.500000000,3.82 +2.520000000,3.84 +2.540000000,3.86 +2.560000000,3.88 +2.580000000,3.88 +2.600000000,3.88 +2.620000000,3.88 +2.640000000,3.88 +2.660000000,3.88 +2.680000000,3.88 +2.700000000,3.88 +2.720000000,3.88 +2.740000000,3.88 +2.760000000,3.88 +2.780000000,3.88 +2.800000000,3.9 +2.820000000,3.92 +2.840000000,3.94 +2.860000000,3.96 +2.880000000,3.98 +2.900000000,4 +2.920000000,4.02 +2.940000000,4.04 +2.960000000,4.06 +2.980000000,4.08 +3.000000000,4.1 +3.020000000,4.12 +3.040000000,4.14 +3.060000000,4.16 +3.080000000,4.18 +3.100000000,4.2 +3.120000000,4.22 +3.140000000,4.24 +3.160000000,4.26 +3.180000000,4.28 +3.200000000,4.3 +3.220000000,4.32 +3.240000000,4.34 +3.260000000,4.36 +3.280000000,4.38 +3.300000000,4.4 +3.320000000,4.42 +3.340000000,4.44 +3.360000000,4.46 +3.380000000,4.48 +3.400000000,4.5 +3.420000000,4.52 +3.440000000,4.54 +3.460000000,4.56 +3.480000000,4.58 +3.500000000,4.6 +3.520000000,4.62 +3.540000000,4.62 +3.560000000,4.62 +3.580000000,4.62 +3.600000000,4.64 +3.620000000,4.66 +3.640000000,4.68 +3.660000000,4.7 +3.680000000,4.72 +3.700000000,4.74 +3.720000000,4.76 +3.740000000,4.78 +3.760000000,4.8 +3.780000000,4.82 +3.800000000,4.84 +3.820000000,4.86 +3.840000000,4.88 +3.860000000,4.9 +3.880000000,4.9 +3.900000000,4.92 +3.920000000,4.92 +3.940000000,4.92 +3.960000000,4.92 +3.980000000,4.92 +4.000000000,4.92 +4.020000000,4.92 +4.040000000,4.92 +4.060000000,4.92 +4.080000000,4.92 +4.100000000,4.92 +4.120000000,4.92 +4.140000000,4.92 +4.160000000,4.92 +4.180000000,4.92 +4.200000000,4.92 +4.220000000,4.94 +4.240000000,4.96 +4.260000000,4.98 +4.280000000,5 +4.300000000,5.02 +4.320000000,5.04 +4.340000000,5.06 +4.360000000,5.08 +4.380000000,5.1 +4.400000000,5.1 +4.420000000,5.1 +4.440000000,5.12 +4.460000000,5.14 +4.480000000,5.16 +4.500000000,5.18 +4.520000000,5.2 +4.540000000,5.22 +4.560000000,5.24 +4.580000000,5.26 +4.600000000,5.28 +4.620000000,5.3 +4.640000000,5.32 +4.660000000,5.32 +4.680000000,5.32 +4.700000000,5.32 +4.720000000,5.32 +4.740000000,5.34 +4.760000000,5.36 +4.780000000,5.36 +4.800000000,5.36 +4.820000000,5.36 +4.840000000,5.36 +4.860000000,5.38 +4.880000000,5.4 +4.900000000,5.4 +4.920000000,5.42 +4.940000000,5.44 +4.960000000,5.46 +4.980000000,5.48 +5.000000000,5.5 +5.020000000,5.52 +5.040000000,5.54 +5.060000000,5.56 +5.080000000,5.56 +5.100000000,5.58 +5.120000000,5.58 +5.140000000,5.58 +5.160000000,5.6 +5.180000000,5.62 +5.200000000,5.64 +5.220000000,5.66 +5.240000000,5.68 +5.260000000,5.7 +5.280000000,5.72 +5.300000000,5.74 +5.320000000,5.76 +5.340000000,5.78 +5.360000000,5.78 +5.380000000,5.8 +5.400000000,5.82 +5.420000000,5.82 +5.440000000,5.82 +5.460000000,5.82 +5.480000000,5.82 +5.500000000,5.82 +5.520000000,5.84 +5.540000000,5.86 +5.560000000,5.88 +5.580000000,5.9 +5.600000000,5.92 +5.620000000,5.94 +5.640000000,5.96 +5.660000000,5.98 +5.680000000,6 +5.700000000,6.02 +5.720000000,6.04 +5.740000000,6.06 +5.760000000,6.08 +5.780000000,6.1 +5.800000000,6.12 +5.820000000,6.12 +5.840000000,6.12 +5.860000000,6.12 +5.880000000,6.14 +5.900000000,6.16 +5.920000000,6.18 +5.940000000,6.2 +5.960000000,6.22 +5.980000000,6.24 +6.000000000,6.26 +6.020000000,6.28 +6.040000000,6.3 +6.060000000,6.32 +6.080000000,6.34 +6.100000000,6.36 +6.120000000,6.38 +6.140000000,6.4 +6.160000000,6.42 +6.180000000,6.44 +6.200000000,6.46 +6.220000000,6.48 +6.240000000,6.5 +6.260000000,6.52 +6.280000000,6.54 +6.300000000,6.56 +6.320000000,6.58 +6.340000000,6.6 +6.360000000,6.62 +6.380000000,6.64 +6.400000000,6.66 +6.420000000,6.68 +6.440000000,6.7 +6.460000000,6.72 +6.480000000,6.74 +6.500000000,6.76 +6.520000000,6.78 +6.540000000,6.8 +6.560000000,6.82 +6.580000000,6.84 +6.600000000,6.86 +6.620000000,6.88 +6.640000000,6.9 +6.660000000,6.92 +6.680000000,6.94 +6.700000000,6.96 +6.720000000,6.98 +6.740000000,7 +6.760000000,7.02 +6.780000000,7.04 +6.800000000,7.06 +6.820000000,7.08 +6.840000000,7.1 +6.860000000,7.12 +6.880000000,7.14 +6.900000000,7.16 +6.920000000,7.18 +6.940000000,7.2 +6.960000000,7.22 +6.980000000,7.24 +7.000000000,7.26 +7.020000000,7.28 +7.040000000,7.3 +7.060000000,7.32 +7.080000000,7.34 +7.100000000,7.36 +7.120000000,7.38 +7.140000000,7.4 +7.160000000,7.42 +7.180000000,7.44 +7.200000000,7.46 +7.220000000,7.48 +7.240000000,7.5 +7.260000000,7.52 +7.280000000,7.54 +7.300000000,7.56 +7.320000000,7.58 +7.340000000,7.6 +7.360000000,7.62 +7.380000000,7.64 +7.400000000,7.66 +7.420000000,7.68 +7.440000000,7.7 +7.460000000,7.72 +7.480000000,7.74 +7.500000000,7.76 +7.520000000,7.78 +7.540000000,7.8 +7.560000000,7.82 +7.580000000,7.82 +7.600000000,7.82 +7.620000000,7.82 +7.640000000,7.82 +7.660000000,7.82 +7.680000000,7.82 +7.700000000,7.82 +7.720000000,7.82 +7.740000000,7.82 +7.760000000,7.82 +7.780000000,7.82 +7.800000000,7.82 +7.820000000,7.82 +7.840000000,7.82 +7.860000000,7.82 +7.880000000,7.82 +7.900000000,7.82 +7.920000000,7.82 +7.940000000,7.82 +7.960000000,7.82 +7.980000000,7.82 +8.000000000,7.84 +8.020000000,7.84 +8.040000000,7.84 +8.060000000,7.84 +8.080000000,7.84 +8.100000000,7.84 +8.120000000,7.84 +8.140000000,7.84 +8.160000000,7.84 +8.180000000,7.84 +8.200000000,7.86 +8.220000000,7.88 +8.240000000,7.9 +8.260000000,7.92 +8.280000000,7.94 +8.300000000,7.96 +8.320000000,7.98 +8.340000000,7.98 +8.360000000,7.98 +8.380000000,7.98 +8.400000000,7.98 +8.420000000,8 +8.440000000,8.02 +8.460000000,8.04 +8.480000000,8.06 +8.500000000,8.08 +8.520000000,8.1 +8.540000000,8.12 +8.560000000,8.14 +8.580000000,8.16 +8.600000000,8.18 +8.620000000,8.2 +8.640000000,8.2 +8.660000000,8.2 +8.680000000,8.2 +8.700000000,8.2 +8.720000000,8.2 +8.740000000,8.2 +8.760000000,8.22 +8.780000000,8.24 +8.800000000,8.26 +8.820000000,8.26 +8.840000000,8.26 +8.860000000,8.28 +8.880000000,8.28 +8.900000000,8.28 +8.920000000,8.3 +8.940000000,8.3 +8.960000000,8.32 +8.980000000,8.34 +9.000000000,8.36 +9.020000000,8.36 +9.040000000,8.36 +9.060000000,8.36 +9.080000000,8.36 +9.100000000,8.36 +9.120000000,8.36 +9.140000000,8.36 +9.160000000,8.36 +9.180000000,8.36 +9.200000000,8.36 +9.220000000,8.36 +9.240000000,8.36 +9.260000000,8.36 +9.280000000,8.36 +9.300000000,8.36 +9.320000000,8.36 +9.340000000,8.36 +9.360000000,8.36 +9.380000000,8.36 +9.400000000,8.36 +9.420000000,8.36 +9.440000000,8.36 +9.460000000,8.36 +9.480000000,8.36 +9.500000000,8.36 +9.520000000,8.36 +9.540000000,8.36 +9.560000000,8.36 +9.580000000,8.36 +9.600000000,8.36 +9.620000000,8.36 +9.640000000,8.36 +9.660000000,8.36 +9.680000000,8.36 +9.700000000,8.36 +9.720000000,8.36 +9.740000000,8.36 +9.760000000,8.36 +9.780000000,8.36 +9.800000000,8.36 +9.820000000,8.36 +9.840000000,8.36 +9.860000000,8.36 +9.880000000,8.36 +9.900000000,8.36 +9.920000000,8.36 +9.940000000,8.36 +9.960000000,8.36 +9.980000000,8.36 +10.000000000,8.36 +10.020000000,8.36 +10.040000000,8.36 +10.060000000,8.36 +10.080000000,8.36 +10.100000000,8.36 +10.120000000,8.36 +10.140000000,8.36 +10.160000000,8.36 +10.180000000,8.36 +10.200000000,8.36 +10.220000000,8.36 +10.240000000,8.36 +10.260000000,8.36 +10.280000000,8.38 +10.300000000,8.4 +10.320000000,8.42 +10.340000000,8.44 +10.360000000,8.46 +10.380000000,8.48 +10.400000000,8.5 +10.420000000,8.52 +10.440000000,8.54 +10.460000000,8.54 +10.480000000,8.56 +10.500000000,8.56 +10.520000000,8.56 +10.540000000,8.56 +10.560000000,8.56 +10.580000000,8.56 +10.600000000,8.56 +10.620000000,8.56 +10.640000000,8.58 +10.660000000,8.6 +10.680000000,8.6 +10.700000000,8.62 +10.720000000,8.62 +10.740000000,8.62 +10.760000000,8.64 +10.780000000,8.66 +10.800000000,8.68 +10.820000000,8.7 +10.840000000,8.7 +10.860000000,8.7 +10.880000000,8.72 +10.900000000,8.74 +10.920000000,8.76 +10.940000000,8.76 +10.960000000,8.76 +10.980000000,8.78 +11.000000000,8.78 +11.020000000,8.78 +11.040000000,8.8 +11.060000000,8.8 +11.080000000,8.82 +11.100000000,8.82 +11.120000000,8.82 +11.140000000,8.82 +11.160000000,8.82 +11.180000000,8.82 +11.200000000,8.82 +11.220000000,8.82 +11.240000000,8.82 +11.260000000,8.82 +11.280000000,8.82 +11.300000000,8.82 +11.320000000,8.82 +11.340000000,8.82 +11.360000000,8.82 +11.380000000,8.82 +11.400000000,8.82 +11.420000000,8.82 +11.440000000,8.84 +11.460000000,8.84 +11.480000000,8.84 +11.500000000,8.84 +11.520000000,8.84 +11.540000000,8.84 +11.560000000,8.84 +11.580000000,8.84 +11.600000000,8.84 +11.620000000,8.84 +11.640000000,8.86 +11.660000000,8.86 +11.680000000,8.86 +11.700000000,8.88 +11.720000000,8.88 +11.740000000,8.88 +11.760000000,8.88 +11.780000000,8.88 +11.800000000,8.88 +11.820000000,8.88 +11.840000000,8.88 +11.860000000,8.88 +11.880000000,8.88 +11.900000000,8.88 +11.920000000,8.88 +11.940000000,8.88 +11.960000000,8.88 +11.980000000,8.88 +12.000000000,8.88 +12.020000000,8.88 +12.040000000,8.88 +12.060000000,8.88 +12.080000000,8.88 +12.100000000,8.88 +12.120000000,8.88 +12.140000000,8.88 +12.160000000,8.88 +12.180000000,8.88 +12.200000000,8.88 +12.220000000,8.88 +12.240000000,8.88 +12.260000000,8.88 +12.280000000,8.88 +12.300000000,8.88 +12.320000000,8.88 +12.340000000,8.88 +12.360000000,8.88 +12.380000000,8.88 +12.400000000,8.88 +12.420000000,8.88 +12.440000000,8.88 +12.460000000,8.88 +12.480000000,8.88 +12.500000000,8.88 +12.520000000,8.88 +12.540000000,8.9 +12.560000000,8.92 +12.580000000,8.94 +12.600000000,8.96 +12.620000000,8.98 +12.640000000,8.98 +12.660000000,9 +12.680000000,9 +12.700000000,9 +12.720000000,9 +12.740000000,9 +12.760000000,9 +12.780000000,9 +12.800000000,9 +12.820000000,9 +12.840000000,9 +12.860000000,9 +12.880000000,9 +12.900000000,9.02 +12.920000000,9.04 +12.940000000,9.06 +12.960000000,9.08 +12.980000000,9.1 +13.000000000,9.12 +13.020000000,9.14 +13.040000000,9.16 +13.060000000,9.18 +13.080000000,9.2 +13.100000000,9.22 +13.120000000,9.24 +13.140000000,9.26 +13.160000000,9.28 +13.180000000,9.3 +13.200000000,9.3 +13.220000000,9.32 +13.240000000,9.34 +13.260000000,9.36 +13.280000000,9.38 +13.300000000,9.38 +13.320000000,9.38 +13.340000000,9.38 +13.360000000,9.4 +13.380000000,9.42 +13.400000000,9.44 +13.420000000,9.46 +13.440000000,9.48 +13.460000000,9.5 +13.480000000,9.52 +13.500000000,9.52 +13.520000000,9.54 +13.540000000,9.56 +13.560000000,9.58 +13.580000000,9.58 +13.600000000,9.58 +13.620000000,9.58 +13.640000000,9.58 +13.660000000,9.58 +13.680000000,9.58 +13.700000000,9.58 +13.720000000,9.58 +13.740000000,9.6 +13.760000000,9.62 +13.780000000,9.62 +13.800000000,9.62 +13.820000000,9.64 +13.840000000,9.66 +13.860000000,9.68 +13.880000000,9.68 +13.900000000,9.68 +13.920000000,9.68 +13.940000000,9.68 +13.960000000,9.68 +13.980000000,9.68 +14.000000000,9.68 +14.020000000,9.68 +14.040000000,9.68 +14.060000000,9.7 +14.080000000,9.72 +14.100000000,9.74 +14.120000000,9.74 +14.140000000,9.74 +14.160000000,9.74 +14.180000000,9.74 +14.200000000,9.74 +14.220000000,9.74 +14.240000000,9.76 +14.260000000,9.76 +14.280000000,9.76 +14.300000000,9.78 +14.320000000,9.8 +14.340000000,9.8 +14.360000000,9.8 +14.380000000,9.82 +14.400000000,9.84 +14.420000000,9.84 +14.440000000,9.84 +14.460000000,9.84 +14.480000000,9.84 +14.500000000,9.84 +14.520000000,9.84 +14.540000000,9.84 +14.560000000,9.84 +14.580000000,9.84 +14.600000000,9.84 +14.620000000,9.84 +14.640000000,9.84 +14.660000000,9.84 +14.680000000,9.84 +14.700000000,9.84 +14.720000000,9.84 +14.740000000,9.84 +14.760000000,9.84 +14.780000000,9.84 +14.800000000,9.84 +14.820000000,9.84 +14.840000000,9.86 +14.860000000,9.86 +14.880000000,9.86 +14.900000000,9.86 +14.920000000,9.86 +14.940000000,9.86 +14.960000000,9.86 +14.980000000,9.86 +15.000000000,9.86 +15.020000000,9.86 +15.040000000,9.86 +15.060000000,9.86 +15.080000000,9.86 +15.100000000,9.88 +15.120000000,9.88 +15.140000000,9.88 +15.160000000,9.88 +15.180000000,9.88 +15.200000000,9.88 +15.220000000,9.88 +15.240000000,9.9 +15.260000000,9.92 +15.280000000,9.92 +15.300000000,9.92 +15.320000000,9.92 +15.340000000,9.94 +15.360000000,9.96 +15.380000000,9.98 +15.400000000,10 +15.420000000,10.02 +15.440000000,10.04 +15.460000000,10.04 +15.480000000,10.04 +15.500000000,10.04 +15.520000000,10.04 +15.540000000,10.04 +15.560000000,10.04 +15.580000000,10.04 +15.600000000,10.04 +15.620000000,10.04 +15.640000000,10.04 +15.660000000,10.04 +15.680000000,10.04 +15.700000000,10.04 +15.720000000,10.04 +15.740000000,10.04 +15.760000000,10.04 +15.780000000,10.04 +15.800000000,10.04 +15.820000000,10.04 +15.840000000,10.04 +15.860000000,10.04 +15.880000000,10.06 +15.900000000,10.08 +15.920000000,10.1 +15.940000000,10.12 +15.960000000,10.14 +15.980000000,10.16 +16.000000000,10.18 +16.020000000,10.2 +16.040000000,10.22 +16.060000000,10.24 +16.080000000,10.26 +16.100000000,10.28 +16.120000000,10.3 +16.140000000,10.32 +16.160000000,10.34 +16.180000000,10.34 +16.200000000,10.36 +16.220000000,10.38 +16.240000000,10.4 +16.260000000,10.42 +16.280000000,10.44 +16.300000000,10.46 +16.320000000,10.46 +16.340000000,10.46 +16.360000000,10.46 +16.380000000,10.46 +16.400000000,10.46 +16.420000000,10.46 +16.440000000,10.46 +16.460000000,10.46 +16.480000000,10.46 +16.500000000,10.46 +16.520000000,10.46 +16.540000000,10.46 +16.560000000,10.48 +16.580000000,10.5 +16.600000000,10.52 +16.620000000,10.54 +16.640000000,10.56 +16.660000000,10.58 +16.680000000,10.6 +16.700000000,10.62 +16.720000000,10.64 +16.740000000,10.66 +16.760000000,10.66 +16.780000000,10.68 +16.800000000,10.68 +16.820000000,10.7 +16.840000000,10.7 +16.860000000,10.7 +16.880000000,10.7 +16.900000000,10.7 +16.920000000,10.7 +16.940000000,10.7 +16.960000000,10.7 +16.980000000,10.7 +17.000000000,10.7 +17.020000000,10.7 +17.040000000,10.7 +17.060000000,10.7 +17.080000000,10.7 +17.100000000,10.7 +17.120000000,10.7 +17.140000000,10.7 +17.160000000,10.72 +17.180000000,10.74 +17.200000000,10.76 +17.220000000,10.76 +17.240000000,10.76 +17.260000000,10.78 +17.280000000,10.8 +17.300000000,10.82 +17.320000000,10.84 +17.340000000,10.86 +17.360000000,10.88 +17.380000000,10.9 +17.400000000,10.92 +17.420000000,10.94 +17.440000000,10.96 +17.460000000,10.98 +17.480000000,11 +17.500000000,11.02 +17.520000000,11.02 +17.540000000,11.02 +17.560000000,11.02 +17.580000000,11.02 +17.600000000,11.02 +17.620000000,11.02 +17.640000000,11.02 +17.660000000,11.02 +17.680000000,11.02 +17.700000000,11.02 +17.720000000,11.02 +17.740000000,11.04 +17.760000000,11.06 +17.780000000,11.08 +17.800000000,11.08 +17.820000000,11.1 +17.840000000,11.12 +17.860000000,11.12 +17.880000000,11.12 +17.900000000,11.14 +17.920000000,11.16 +17.940000000,11.18 +17.960000000,11.2 +17.980000000,11.22 +18.000000000,11.24 +18.020000000,11.26 +18.040000000,11.28 +18.060000000,11.3 +18.080000000,11.32 +18.100000000,11.34 +18.120000000,11.36 +18.140000000,11.38 +18.160000000,11.4 +18.180000000,11.42 +18.200000000,11.44 +18.220000000,11.46 +18.240000000,11.48 +18.260000000,11.5 +18.280000000,11.52 +18.300000000,11.54 +18.320000000,11.56 +18.340000000,11.58 +18.360000000,11.58 +18.380000000,11.58 +18.400000000,11.58 +18.420000000,11.58 +18.440000000,11.58 +18.460000000,11.58 +18.480000000,11.6 +18.500000000,11.62 +18.520000000,11.64 +18.540000000,11.66 +18.560000000,11.68 +18.580000000,11.68 +18.600000000,11.7 +18.620000000,11.7 +18.640000000,11.7 +18.660000000,11.72 +18.680000000,11.72 +18.700000000,11.72 +18.720000000,11.72 +18.740000000,11.74 +18.760000000,11.74 +18.780000000,11.74 +18.800000000,11.76 +18.820000000,11.78 +18.840000000,11.8 +18.860000000,11.8 +18.880000000,11.82 +18.900000000,11.82 +18.920000000,11.82 +18.940000000,11.82 +18.960000000,11.84 +18.980000000,11.84 +19.000000000,11.84 +19.020000000,11.84 +19.040000000,11.84 +19.060000000,11.86 +19.080000000,11.88 +19.100000000,11.9 +19.120000000,11.92 +19.140000000,11.94 +19.160000000,11.96 +19.180000000,11.98 +19.200000000,12 +19.220000000,12.02 +19.240000000,12.04 +19.260000000,12.06 +19.280000000,12.08 +19.300000000,12.1 +19.320000000,12.12 +19.340000000,12.14 +19.360000000,12.16 +19.380000000,12.16 +19.400000000,12.18 +19.420000000,12.18 +19.440000000,12.2 +19.460000000,12.22 +19.480000000,12.24 +19.500000000,12.24 +19.520000000,12.24 +19.540000000,12.24 +19.560000000,12.26 +19.580000000,12.28 +19.600000000,12.3 +19.620000000,12.32 +19.640000000,12.34 +19.660000000,12.34 +19.680000000,12.36 +19.700000000,12.36 +19.720000000,12.36 +19.740000000,12.36 +19.760000000,12.36 +19.780000000,12.36 +19.800000000,12.36 +19.820000000,12.38 +19.840000000,12.4 +19.860000000,12.4 +19.880000000,12.42 +19.900000000,12.44 +19.920000000,12.46 +19.940000000,12.46 +19.960000000,12.48 +19.980000000,12.5 +20.000000000,12.5 +20.020000000,12.5 +20.040000000,12.5 +20.060000000,12.5 +20.080000000,12.52 +20.100000000,12.54 +20.120000000,12.56 +20.140000000,12.58 +20.160000000,12.6 +20.180000000,12.6 +20.200000000,12.62 +20.220000000,12.62 +20.240000000,12.64 +20.260000000,12.66 +20.280000000,12.68 +20.300000000,12.7 +20.320000000,12.72 +20.340000000,12.74 +20.360000000,12.74 +20.380000000,12.74 +20.400000000,12.74 +20.420000000,12.74 +20.440000000,12.74 +20.460000000,12.74 +20.480000000,12.74 +20.500000000,12.74 +20.520000000,12.74 +20.540000000,12.74 +20.560000000,12.74 +20.580000000,12.74 +20.600000000,12.74 +20.620000000,12.74 +20.640000000,12.74 +20.660000000,12.76 +20.680000000,12.78 +20.700000000,12.8 +20.720000000,12.82 +20.740000000,12.84 +20.760000000,12.86 +20.780000000,12.86 +20.800000000,12.86 +20.820000000,12.86 +20.840000000,12.86 +20.860000000,12.86 +20.880000000,12.86 +20.900000000,12.86 +20.920000000,12.86 +20.940000000,12.86 +20.960000000,12.86 +20.980000000,12.86 +21.000000000,12.86 +21.020000000,12.86 +21.040000000,12.86 +21.060000000,12.86 +21.080000000,12.86 +21.100000000,12.86 +21.120000000,12.86 +21.140000000,12.86 +21.160000000,12.86 +21.180000000,12.86 +21.200000000,12.86 +21.220000000,12.86 +21.240000000,12.86 +21.260000000,12.86 +21.280000000,12.86 +21.300000000,12.86 +21.320000000,12.86 +21.340000000,12.86 +21.360000000,12.86 +21.380000000,12.86 +21.400000000,12.88 +21.420000000,12.9 +21.440000000,12.92 +21.460000000,12.94 +21.480000000,12.96 +21.500000000,12.98 +21.520000000,13 +21.540000000,13 +21.560000000,13 +21.580000000,13.02 +21.600000000,13.02 +21.620000000,13.04 +21.640000000,13.04 +21.660000000,13.06 +21.680000000,13.06 +21.700000000,13.06 +21.720000000,13.06 +21.740000000,13.06 +21.760000000,13.08 +21.780000000,13.08 +21.800000000,13.08 +21.820000000,13.08 +21.840000000,13.08 +21.860000000,13.08 +21.880000000,13.08 +21.900000000,13.1 +21.920000000,13.12 +21.940000000,13.14 +21.960000000,13.16 +21.980000000,13.18 +22.000000000,13.2 +22.020000000,13.22 +22.040000000,13.24 +22.060000000,13.26 +22.080000000,13.28 +22.100000000,13.3 +22.120000000,13.32 +22.140000000,13.34 +22.160000000,13.36 +22.180000000,13.36 +22.200000000,13.36 +22.220000000,13.36 +22.240000000,13.36 +22.260000000,13.36 +22.280000000,13.36 +22.300000000,13.36 +22.320000000,13.36 +22.340000000,13.36 +22.360000000,13.36 +22.380000000,13.36 +22.400000000,13.36 +22.420000000,13.36 +22.440000000,13.36 +22.460000000,13.36 +22.480000000,13.36 +22.500000000,13.38 +22.520000000,13.4 +22.540000000,13.42 +22.560000000,13.44 +22.580000000,13.46 +22.600000000,13.48 +22.620000000,13.5 +22.640000000,13.52 +22.660000000,13.54 +22.680000000,13.56 +22.700000000,13.56 +22.720000000,13.58 +22.740000000,13.6 +22.760000000,13.62 +22.780000000,13.64 +22.800000000,13.66 +22.820000000,13.68 +22.840000000,13.7 +22.860000000,13.7 +22.880000000,13.7 +22.900000000,13.72 +22.920000000,13.74 +22.940000000,13.76 +22.960000000,13.78 +22.980000000,13.78 +23.000000000,13.78 +23.020000000,13.8 +23.040000000,13.8 +23.060000000,13.8 +23.080000000,13.82 +23.100000000,13.82 +23.120000000,13.82 +23.140000000,13.84 +23.160000000,13.86 +23.180000000,13.88 +23.200000000,13.9 +23.220000000,13.92 +23.240000000,13.94 +23.260000000,13.96 +23.280000000,13.98 +23.300000000,14 +23.320000000,14 +23.340000000,14.02 +23.360000000,14.02 +23.380000000,14.02 +23.400000000,14.04 +23.420000000,14.06 +23.440000000,14.08 +23.460000000,14.1 +23.480000000,14.12 +23.500000000,14.14 +23.520000000,14.16 +23.540000000,14.16 +23.560000000,14.18 +23.580000000,14.18 +23.600000000,14.18 +23.620000000,14.18 +23.640000000,14.18 +23.660000000,14.18 +23.680000000,14.2 +23.700000000,14.22 +23.720000000,14.24 +23.740000000,14.26 +23.760000000,14.28 +23.780000000,14.3 +23.800000000,14.3 +23.820000000,14.3 +23.840000000,14.32 +23.860000000,14.34 +23.880000000,14.34 +23.900000000,14.34 +23.920000000,14.36 +23.940000000,14.38 +23.960000000,14.4 +23.980000000,14.42 +24.000000000,14.44 +24.020000000,14.46 +24.040000000,14.48 +24.060000000,14.5 +24.080000000,14.52 +24.100000000,14.54 +24.120000000,14.56 +24.140000000,14.56 +24.160000000,14.56 +24.180000000,14.58 +24.200000000,14.6 +24.220000000,14.62 +24.240000000,14.64 +24.260000000,14.66 +24.280000000,14.68 +24.300000000,14.7 +24.320000000,14.72 +24.340000000,14.74 +24.360000000,14.76 +24.380000000,14.76 +24.400000000,14.76 +24.420000000,14.76 +24.440000000,14.76 +24.460000000,14.76 +24.480000000,14.76 +24.500000000,14.76 +24.520000000,14.76 +24.540000000,14.76 +24.560000000,14.76 +24.580000000,14.76 +24.600000000,14.76 +24.620000000,14.76 +24.640000000,14.76 +24.660000000,14.76 +24.680000000,14.76 +24.700000000,14.76 +24.720000000,14.76 +24.740000000,14.76 +24.760000000,14.76 +24.780000000,14.76 +24.800000000,14.76 +24.820000000,14.76 +24.840000000,14.78 +24.860000000,14.8 +24.880000000,14.82 +24.900000000,14.84 +24.920000000,14.86 +24.940000000,14.88 +24.960000000,14.9 +24.980000000,14.92 +25.000000000,14.94 +25.020000000,14.94 +25.040000000,14.94 +25.060000000,14.96 +25.080000000,14.96 +25.100000000,14.96 +25.120000000,14.96 +25.140000000,14.96 +25.160000000,14.96 +25.180000000,14.98 +25.200000000,15 +25.220000000,15.02 +25.240000000,15.04 +25.260000000,15.06 +25.280000000,15.08 +25.300000000,15.1 +25.320000000,15.12 +25.340000000,15.14 +25.360000000,15.16 +25.380000000,15.16 +25.400000000,15.16 +25.420000000,15.16 +25.440000000,15.16 +25.460000000,15.16 +25.480000000,15.16 +25.500000000,15.18 +25.520000000,15.2 +25.540000000,15.22 +25.560000000,15.24 +25.580000000,15.26 +25.600000000,15.26 +25.620000000,15.28 +25.640000000,15.3 +25.660000000,15.32 +25.680000000,15.34 +25.700000000,15.36 +25.720000000,15.38 +25.740000000,15.4 +25.760000000,15.42 +25.780000000,15.44 +25.800000000,15.46 +25.820000000,15.48 +25.840000000,15.5 +25.860000000,15.5 +25.880000000,15.5 +25.900000000,15.5 +25.920000000,15.5 +25.940000000,15.5 +25.960000000,15.5 +25.980000000,15.5 +26.000000000,15.5 +26.020000000,15.5 +26.040000000,15.5 +26.060000000,15.5 +26.080000000,15.5 +26.100000000,15.5 +26.120000000,15.5 +26.140000000,15.5 +26.160000000,15.52 +26.180000000,15.54 +26.200000000,15.56 +26.220000000,15.58 +26.240000000,15.58 +26.260000000,15.6 +26.280000000,15.6 +26.300000000,15.62 +26.320000000,15.64 +26.340000000,15.66 +26.360000000,15.68 +26.380000000,15.7 +26.400000000,15.72 +26.420000000,15.74 +26.440000000,15.76 +26.460000000,15.78 +26.480000000,15.8 +26.500000000,15.8 +26.520000000,15.82 +26.540000000,15.84 +26.560000000,15.84 +26.580000000,15.84 +26.600000000,15.84 +26.620000000,15.84 +26.640000000,15.86 +26.660000000,15.88 +26.680000000,15.9 +26.700000000,15.92 +26.720000000,15.94 +26.740000000,15.96 +26.760000000,15.96 +26.780000000,15.96 +26.800000000,15.96 +26.820000000,15.98 +26.840000000,16 +26.860000000,16.02 +26.880000000,16.04 +26.900000000,16.06 +26.920000000,16.08 +26.940000000,16.1 +26.960000000,16.12 +26.980000000,16.14 +27.000000000,16.16 +27.020000000,16.18 +27.040000000,16.2 +27.060000000,16.2 +27.080000000,16.2 +27.100000000,16.2 +27.120000000,16.2 +27.140000000,16.2 +27.160000000,16.2 +27.180000000,16.2 +27.200000000,16.2 +27.220000000,16.2 +27.240000000,16.2 +27.260000000,16.2 +27.280000000,16.2 +27.300000000,16.2 +27.320000000,16.2 +27.340000000,16.2 +27.360000000,16.22 +27.380000000,16.24 +27.400000000,16.26 +27.420000000,16.28 +27.440000000,16.3 +27.460000000,16.32 +27.480000000,16.34 +27.500000000,16.36 +27.520000000,16.38 +27.540000000,16.4 +27.560000000,16.42 +27.580000000,16.44 +27.600000000,16.46 +27.620000000,16.48 +27.640000000,16.5 +27.660000000,16.52 +27.680000000,16.54 +27.700000000,16.56 +27.720000000,16.58 +27.740000000,16.6 +27.760000000,16.62 +27.780000000,16.64 +27.800000000,16.66 +27.820000000,16.68 +27.840000000,16.7 +27.860000000,16.72 +27.880000000,16.74 +27.900000000,16.76 +27.920000000,16.76 +27.940000000,16.76 +27.960000000,16.78 +27.980000000,16.8 +28.000000000,16.82 +28.020000000,16.84 +28.040000000,16.86 +28.060000000,16.88 +28.080000000,16.9 +28.100000000,16.92 +28.120000000,16.94 +28.140000000,16.94 +28.160000000,16.96 +28.180000000,16.96 +28.200000000,16.96 +28.220000000,16.96 +28.240000000,16.96 +28.260000000,16.96 +28.280000000,16.98 +28.300000000,16.98 +28.320000000,16.98 +28.340000000,16.98 +28.360000000,16.98 +28.380000000,16.98 +28.400000000,16.98 +28.420000000,16.98 +28.440000000,16.98 +28.460000000,16.98 +28.480000000,16.98 +28.500000000,17 +28.520000000,17.02 +28.540000000,17.04 +28.560000000,17.06 +28.580000000,17.08 +28.600000000,17.1 +28.620000000,17.12 +28.640000000,17.12 +28.660000000,17.12 +28.680000000,17.12 +28.700000000,17.12 +28.720000000,17.12 +28.740000000,17.12 +28.760000000,17.12 +28.780000000,17.12 +28.800000000,17.12 +28.820000000,17.14 +28.840000000,17.16 +28.860000000,17.18 +28.880000000,17.2 +28.900000000,17.22 +28.920000000,17.24 +28.940000000,17.26 +28.960000000,17.28 +28.980000000,17.3 +29.000000000,17.32 +29.020000000,17.34 +29.040000000,17.36 +29.060000000,17.38 +29.080000000,17.4 +29.100000000,17.42 +29.120000000,17.44 +29.140000000,17.46 +29.160000000,17.48 +29.180000000,17.5 +29.200000000,17.52 +29.220000000,17.54 +29.240000000,17.56 +29.260000000,17.58 +29.280000000,17.6 +29.300000000,17.62 +29.320000000,17.64 +29.340000000,17.66 +29.360000000,17.68 +29.380000000,17.7 +29.400000000,17.72 +29.420000000,17.74 +29.440000000,17.76 +29.460000000,17.78 +29.480000000,17.8 +29.500000000,17.82 +29.520000000,17.84 +29.540000000,17.86 +29.560000000,17.86 +29.580000000,17.86 +29.600000000,17.86 +29.620000000,17.86 +29.640000000,17.86 +29.660000000,17.86 +29.680000000,17.86 +29.700000000,17.86 +29.720000000,17.88 +29.740000000,17.9 +29.760000000,17.92 +29.780000000,17.94 +29.800000000,17.96 +29.820000000,17.98 +29.840000000,18 +29.860000000,18.02 +29.880000000,18.04 +29.900000000,18.06 +29.920000000,18.08 +29.940000000,18.1 +29.960000000,18.12 +29.980000000,18.14 +30.000000000,18.16 +30.020000000,18.18 +30.040000000,18.2 +30.060000000,18.22 +30.080000000,18.24 +30.100000000,18.26 +30.120000000,18.28 +30.140000000,18.3 +30.160000000,18.32 +30.180000000,18.34 +30.200000000,18.36 +30.220000000,18.38 +30.240000000,18.4 +30.260000000,18.42 +30.280000000,18.44 +30.300000000,18.46 +30.320000000,18.48 +30.340000000,18.5 +30.360000000,18.52 +30.380000000,18.54 +30.400000000,18.56 +30.420000000,18.58 +30.440000000,18.6 +30.460000000,18.62 +30.480000000,18.64 +30.500000000,18.66 +30.520000000,18.68 +30.540000000,18.7 +30.560000000,18.72 +30.580000000,18.74 +30.600000000,18.76 +30.620000000,18.78 +30.640000000,18.8 +30.660000000,18.82 +30.680000000,18.84 +30.700000000,18.86 +30.720000000,18.88 +30.740000000,18.9 +30.760000000,18.92 +30.780000000,18.94 +30.800000000,18.96 +30.820000000,18.98 +30.840000000,19 +30.860000000,19.02 +30.880000000,19.04 +30.900000000,19.04 +30.920000000,19.04 +30.940000000,19.04 +30.960000000,19.04 +30.980000000,19.04 +31.000000000,19.04 +31.020000000,19.04 +31.040000000,19.06 +31.060000000,19.06 +31.080000000,19.06 +31.100000000,19.06 +31.120000000,19.06 +31.140000000,19.06 +31.160000000,19.06 +31.180000000,19.06 +31.200000000,19.08 +31.220000000,19.1 +31.240000000,19.1 +31.260000000,19.1 +31.280000000,19.12 +31.300000000,19.14 +31.320000000,19.16 +31.340000000,19.18 +31.360000000,19.2 +31.380000000,19.22 +31.400000000,19.24 +31.420000000,19.26 +31.440000000,19.28 +31.460000000,19.3 +31.480000000,19.32 +31.500000000,19.34 +31.520000000,19.36 +31.540000000,19.38 +31.560000000,19.4 +31.580000000,19.42 +31.600000000,19.44 +31.620000000,19.46 +31.640000000,19.48 +31.660000000,19.5 +31.680000000,19.52 +31.700000000,19.54 +31.720000000,19.56 +31.740000000,19.58 +31.760000000,19.6 +31.780000000,19.62 +31.800000000,19.64 +31.820000000,19.64 +31.840000000,19.64 +31.860000000,19.64 +31.880000000,19.66 +31.900000000,19.68 +31.920000000,19.7 +31.940000000,19.7 +31.960000000,19.7 +31.980000000,19.7 +32.000000000,19.72 +32.020000000,19.74 +32.040000000,19.76 +32.060000000,19.78 +32.080000000,19.78 +32.100000000,19.78 +32.120000000,19.78 +32.140000000,19.78 +32.160000000,19.78 +32.180000000,19.78 +32.200000000,19.78 +32.220000000,19.78 +32.240000000,19.78 +32.260000000,19.78 +32.280000000,19.78 +32.300000000,19.78 +32.320000000,19.78 +32.340000000,19.78 +32.360000000,19.8 +32.380000000,19.82 +32.400000000,19.84 +32.420000000,19.86 +32.440000000,19.88 +32.460000000,19.88 +32.480000000,19.9 +32.500000000,19.92 +32.520000000,19.92 +32.540000000,19.92 +32.560000000,19.92 +32.580000000,19.92 +32.600000000,19.92 +32.620000000,19.92 +32.640000000,19.92 +32.660000000,19.92 +32.680000000,19.92 +32.700000000,19.92 +32.720000000,19.94 +32.740000000,19.96 +32.760000000,19.98 +32.780000000,20 +32.800000000,20.02 +32.820000000,20.04 +32.840000000,20.06 +32.860000000,20.08 +32.880000000,20.1 +32.900000000,20.12 +32.920000000,20.14 +32.940000000,20.16 +32.960000000,20.18 +32.980000000,20.2 +33.000000000,20.22 +33.020000000,20.24 +33.040000000,20.26 +33.060000000,20.28 +33.080000000,20.3 +33.100000000,20.32 +33.120000000,20.34 +33.140000000,20.36 +33.160000000,20.38 +33.180000000,20.4 +33.200000000,20.42 +33.220000000,20.44 +33.240000000,20.46 +33.260000000,20.48 +33.280000000,20.5 +33.300000000,20.52 +33.320000000,20.54 +33.340000000,20.56 +33.360000000,20.58 +33.380000000,20.6 +33.400000000,20.6 +33.420000000,20.62 +33.440000000,20.64 +33.460000000,20.66 +33.480000000,20.68 +33.500000000,20.7 +33.520000000,20.72 +33.540000000,20.72 +33.560000000,20.72 +33.580000000,20.74 +33.600000000,20.76 +33.620000000,20.78 +33.640000000,20.8 +33.660000000,20.82 +33.680000000,20.84 +33.700000000,20.86 +33.720000000,20.88 +33.740000000,20.9 +33.760000000,20.92 +33.780000000,20.92 +33.800000000,20.92 +33.820000000,20.94 +33.840000000,20.94 +33.860000000,20.96 +33.880000000,20.98 +33.900000000,21 +33.920000000,21.02 +33.940000000,21.04 +33.960000000,21.06 +33.980000000,21.08 +34.000000000,21.1 +34.020000000,21.12 +34.040000000,21.12 +34.060000000,21.14 +34.080000000,21.14 +34.100000000,21.14 +34.120000000,21.14 +34.140000000,21.14 +34.160000000,21.16 +34.180000000,21.18 +34.200000000,21.2 +34.220000000,21.22 +34.240000000,21.24 +34.260000000,21.26 +34.280000000,21.28 +34.300000000,21.3 +34.320000000,21.3 +34.340000000,21.3 +34.360000000,21.3 +34.380000000,21.3 +34.400000000,21.3 +34.420000000,21.32 +34.440000000,21.34 +34.460000000,21.36 +34.480000000,21.36 +34.500000000,21.36 +34.520000000,21.36 +34.540000000,21.38 +34.560000000,21.4 +34.580000000,21.4 +34.600000000,21.4 +34.620000000,21.4 +34.640000000,21.4 +34.660000000,21.4 +34.680000000,21.4 +34.700000000,21.4 +34.720000000,21.4 +34.740000000,21.4 +34.760000000,21.4 +34.780000000,21.42 +34.800000000,21.42 +34.820000000,21.44 +34.840000000,21.46 +34.860000000,21.46 +34.880000000,21.46 +34.900000000,21.46 +34.920000000,21.46 +34.940000000,21.46 +34.960000000,21.46 +34.980000000,21.46 +35.000000000,21.46 +35.020000000,21.46 +35.040000000,21.46 +35.060000000,21.46 +35.080000000,21.46 +35.100000000,21.46 +35.120000000,21.46 +35.140000000,21.46 +35.160000000,21.46 +35.180000000,21.46 +35.200000000,21.46 +35.220000000,21.46 +35.240000000,21.46 +35.260000000,21.46 +35.280000000,21.46 +35.300000000,21.46 +35.320000000,21.46 +35.340000000,21.46 +35.360000000,21.48 +35.380000000,21.5 +35.400000000,21.52 +35.420000000,21.54 +35.440000000,21.56 +35.460000000,21.58 +35.480000000,21.6 +35.500000000,21.6 +35.520000000,21.6 +35.540000000,21.6 +35.560000000,21.62 +35.580000000,21.62 +35.600000000,21.62 +35.620000000,21.62 +35.640000000,21.62 +35.660000000,21.62 +35.680000000,21.62 +35.700000000,21.62 +35.720000000,21.62 +35.740000000,21.62 +35.760000000,21.62 +35.780000000,21.62 +35.800000000,21.62 +35.820000000,21.62 +35.840000000,21.62 +35.860000000,21.62 +35.880000000,21.62 +35.900000000,21.62 +35.920000000,21.62 +35.940000000,21.62 +35.960000000,21.64 +35.980000000,21.64 +36.000000000,21.64 +36.020000000,21.64 +36.040000000,21.64 +36.060000000,21.64 +36.080000000,21.64 +36.100000000,21.64 +36.120000000,21.64 +36.140000000,21.66 +36.160000000,21.68 +36.180000000,21.68 +36.200000000,21.68 +36.220000000,21.68 +36.240000000,21.68 +36.260000000,21.68 +36.280000000,21.68 +36.300000000,21.7 +36.320000000,21.7 +36.340000000,21.72 +36.360000000,21.74 +36.380000000,21.76 +36.400000000,21.76 +36.420000000,21.76 +36.440000000,21.76 +36.460000000,21.76 +36.480000000,21.76 +36.500000000,21.76 +36.520000000,21.76 +36.540000000,21.76 +36.560000000,21.76 +36.580000000,21.76 +36.600000000,21.76 +36.620000000,21.76 +36.640000000,21.76 +36.660000000,21.76 +36.680000000,21.76 +36.700000000,21.76 +36.720000000,21.76 +36.740000000,21.76 +36.760000000,21.76 +36.780000000,21.76 +36.800000000,21.76 +36.820000000,21.76 +36.840000000,21.78 +36.860000000,21.8 +36.880000000,21.82 +36.900000000,21.84 +36.920000000,21.86 +36.940000000,21.88 +36.960000000,21.9 +36.980000000,21.92 +37.000000000,21.94 +37.020000000,21.96 +37.040000000,21.98 +37.060000000,22 +37.080000000,22.02 +37.100000000,22.04 +37.120000000,22.06 +37.140000000,22.06 +37.160000000,22.06 +37.180000000,22.06 +37.200000000,22.06 +37.220000000,22.06 +37.240000000,22.06 +37.260000000,22.06 +37.280000000,22.06 +37.300000000,22.06 +37.320000000,22.06 +37.340000000,22.06 +37.360000000,22.06 +37.380000000,22.06 +37.400000000,22.06 +37.420000000,22.06 +37.440000000,22.06 +37.460000000,22.06 +37.480000000,22.08 +37.500000000,22.1 +37.520000000,22.12 +37.540000000,22.14 +37.560000000,22.16 +37.580000000,22.18 +37.600000000,22.18 +37.620000000,22.18 +37.640000000,22.18 +37.660000000,22.18 +37.680000000,22.18 +37.700000000,22.18 +37.720000000,22.2 +37.740000000,22.2 +37.760000000,22.22 +37.780000000,22.22 +37.800000000,22.24 +37.820000000,22.26 +37.840000000,22.28 +37.860000000,22.28 +37.880000000,22.28 +37.900000000,22.28 +37.920000000,22.3 +37.940000000,22.32 +37.960000000,22.34 +37.980000000,22.36 +38.000000000,22.36 +38.020000000,22.36 +38.040000000,22.38 +38.060000000,22.4 +38.080000000,22.4 +38.100000000,22.4 +38.120000000,22.4 +38.140000000,22.4 +38.160000000,22.42 +38.180000000,22.44 +38.200000000,22.44 +38.220000000,22.44 +38.240000000,22.44 +38.260000000,22.44 +38.280000000,22.46 +38.300000000,22.48 +38.320000000,22.48 +38.340000000,22.48 +38.360000000,22.5 +38.380000000,22.5 +38.400000000,22.52 +38.420000000,22.54 +38.440000000,22.54 +38.460000000,22.54 +38.480000000,22.54 +38.500000000,22.54 +38.520000000,22.56 +38.540000000,22.58 +38.560000000,22.6 +38.580000000,22.62 +38.600000000,22.64 +38.620000000,22.66 +38.640000000,22.68 +38.660000000,22.7 +38.680000000,22.72 +38.700000000,22.74 +38.720000000,22.76 +38.740000000,22.78 +38.760000000,22.8 +38.780000000,22.82 +38.800000000,22.84 +38.820000000,22.84 +38.840000000,22.84 +38.860000000,22.84 +38.880000000,22.84 +38.900000000,22.84 +38.920000000,22.84 +38.940000000,22.84 +38.960000000,22.84 +38.980000000,22.84 +39.000000000,22.84 +39.020000000,22.86 +39.040000000,22.88 +39.060000000,22.9 +39.080000000,22.92 +39.100000000,22.94 +39.120000000,22.96 +39.140000000,22.98 +39.160000000,23 +39.180000000,23.02 +39.200000000,23.04 +39.220000000,23.06 +39.240000000,23.08 +39.260000000,23.1 +39.280000000,23.12 +39.300000000,23.14 +39.320000000,23.16 +39.340000000,23.18 +39.360000000,23.2 +39.380000000,23.22 +39.400000000,23.24 +39.420000000,23.26 +39.440000000,23.28 +39.460000000,23.3 +39.480000000,23.32 +39.500000000,23.34 +39.520000000,23.36 +39.540000000,23.38 +39.560000000,23.4 +39.580000000,23.42 +39.600000000,23.44 +39.620000000,23.46 +39.640000000,23.48 +39.660000000,23.5 +39.680000000,23.52 +39.700000000,23.54 +39.720000000,23.56 +39.740000000,23.58 +39.760000000,23.6 +39.780000000,23.62 +39.800000000,23.64 +39.820000000,23.66 +39.840000000,23.68 +39.860000000,23.7 +39.880000000,23.72 +39.900000000,23.74 +39.920000000,23.76 +39.940000000,23.78 +39.960000000,23.8 +39.980000000,23.82 +40.000000000,23.84 +40.020000000,23.86 +40.040000000,23.88 +40.060000000,23.9 +40.080000000,23.92 +40.100000000,23.94 +40.100000000,23.96 +40.100000000,23.98 +40.120000000,24 +40.120000000,24.02 +40.120000000,24.04 +40.120000000,24.06 +40.120000000,24.08 +40.120000000,24.1 +40.120000000,24.12 +40.120000000,24.14 +40.120000000,24.16 +40.120000000,24.18 +40.120000000,24.2 +40.120000000,24.22 +40.140000000,24.24 +40.160000000,24.26 +40.180000000,24.28 +40.200000000,24.3 +40.220000000,24.32 +40.220000000,24.34 +40.220000000,24.36 +40.220000000,24.38 +40.220000000,24.4 +40.220000000,24.42 +40.220000000,24.44 +40.220000000,24.46 +40.220000000,24.48 +40.220000000,24.5 +40.220000000,24.52 +40.240000000,24.54 +40.260000000,24.56 +40.280000000,24.58 +40.280000000,24.6 +40.280000000,24.62 +40.300000000,24.64 +40.320000000,24.66 +40.320000000,24.68 +40.320000000,24.7 +40.320000000,24.72 +40.320000000,24.74 +40.320000000,24.76 +40.320000000,24.78 +40.320000000,24.8 +40.320000000,24.82 +40.320000000,24.84 +40.320000000,24.86 +40.320000000,24.88 +40.320000000,24.9 +40.320000000,24.92 +40.320000000,24.94 +40.320000000,24.96 +40.320000000,24.98 +40.320000000,25 +40.320000000,25.02 +40.320000000,25.04 +40.320000000,25.06 +40.320000000,25.08 +40.340000000,25.1 +40.340000000,25.12 +40.340000000,25.14 +40.340000000,25.16 +40.340000000,25.18 +40.340000000,25.2 +40.340000000,25.22 +40.340000000,25.24 +40.340000000,25.26 +40.340000000,25.28 +40.340000000,25.3 +40.340000000,25.32 +40.340000000,25.34 +40.340000000,25.36 +40.340000000,25.38 +40.340000000,25.4 +40.340000000,25.42 +40.340000000,25.44 +40.340000000,25.46 +40.340000000,25.48 +40.340000000,25.5 +40.340000000,25.52 +40.340000000,25.54 +40.340000000,25.56 +40.340000000,25.58 +40.340000000,25.6 +40.340000000,25.62 +40.340000000,25.64 +40.340000000,25.66 +40.340000000,25.68 +40.340000000,25.7 +40.340000000,25.72 +40.340000000,25.74 +40.340000000,25.76 +40.340000000,25.78 +40.360000000,25.8 +40.380000000,25.82 +40.400000000,25.84 +40.420000000,25.86 +40.440000000,25.88 +40.460000000,25.9 +40.480000000,25.92 +40.500000000,25.94 +40.500000000,25.96 +40.500000000,25.98 +40.520000000,26 +40.540000000,26.02 +40.560000000,26.04 +40.580000000,26.06 +40.600000000,26.08 +40.620000000,26.1 +40.640000000,26.12 +40.660000000,26.14 +40.680000000,26.16 +40.680000000,26.18 +40.680000000,26.2 +40.680000000,26.22 +40.680000000,26.24 +40.680000000,26.26 +40.680000000,26.28 +40.680000000,26.3 +40.700000000,26.32 +40.720000000,26.34 +40.740000000,26.36 +40.740000000,26.38 +40.740000000,26.4 +40.740000000,26.42 +40.740000000,26.44 +40.740000000,26.46 +40.740000000,26.48 +40.740000000,26.5 +40.740000000,26.52 +40.760000000,26.54 +40.780000000,26.56 +40.800000000,26.58 +40.820000000,26.6 +40.820000000,26.62 +40.820000000,26.64 +40.820000000,26.66 +40.820000000,26.68 +40.820000000,26.7 +40.820000000,26.72 +40.820000000,26.74 +40.820000000,26.76 +40.820000000,26.78 +40.820000000,26.8 +40.820000000,26.82 +40.820000000,26.84 +40.820000000,26.86 +40.820000000,26.88 +40.820000000,26.9 +40.820000000,26.92 +40.820000000,26.94 +40.820000000,26.96 +40.820000000,26.98 +40.820000000,27 +40.820000000,27.02 +40.820000000,27.04 +40.820000000,27.06 +40.820000000,27.08 +40.820000000,27.1 +40.820000000,27.12 +40.820000000,27.14 +40.840000000,27.16 +40.840000000,27.18 +40.840000000,27.2 +40.840000000,27.22 +40.840000000,27.24 +40.840000000,27.26 +40.840000000,27.28 +40.840000000,27.3 +40.840000000,27.32 +40.840000000,27.34 +40.840000000,27.36 +40.840000000,27.38 +40.840000000,27.4 +40.840000000,27.42 +40.840000000,27.44 +40.840000000,27.46 +40.840000000,27.48 +40.840000000,27.5 +40.840000000,27.52 +40.840000000,27.54 +40.840000000,27.56 +40.840000000,27.58 +40.840000000,27.6 +40.840000000,27.62 +40.840000000,27.64 +40.840000000,27.66 +40.840000000,27.68 +40.840000000,27.7 +40.840000000,27.72 +40.840000000,27.74 +40.860000000,27.76 +40.860000000,27.78 +40.860000000,27.8 +40.860000000,27.82 +40.860000000,27.84 +40.860000000,27.86 +40.860000000,27.88 +40.860000000,27.9 +40.860000000,27.92 +40.860000000,27.94 +40.860000000,27.96 +40.860000000,27.98 +40.860000000,28 +40.860000000,28.02 +40.860000000,28.04 +40.860000000,28.06 +40.860000000,28.08 +40.860000000,28.1 +40.860000000,28.12 +40.860000000,28.14 +40.860000000,28.16 +40.860000000,28.18 +40.860000000,28.2 +40.860000000,28.22 +40.860000000,28.24 +40.860000000,28.26 +40.860000000,28.28 +40.860000000,28.3 +40.860000000,28.32 +40.860000000,28.34 +40.860000000,28.36 +40.860000000,28.38 +40.860000000,28.4 +40.880000000,28.42 +40.900000000,28.44 +40.920000000,28.46 +40.940000000,28.48 +40.960000000,28.5 +40.980000000,28.52 +41.000000000,28.54 +41.020000000,28.56 +41.040000000,28.58 +41.040000000,28.6 +41.040000000,28.62 +41.040000000,28.64 +41.040000000,28.66 +41.040000000,28.68 +41.040000000,28.7 +41.060000000,28.72 +41.080000000,28.74 +41.100000000,28.76 +41.120000000,28.78 +41.140000000,28.8 +41.160000000,28.82 +41.180000000,28.84 +41.200000000,28.86 +41.220000000,28.88 +41.240000000,28.9 +41.260000000,28.92 +41.280000000,28.94 +41.300000000,28.96 +41.320000000,28.98 +41.340000000,29 +41.360000000,29.02 +41.380000000,29.04 +41.400000000,29.06 +41.400000000,29.08 +41.400000000,29.1 +41.400000000,29.12 +41.400000000,29.14 +41.420000000,29.16 +41.440000000,29.18 +41.440000000,29.2 +41.440000000,29.22 +41.460000000,29.24 +41.460000000,29.26 +41.480000000,29.28 +41.500000000,29.3 +41.500000000,29.32 +41.520000000,29.34 +41.520000000,29.36 +41.520000000,29.38 +41.520000000,29.4 +41.520000000,29.42 +41.520000000,29.44 +41.520000000,29.46 +41.520000000,29.48 +41.520000000,29.5 +41.520000000,29.52 +41.540000000,29.54 +41.560000000,29.56 +41.580000000,29.58 +41.580000000,29.6 +41.580000000,29.62 +41.580000000,29.64 +41.580000000,29.66 +41.580000000,29.68 +41.580000000,29.7 +41.580000000,29.72 +41.580000000,29.74 +41.600000000,29.76 +41.620000000,29.78 +41.640000000,29.8 +41.660000000,29.82 +41.680000000,29.84 +41.700000000,29.86 +41.720000000,29.88 +41.740000000,29.9 +41.740000000,29.92 +41.760000000,29.94 +41.780000000,29.96 +41.800000000,29.98 +41.820000000,30 +41.840000000,30.02 +41.860000000,30.04 +41.860000000,30.06 +41.860000000,30.08 +41.860000000,30.1 +41.860000000,30.12 +41.860000000,30.14 +41.860000000,30.16 +41.860000000,30.18 +41.860000000,30.2 +41.860000000,30.22 +41.880000000,30.24 +41.880000000,30.26 +41.880000000,30.28 +41.880000000,30.3 +41.880000000,30.32 +41.880000000,30.34 +41.880000000,30.36 +41.880000000,30.38 +41.880000000,30.4 +41.880000000,30.42 +41.900000000,30.44 +41.920000000,30.46 +41.920000000,30.48 +41.920000000,30.5 +41.920000000,30.52 +41.920000000,30.54 +41.920000000,30.56 +41.920000000,30.58 +41.920000000,30.6 +41.920000000,30.62 +41.920000000,30.64 +41.920000000,30.66 +41.920000000,30.68 +41.920000000,30.7 +41.920000000,30.72 +41.920000000,30.74 +41.940000000,30.76 +41.940000000,30.78 +41.960000000,30.8 +41.980000000,30.82 +42.000000000,30.84 +42.020000000,30.86 +42.040000000,30.88 +42.060000000,30.9 +42.060000000,30.92 +42.060000000,30.94 +42.060000000,30.96 +42.060000000,30.98 +42.060000000,31 +42.060000000,31.02 +42.060000000,31.04 +42.060000000,31.06 +42.060000000,31.08 +42.060000000,31.1 +42.060000000,31.12 +42.060000000,31.14 +42.060000000,31.16 +42.060000000,31.18 +42.060000000,31.2 +42.060000000,31.22 +42.060000000,31.24 +42.060000000,31.26 +42.060000000,31.28 +42.060000000,31.3 +42.060000000,31.32 +42.060000000,31.34 +42.060000000,31.36 +42.060000000,31.38 +42.060000000,31.4 +42.080000000,31.42 +42.100000000,31.44 +42.120000000,31.46 +42.140000000,31.48 +42.160000000,31.5 +42.180000000,31.52 +42.200000000,31.54 +42.220000000,31.56 +42.240000000,31.58 +42.260000000,31.6 +42.280000000,31.62 +42.300000000,31.64 +42.320000000,31.66 +42.340000000,31.68 +42.360000000,31.7 +42.380000000,31.72 +42.400000000,31.74 +42.420000000,31.76 +42.440000000,31.78 +42.460000000,31.8 +42.480000000,31.82 +42.500000000,31.84 +42.520000000,31.86 +42.540000000,31.88 +42.560000000,31.9 +42.580000000,31.92 +42.600000000,31.94 +42.620000000,31.96 +42.640000000,31.98 +42.660000000,32 +42.680000000,32.02 +42.700000000,32.04 +42.720000000,32.06 +42.740000000,32.08 +42.760000000,32.1 +42.780000000,32.12 +42.800000000,32.14 +42.820000000,32.16 +42.840000000,32.18 +42.860000000,32.2 +42.880000000,32.22 +42.900000000,32.24 +42.920000000,32.26 +42.940000000,32.28 +42.960000000,32.3 +42.980000000,32.32 +43.000000000,32.34 +43.020000000,32.36 +43.040000000,32.38 +43.060000000,32.4 +43.080000000,32.42 +43.100000000,32.42 +43.120000000,32.44 +43.140000000,32.46 +43.160000000,32.46 +43.180000000,32.46 +43.200000000,32.46 +43.220000000,32.46 +43.240000000,32.46 +43.260000000,32.46 +43.280000000,32.46 +43.300000000,32.46 +43.320000000,32.46 +43.340000000,32.46 +43.360000000,32.46 +43.380000000,32.46 +43.400000000,32.46 +43.420000000,32.48 +43.440000000,32.5 +43.460000000,32.52 +43.480000000,32.52 +43.500000000,32.52 +43.520000000,32.52 +43.540000000,32.52 +43.560000000,32.52 +43.580000000,32.52 +43.600000000,32.52 +43.620000000,32.52 +43.640000000,32.52 +43.660000000,32.52 +43.680000000,32.52 +43.700000000,32.52 +43.720000000,32.52 +43.740000000,32.52 +43.760000000,32.52 +43.780000000,32.52 +43.800000000,32.52 +43.820000000,32.52 +43.840000000,32.52 +43.860000000,32.52 +43.880000000,32.52 +43.900000000,32.52 +43.920000000,32.52 +43.940000000,32.52 +43.960000000,32.52 +43.980000000,32.52 +44.000000000,32.52 +44.020000000,32.52 +44.040000000,32.52 +44.060000000,32.52 +44.080000000,32.52 +44.100000000,32.52 +44.120000000,32.52 +44.140000000,32.52 +44.160000000,32.52 +44.180000000,32.52 +44.200000000,32.52 +44.220000000,32.52 +44.240000000,32.52 +44.260000000,32.52 +44.280000000,32.52 +44.300000000,32.52 +44.320000000,32.52 +44.340000000,32.52 +44.360000000,32.52 +44.380000000,32.52 +44.400000000,32.52 +44.420000000,32.52 +44.440000000,32.52 +44.460000000,32.54 +44.480000000,32.56 +44.500000000,32.58 +44.520000000,32.58 +44.540000000,32.58 +44.560000000,32.58 +44.580000000,32.6 +44.600000000,32.6 +44.620000000,32.6 +44.640000000,32.6 +44.660000000,32.6 +44.680000000,32.6 +44.700000000,32.62 +44.720000000,32.64 +44.740000000,32.66 +44.760000000,32.68 +44.780000000,32.7 +44.800000000,32.72 +44.820000000,32.74 +44.840000000,32.76 +44.860000000,32.78 +44.880000000,32.8 +44.900000000,32.82 +44.920000000,32.82 +44.940000000,32.82 +44.960000000,32.84 +44.980000000,32.86 +45.000000000,32.88 +45.020000000,32.88 +45.040000000,32.88 +45.060000000,32.88 +45.080000000,32.88 +45.100000000,32.88 +45.120000000,32.88 +45.140000000,32.9 +45.160000000,32.92 +45.180000000,32.92 +45.200000000,32.92 +45.220000000,32.92 +45.240000000,32.92 +45.260000000,32.92 +45.280000000,32.92 +45.300000000,32.92 +45.320000000,32.92 +45.340000000,32.92 +45.360000000,32.94 +45.380000000,32.94 +45.400000000,32.94 +45.420000000,32.94 +45.440000000,32.96 +45.460000000,32.96 +45.480000000,32.96 +45.500000000,32.96 +45.520000000,32.96 +45.540000000,32.96 +45.560000000,32.96 +45.580000000,32.96 +45.600000000,32.96 +45.620000000,32.96 +45.640000000,32.98 +45.660000000,32.98 +45.680000000,32.98 +45.700000000,33 +45.720000000,33.02 +45.740000000,33.02 +45.760000000,33.04 +45.780000000,33.06 +45.800000000,33.08 +45.820000000,33.1 +45.840000000,33.12 +45.860000000,33.14 +45.880000000,33.16 +45.900000000,33.18 +45.920000000,33.2 +45.940000000,33.22 +45.960000000,33.24 +45.980000000,33.26 +46.000000000,33.28 +46.020000000,33.28 +46.040000000,33.28 +46.060000000,33.28 +46.080000000,33.28 +46.100000000,33.28 +46.120000000,33.28 +46.140000000,33.28 +46.160000000,33.28 +46.180000000,33.3 +46.200000000,33.3 +46.220000000,33.3 +46.240000000,33.3 +46.260000000,33.3 +46.280000000,33.3 +46.300000000,33.3 +46.320000000,33.3 +46.340000000,33.3 +46.360000000,33.3 +46.380000000,33.3 +46.400000000,33.3 +46.420000000,33.3 +46.440000000,33.3 +46.460000000,33.3 +46.480000000,33.3 +46.500000000,33.3 +46.520000000,33.3 +46.540000000,33.3 +46.560000000,33.3 +46.580000000,33.3 +46.600000000,33.3 +46.620000000,33.3 +46.640000000,33.3 +46.660000000,33.3 +46.680000000,33.3 +46.700000000,33.3 +46.720000000,33.3 +46.740000000,33.3 +46.760000000,33.3 +46.780000000,33.3 +46.800000000,33.3 +46.820000000,33.3 +46.840000000,33.3 +46.860000000,33.3 +46.880000000,33.3 +46.900000000,33.3 +46.920000000,33.3 +46.940000000,33.3 +46.960000000,33.32 +46.980000000,33.34 +47.000000000,33.36 +47.020000000,33.38 +47.040000000,33.4 +47.060000000,33.4 +47.080000000,33.4 +47.100000000,33.4 +47.120000000,33.42 +47.140000000,33.44 +47.160000000,33.44 +47.180000000,33.44 +47.200000000,33.44 +47.220000000,33.44 +47.240000000,33.44 +47.260000000,33.44 +47.280000000,33.44 +47.300000000,33.44 +47.320000000,33.46 +47.340000000,33.46 +47.360000000,33.46 +47.380000000,33.46 +47.400000000,33.46 +47.420000000,33.46 +47.440000000,33.46 +47.460000000,33.46 +47.480000000,33.46 +47.500000000,33.46 +47.520000000,33.46 +47.540000000,33.46 +47.560000000,33.48 +47.580000000,33.5 +47.600000000,33.5 +47.620000000,33.5 +47.640000000,33.5 +47.660000000,33.5 +47.680000000,33.5 +47.700000000,33.5 +47.720000000,33.5 +47.740000000,33.5 +47.760000000,33.52 +47.780000000,33.52 +47.800000000,33.52 +47.820000000,33.54 +47.840000000,33.54 +47.860000000,33.56 +47.880000000,33.58 +47.900000000,33.6 +47.920000000,33.62 +47.940000000,33.64 +47.960000000,33.66 +47.980000000,33.68 +48.000000000,33.7 +48.020000000,33.72 +48.040000000,33.74 +48.060000000,33.76 +48.080000000,33.78 +48.100000000,33.8 +48.120000000,33.82 +48.140000000,33.84 +48.160000000,33.86 +48.180000000,33.88 +48.200000000,33.9 +48.220000000,33.92 +48.240000000,33.94 +48.260000000,33.96 +48.280000000,33.98 +48.300000000,34 +48.320000000,34.02 +48.340000000,34.04 +48.360000000,34.06 +48.380000000,34.08 +48.400000000,34.1 +48.420000000,34.12 +48.440000000,34.14 +48.460000000,34.16 +48.480000000,34.18 +48.500000000,34.2 +48.520000000,34.22 +48.540000000,34.24 +48.560000000,34.26 +48.580000000,34.28 +48.600000000,34.3 +48.620000000,34.32 +48.640000000,34.34 +48.660000000,34.36 +48.680000000,34.38 +48.700000000,34.4 +48.720000000,34.42 +48.740000000,34.44 +48.760000000,34.46 +48.780000000,34.48 +48.800000000,34.5 +48.820000000,34.52 +48.840000000,34.54 +48.860000000,34.56 +48.860000000,34.58 +48.860000000,34.6 +48.860000000,34.62 +48.860000000,34.64 +48.860000000,34.66 +48.860000000,34.68 +48.860000000,34.7 +48.860000000,34.72 +48.860000000,34.74 +48.860000000,34.76 +48.860000000,34.78 +48.860000000,34.8 +48.860000000,34.82 +48.860000000,34.84 +48.860000000,34.86 +48.860000000,34.88 +48.860000000,34.9 +48.860000000,34.92 +48.860000000,34.94 +48.860000000,34.96 +48.860000000,34.98 +48.860000000,35 +48.860000000,35.02 +48.860000000,35.04 +48.860000000,35.06 +48.860000000,35.08 +48.860000000,35.1 +48.860000000,35.12 +48.860000000,35.14 +48.860000000,35.16 +48.860000000,35.18 +48.860000000,35.2 +48.860000000,35.22 +48.860000000,35.24 +48.860000000,35.26 +48.860000000,35.28 +48.860000000,35.3 +48.860000000,35.32 +48.860000000,35.34 +48.860000000,35.36 +48.860000000,35.38 +48.860000000,35.4 +48.860000000,35.42 +48.860000000,35.44 +48.860000000,35.46 +48.860000000,35.48 +48.860000000,35.5 +48.860000000,35.52 +48.860000000,35.54 +48.860000000,35.56 +48.860000000,35.58 +48.860000000,35.6 +48.860000000,35.62 +48.860000000,35.64 +48.860000000,35.66 +48.860000000,35.68 +48.860000000,35.7 +48.860000000,35.72 +48.860000000,35.74 +48.860000000,35.76 +48.860000000,35.78 +48.860000000,35.8 +48.860000000,35.82 +48.860000000,35.84 +48.860000000,35.86 +48.860000000,35.88 +48.860000000,35.9 +48.860000000,35.92 +48.860000000,35.94 +48.860000000,35.96 +48.860000000,35.98 +48.860000000,36 +48.860000000,36.02 +48.860000000,36.04 +48.860000000,36.06 +48.860000000,36.08 +48.860000000,36.1 +48.860000000,36.12 +48.860000000,36.14 +48.860000000,36.16 +48.860000000,36.18 +48.860000000,36.2 +48.860000000,36.22 +48.860000000,36.24 +48.860000000,36.26 +48.860000000,36.28 +48.860000000,36.3 +48.860000000,36.32 +48.860000000,36.34 +48.860000000,36.36 +48.860000000,36.38 +48.860000000,36.4 +48.860000000,36.42 +48.860000000,36.44 +48.860000000,36.46 +48.860000000,36.48 +48.860000000,36.5 +48.860000000,36.52 +48.860000000,36.54 +48.860000000,36.56 +48.860000000,36.58 +48.860000000,36.6 +48.860000000,36.62 +48.860000000,36.64 +48.860000000,36.66 +48.860000000,36.68 +48.860000000,36.7 +48.860000000,36.72 +48.860000000,36.74 +48.860000000,36.76 +48.860000000,36.78 +48.860000000,36.8 +48.860000000,36.82 +48.860000000,36.84 +48.860000000,36.86 +48.860000000,36.88 +48.860000000,36.9 +48.860000000,36.92 +48.860000000,36.94 +48.860000000,36.96 +48.860000000,36.98 +48.860000000,37 +48.860000000,37.02 +48.860000000,37.04 +48.860000000,37.06 +48.860000000,37.08 +48.860000000,37.1 +48.860000000,37.12 +48.860000000,37.14 +48.860000000,37.16 +48.860000000,37.18 +48.860000000,37.2 +48.860000000,37.22 +48.860000000,37.24 +48.860000000,37.26 +48.860000000,37.28 +48.860000000,37.3 +48.860000000,37.32 +48.860000000,37.34 +48.860000000,37.36 +48.860000000,37.38 +48.860000000,37.4 +48.860000000,37.42 +48.860000000,37.44 +48.860000000,37.46 +48.860000000,37.48 +48.860000000,37.5 +48.860000000,37.52 +48.860000000,37.54 +48.860000000,37.56 +48.860000000,37.58 +48.860000000,37.6 +48.860000000,37.62 +48.860000000,37.64 +48.860000000,37.66 +48.860000000,37.68 +48.860000000,37.7 +48.860000000,37.72 +48.860000000,37.74 +48.860000000,37.76 +48.860000000,37.78 +48.860000000,37.8 +48.860000000,37.82 +48.860000000,37.84 +48.860000000,37.86 +48.860000000,37.88 +48.860000000,37.9 +48.860000000,37.92 +48.860000000,37.94 +48.860000000,37.96 +48.860000000,37.98 +48.860000000,38 +48.860000000,38.02 +48.860000000,38.04 +48.860000000,38.06 +48.860000000,38.08 +48.860000000,38.1 +48.860000000,38.12 +48.860000000,38.14 +48.860000000,38.16 +48.860000000,38.18 +48.860000000,38.2 +48.860000000,38.22 +48.860000000,38.24 +48.860000000,38.26 +48.860000000,38.28 +48.860000000,38.3 +48.860000000,38.32 +48.860000000,38.34 +48.860000000,38.36 +48.860000000,38.38 +48.860000000,38.4 +48.860000000,38.42 +48.860000000,38.44 +48.860000000,38.46 +48.860000000,38.48 +48.860000000,38.5 +48.860000000,38.52 +48.860000000,38.54 +48.860000000,38.56 +48.860000000,38.58 +48.860000000,38.6 +48.860000000,38.62 +48.860000000,38.64 +48.860000000,38.66 +48.860000000,38.68 +48.860000000,38.7 +48.860000000,38.72 +48.860000000,38.74 +48.860000000,38.76 +48.860000000,38.78 +48.860000000,38.8 +48.860000000,38.82 +48.860000000,38.84 +48.860000000,38.86 +48.860000000,38.88 +48.860000000,38.9 +48.860000000,38.92 +48.860000000,38.94 +48.860000000,38.96 +48.860000000,38.98 +48.860000000,39 +48.860000000,39.02 +48.860000000,39.04 +48.860000000,39.06 +48.860000000,39.08 +48.860000000,39.1 +48.860000000,39.12 +48.860000000,39.14 +48.860000000,39.16 +48.860000000,39.18 +48.860000000,39.2 +48.860000000,39.22 +48.860000000,39.24 +48.860000000,39.26 +48.860000000,39.28 +48.860000000,39.3 +48.860000000,39.32 +48.860000000,39.34 +48.860000000,39.36 +48.860000000,39.38 +48.860000000,39.4 +48.860000000,39.42 +48.860000000,39.44 +48.860000000,39.46 +48.860000000,39.48 +48.860000000,39.5 +48.860000000,39.52 +48.860000000,39.54 +48.860000000,39.56 +48.860000000,39.58 +48.860000000,39.6 +48.860000000,39.62 +48.860000000,39.64 +48.860000000,39.66 +48.860000000,39.68 +48.860000000,39.7 +48.860000000,39.72 +48.860000000,39.74 +48.860000000,39.76 +48.860000000,39.78 +48.860000000,39.8 +48.860000000,39.82 +48.860000000,39.84 +48.860000000,39.86 +48.860000000,39.88 +48.860000000,39.9 +48.860000000,39.92 +48.860000000,39.94 +48.860000000,39.96 +48.860000000,39.98 +48.860000000,40 +48.860000000,40.02 +48.860000000,40.04 +48.860000000,40.06 +48.860000000,40.08 +48.860000000,40.1 +48.860000000,40.12 +48.860000000,40.14 +48.860000000,40.16 +48.860000000,40.18 +48.860000000,40.2 +48.860000000,40.22 +48.860000000,40.24 +48.860000000,40.26 +48.860000000,40.28 +48.860000000,40.3 +48.860000000,40.32 +48.860000000,40.34 +48.860000000,40.36 +48.860000000,40.38 +48.860000000,40.4 +48.860000000,40.42 +48.860000000,40.44 +48.860000000,40.46 +48.860000000,40.48 +48.860000000,40.5 +48.860000000,40.52 +48.860000000,40.54 +48.860000000,40.56 +48.860000000,40.58 +48.860000000,40.6 +48.860000000,40.62 +48.860000000,40.64 +48.860000000,40.66 +48.860000000,40.68 +48.860000000,40.7 +48.860000000,40.72 +48.860000000,40.74 +48.860000000,40.76 +48.860000000,40.78 +48.860000000,40.8 +48.860000000,40.82 +48.860000000,40.84 +48.860000000,40.86 +48.860000000,40.88 +48.860000000,40.9 +48.860000000,40.92 +48.860000000,40.94 +48.860000000,40.96 +48.860000000,40.98 +48.860000000,41 +48.860000000,41.02 +48.860000000,41.04 +48.860000000,41.06 +48.860000000,41.08 +48.860000000,41.1 +48.860000000,41.12 +48.860000000,41.14 +48.860000000,41.16 +48.860000000,41.18 +48.860000000,41.2 +48.860000000,41.22 +48.860000000,41.24 +48.860000000,41.26 +48.860000000,41.28 +48.860000000,41.3 +48.860000000,41.32 +48.860000000,41.34 +48.860000000,41.36 +48.860000000,41.38 +48.860000000,41.4 +48.860000000,41.42 +48.860000000,41.44 +48.860000000,41.46 +48.860000000,41.48 +48.860000000,41.5 +48.860000000,41.52 +48.860000000,41.54 +48.860000000,41.56 +48.860000000,41.58 +48.860000000,41.6 +48.860000000,41.62 +48.860000000,41.64 +48.860000000,41.66 +48.860000000,41.68 +48.860000000,41.7 +48.860000000,41.72 +48.860000000,41.74 +48.860000000,41.76 +48.860000000,41.78 +48.860000000,41.8 +48.860000000,41.82 +48.860000000,41.84 +48.860000000,41.86 +48.860000000,41.88 +48.860000000,41.9 +48.860000000,41.92 +48.860000000,41.94 +48.860000000,41.96 +48.860000000,41.98 +48.860000000,42 +48.860000000,42.02 +48.860000000,42.04 +48.860000000,42.06 +48.860000000,42.08 +48.860000000,42.1 +48.860000000,42.12 +48.860000000,42.14 +48.860000000,42.16 +48.860000000,42.18 +48.860000000,42.2 +48.860000000,42.22 +48.860000000,42.24 +48.860000000,42.26 +48.860000000,42.28 +48.860000000,42.3 +48.860000000,42.32 +48.860000000,42.34 +48.860000000,42.36 +48.860000000,42.38 +48.860000000,42.4 +48.860000000,42.42 +48.860000000,42.44 +48.860000000,42.46 +48.860000000,42.48 +48.860000000,42.5 +48.860000000,42.52 +48.860000000,42.54 +48.860000000,42.56 +48.860000000,42.58 +48.860000000,42.6 +48.860000000,42.62 +48.860000000,42.64 +48.860000000,42.66 +48.860000000,42.68 +48.860000000,42.7 +48.860000000,42.72 +48.860000000,42.74 +48.860000000,42.76 +48.860000000,42.78 +48.860000000,42.8 +48.860000000,42.82 +48.860000000,42.84 +48.860000000,42.86 +48.860000000,42.88 +48.860000000,42.9 +48.860000000,42.92 +48.860000000,42.94 +48.860000000,42.96 +48.860000000,42.98 +48.860000000,43 +48.860000000,43.02 +48.860000000,43.04 +48.860000000,43.06 +48.860000000,43.08 +48.860000000,43.1 +48.860000000,43.12 +48.860000000,43.14 +48.860000000,43.16 +48.860000000,43.18 +48.860000000,43.2 +48.860000000,43.22 +48.860000000,43.24 +48.860000000,43.26 +48.860000000,43.28 +48.860000000,43.3 +48.860000000,43.32 +48.860000000,43.34 +48.860000000,43.36 +48.860000000,43.38 +48.860000000,43.4 +48.860000000,43.42 +48.860000000,43.44 +48.860000000,43.46 +48.860000000,43.48 +48.860000000,43.5 +48.860000000,43.52 +48.860000000,43.54 +48.860000000,43.56 +48.860000000,43.58 +48.860000000,43.6 +48.860000000,43.62 +48.860000000,43.64 +48.860000000,43.66 +48.860000000,43.68 +48.860000000,43.7 +48.860000000,43.72 +48.860000000,43.74 +48.860000000,43.76 +48.860000000,43.78 +48.860000000,43.8 +48.860000000,43.82 +48.860000000,43.84 +48.860000000,43.86 +48.860000000,43.88 +48.860000000,43.9 +48.860000000,43.92 +48.860000000,43.94 +48.860000000,43.96 +48.860000000,43.98 +48.860000000,44 +48.860000000,44.02 +48.860000000,44.04 +48.860000000,44.06 +48.860000000,44.08 +48.860000000,44.1 +48.860000000,44.12 +48.860000000,44.14 +48.860000000,44.16 +48.860000000,44.18 +48.860000000,44.2 +48.860000000,44.22 +48.860000000,44.24 +48.860000000,44.26 +48.860000000,44.28 +48.860000000,44.3 +48.860000000,44.32 +48.860000000,44.34 +48.860000000,44.36 +48.860000000,44.38 +48.860000000,44.4 +48.860000000,44.42 +48.860000000,44.44 +48.860000000,44.46 +48.860000000,44.48 +48.860000000,44.5 +48.860000000,44.52 +48.860000000,44.54 +48.860000000,44.56 +48.860000000,44.58 +48.860000000,44.6 +48.860000000,44.62 +48.860000000,44.64 +48.860000000,44.66 +48.860000000,44.68 +48.860000000,44.7 +48.860000000,44.72 +48.860000000,44.74 +48.860000000,44.76 +48.860000000,44.78 +48.860000000,44.8 +48.860000000,44.82 +48.860000000,44.84 +48.860000000,44.86 +48.860000000,44.88 +48.860000000,44.9 +48.860000000,44.92 +48.860000000,44.94 +48.860000000,44.96 +48.860000000,44.98 +48.860000000,45 +48.860000000,45.02 +48.860000000,45.04 +48.860000000,45.06 +48.860000000,45.08 +48.860000000,45.1 +48.860000000,45.12 +48.860000000,45.14 +48.860000000,45.16 +48.860000000,45.18 +48.860000000,45.2 +48.860000000,45.22 +48.860000000,45.24 +48.860000000,45.26 +48.860000000,45.28 +48.860000000,45.3 +48.860000000,45.32 +48.860000000,45.34 +48.860000000,45.36 +48.860000000,45.38 +48.860000000,45.4 +48.860000000,45.42 +48.860000000,45.44 +48.860000000,45.46 +48.860000000,45.48 +48.860000000,45.5 +48.860000000,45.52 +48.860000000,45.54 +48.860000000,45.56 +48.860000000,45.58 +48.860000000,45.6 +48.860000000,45.62 +48.860000000,45.64 +48.860000000,45.66 +48.860000000,45.68 +48.860000000,45.7 +48.860000000,45.72 +48.860000000,45.74 +48.860000000,45.76 +48.860000000,45.78 +48.860000000,45.8 +48.860000000,45.82 +48.860000000,45.84 +48.860000000,45.86 +48.860000000,45.88 +48.860000000,45.9 +48.860000000,45.92 +48.860000000,45.94 +48.860000000,45.96 +48.860000000,45.98 +48.860000000,46 +48.860000000,46.02 +48.860000000,46.04 +48.860000000,46.06 +48.860000000,46.08 +48.860000000,46.1 +48.860000000,46.12 +48.860000000,46.14 +48.860000000,46.16 +48.860000000,46.18 +48.860000000,46.2 +48.860000000,46.22 +48.860000000,46.24 +48.860000000,46.26 +48.860000000,46.28 +48.860000000,46.3 +48.860000000,46.32 +48.860000000,46.34 +48.860000000,46.36 +48.860000000,46.38 +48.860000000,46.4 +48.860000000,46.42 +48.860000000,46.44 +48.860000000,46.46 +48.860000000,46.48 +48.860000000,46.5 +48.860000000,46.52 +48.860000000,46.54 +48.860000000,46.56 +48.860000000,46.58 +48.860000000,46.6 +48.860000000,46.62 +48.860000000,46.64 +48.860000000,46.66 +48.860000000,46.68 +48.860000000,46.7 +48.860000000,46.72 +48.860000000,46.74 +48.860000000,46.76 +48.860000000,46.78 +48.860000000,46.8 +48.860000000,46.82 +48.860000000,46.84 +48.860000000,46.86 +48.860000000,46.88 +48.860000000,46.9 +48.860000000,46.92 +48.860000000,46.94 +48.860000000,46.96 +48.860000000,46.98 +48.860000000,47 +48.860000000,47.02 +48.860000000,47.04 +48.860000000,47.06 +48.860000000,47.08 +48.860000000,47.1 +48.860000000,47.12 +48.860000000,47.14 +48.860000000,47.16 +48.860000000,47.18 +48.860000000,47.2 +48.860000000,47.22 +48.860000000,47.24 +48.860000000,47.26 +48.860000000,47.28 +48.860000000,47.3 +48.860000000,47.32 +48.860000000,47.34 +48.860000000,47.36 +48.860000000,47.38 +48.860000000,47.4 +48.860000000,47.42 +48.860000000,47.44 +48.860000000,47.46 +48.860000000,47.48 +48.860000000,47.5 +48.860000000,47.52 +48.860000000,47.54 +48.860000000,47.56 +48.860000000,47.58 +48.860000000,47.6 +48.860000000,47.62 +48.860000000,47.64 +48.860000000,47.66 +48.860000000,47.68 +48.860000000,47.7 +48.860000000,47.72 +48.860000000,47.74 +48.860000000,47.76 +48.860000000,47.78 +48.860000000,47.8 +48.860000000,47.82 +48.860000000,47.84 +48.860000000,47.86 +48.860000000,47.88 +48.860000000,47.9 +48.860000000,47.92 +48.860000000,47.94 +48.860000000,47.96 +48.860000000,47.98 +48.860000000,48 +48.860000000,48.02 +48.860000000,48.04 +48.860000000,48.06 +48.860000000,48.08 +48.860000000,48.1 +48.860000000,48.12 +48.860000000,48.14 +48.860000000,48.16 +48.860000000,48.18 +48.860000000,48.2 +48.860000000,48.22 +48.860000000,48.24 +48.860000000,48.26 +48.860000000,48.28 +48.860000000,48.3 +48.860000000,48.32 +48.860000000,48.34 +48.860000000,48.36 +48.860000000,48.38 +48.860000000,48.4 +48.860000000,48.42 +48.860000000,48.44 +48.860000000,48.46 +48.860000000,48.48 +48.860000000,48.5 +48.860000000,48.52 +48.860000000,48.54 +48.860000000,48.56 +48.860000000,48.58 +48.860000000,48.6 +48.860000000,48.62 +48.860000000,48.64 +48.860000000,48.66 +48.860000000,48.68 +48.860000000,48.7 +48.860000000,48.72 +48.860000000,48.74 +48.860000000,48.76 +48.860000000,48.78 +48.860000000,48.8 +48.860000000,48.82 +48.860000000,48.84 +48.860000000,48.86 +48.860000000,48.88 +48.860000000,48.9 +48.860000000,48.92 +48.860000000,48.94 +48.860000000,48.96 +48.860000000,48.98 +48.860000000,49 +48.860000000,49.02 +48.860000000,49.04 +48.860000000,49.06 +48.860000000,49.08 +48.860000000,49.1 +48.860000000,49.12 +48.860000000,49.14 +48.860000000,49.16 +48.860000000,49.18 +48.860000000,49.2 +48.860000000,49.22 +48.860000000,49.24 +48.860000000,49.26 +48.860000000,49.28 +48.860000000,49.3 +48.860000000,49.32 +48.860000000,49.34 +48.860000000,49.36 +48.860000000,49.38 +48.860000000,49.4 +48.860000000,49.42 +48.860000000,49.44 +48.860000000,49.46 +48.860000000,49.48 +48.860000000,49.5 +48.860000000,49.52 +48.860000000,49.54 +48.860000000,49.56 +48.860000000,49.58 +48.860000000,49.6 +48.860000000,49.62 +48.860000000,49.64 +48.860000000,49.66 +48.860000000,49.68 +48.860000000,49.7 +48.860000000,49.72 +48.860000000,49.74 +48.860000000,49.76 +48.860000000,49.78 +48.860000000,49.8 +48.860000000,49.82 +48.860000000,49.84 +48.860000000,49.86 +48.860000000,49.88 +48.860000000,49.9 +48.860000000,49.92 +48.860000000,49.94 +48.860000000,49.96 +48.860000000,49.98 +48.860000000,50 +48.860000000,50.02 +48.860000000,50.04 +48.860000000,50.06 +48.860000000,50.08 +48.860000000,50.1 +48.860000000,50.12 +48.860000000,50.14 +48.860000000,50.16 +48.860000000,50.18 +48.860000000,50.2 +48.860000000,50.22 +48.860000000,50.24 +48.860000000,50.26 +48.860000000,50.28 +48.860000000,50.3 +48.860000000,50.32 +48.860000000,50.34 +48.860000000,50.36 +48.860000000,50.38 +48.860000000,50.4 +48.860000000,50.42 +48.860000000,50.44 +48.860000000,50.46 +48.860000000,50.48 +48.860000000,50.5 +48.860000000,50.52 +48.860000000,50.54 +48.860000000,50.56 +48.860000000,50.58 +48.860000000,50.6 +48.860000000,50.62 +48.860000000,50.64 +48.860000000,50.66 +48.860000000,50.68 +48.860000000,50.7 +48.860000000,50.72 +48.860000000,50.74 +48.860000000,50.76 +48.860000000,50.78 +48.860000000,50.8 +48.860000000,50.82 +48.860000000,50.84 +48.860000000,50.86 +48.860000000,50.88 +48.860000000,50.9 +48.860000000,50.92 +48.860000000,50.94 +48.860000000,50.96 +48.860000000,50.98 +48.860000000,51 +48.860000000,51.02 +48.860000000,51.04 +48.860000000,51.06 +48.860000000,51.08 +48.860000000,51.1 +48.860000000,51.12 +48.860000000,51.14 +48.860000000,51.16 +48.860000000,51.18 +48.860000000,51.2 +48.860000000,51.22 +48.860000000,51.24 +48.860000000,51.26 +48.860000000,51.28 +48.860000000,51.3 +48.860000000,51.32 +48.860000000,51.34 +48.860000000,51.36 +48.860000000,51.38 +48.860000000,51.4 +48.860000000,51.42 +48.860000000,51.44 +48.860000000,51.46 +48.860000000,51.48 +48.860000000,51.5 +48.860000000,51.52 +48.860000000,51.54 +48.860000000,51.56 +48.860000000,51.58 +48.860000000,51.6 +48.860000000,51.62 +48.860000000,51.64 +48.860000000,51.66 +48.860000000,51.68 +48.860000000,51.7 +48.860000000,51.72 +48.860000000,51.74 +48.860000000,51.76 +48.860000000,51.78 +48.860000000,51.8 +48.860000000,51.82 +48.860000000,51.84 +48.860000000,51.86 +48.860000000,51.88 +48.860000000,51.9 +48.860000000,51.92 +48.860000000,51.94 +48.860000000,51.96 +48.860000000,51.98 +48.860000000,52 +48.860000000,52.02 +48.860000000,52.04 +48.860000000,52.06 +48.860000000,52.08 +48.860000000,52.1 +48.860000000,52.12 +48.860000000,52.14 +48.860000000,52.16 +48.860000000,52.18 +48.860000000,52.2 +48.860000000,52.22 +48.860000000,52.24 +48.860000000,52.26 +48.860000000,52.28 +48.860000000,52.3 +48.860000000,52.32 +48.860000000,52.34 +48.860000000,52.36 +48.860000000,52.38 +48.860000000,52.4 +48.860000000,52.42 +48.860000000,52.44 +48.860000000,52.46 +48.860000000,52.48 +48.860000000,52.5 +48.860000000,52.52 +48.860000000,52.54 +48.860000000,52.56 +48.860000000,52.58 +48.860000000,52.6 +48.860000000,52.62 +48.860000000,52.64 +48.860000000,52.66 +48.860000000,52.68 +48.860000000,52.7 +48.860000000,52.72 +48.860000000,52.74 +48.860000000,52.76 +48.860000000,52.78 +48.860000000,52.8 +48.860000000,52.82 +48.860000000,52.84 +48.860000000,52.86 +48.860000000,52.88 +48.860000000,52.9 +48.860000000,52.92 +48.860000000,52.94 +48.860000000,52.96 +48.860000000,52.98 +48.860000000,53 +48.860000000,53.02 +48.860000000,53.04 +48.860000000,53.06 +48.860000000,53.08 +48.860000000,53.1 +48.860000000,53.12 +48.860000000,53.14 +48.860000000,53.16 +48.860000000,53.18 +48.860000000,53.2 +48.860000000,53.22 +48.860000000,53.24 +48.860000000,53.26 +48.860000000,53.28 +48.860000000,53.3 +48.860000000,53.32 +48.860000000,53.34 +48.860000000,53.36 +48.860000000,53.38 +48.860000000,53.4 +48.860000000,53.42 +48.860000000,53.44 +48.860000000,53.46 +48.860000000,53.48 +48.860000000,53.5 +48.860000000,53.52 +48.860000000,53.54 +48.860000000,53.56 +48.860000000,53.58 +48.860000000,53.6 +48.860000000,53.62 +48.860000000,53.64 +48.860000000,53.66 +48.860000000,53.68 +48.860000000,53.7 +48.860000000,53.72 +48.860000000,53.74 +48.860000000,53.76 +48.860000000,53.78 +48.860000000,53.8 +48.860000000,53.82 +48.860000000,53.84 +48.860000000,53.86 +48.860000000,53.88 +48.860000000,53.9 +48.860000000,53.92 +48.860000000,53.94 +48.860000000,53.96 +48.860000000,53.98 +48.860000000,54 +48.860000000,54.02 +48.860000000,54.04 +48.860000000,54.06 +48.860000000,54.08 +48.860000000,54.1 +48.860000000,54.12 +48.860000000,54.14 +48.860000000,54.16 +48.860000000,54.18 +48.860000000,54.2 +48.860000000,54.22 +48.860000000,54.24 +48.860000000,54.26 +48.860000000,54.28 +48.860000000,54.3 +48.860000000,54.32 +48.860000000,54.34 +48.860000000,54.36 +48.860000000,54.38 +48.860000000,54.4 +48.860000000,54.42 +48.860000000,54.44 +48.860000000,54.46 +48.860000000,54.48 +48.860000000,54.5 +48.860000000,54.52 +48.860000000,54.54 +48.860000000,54.56 +48.860000000,54.58 +48.860000000,54.6 +48.860000000,54.62 +48.860000000,54.64 +48.860000000,54.66 +48.860000000,54.68 +48.860000000,54.7 +48.860000000,54.72 +48.860000000,54.74 +48.860000000,54.76 +48.860000000,54.78 +48.860000000,54.8 +48.860000000,54.82 +48.860000000,54.84 +48.860000000,54.86 +48.860000000,54.88 +48.860000000,54.9 +48.860000000,54.92 +48.860000000,54.94 +48.860000000,54.96 +48.860000000,54.98 +48.860000000,55 +48.860000000,55.02 +48.860000000,55.04 +48.860000000,55.06 +48.860000000,55.08 +48.860000000,55.1 +48.860000000,55.12 +48.860000000,55.14 +48.860000000,55.16 +48.860000000,55.18 +48.860000000,55.2 +48.860000000,55.22 +48.860000000,55.24 +48.860000000,55.26 +48.860000000,55.28 +48.860000000,55.3 +48.860000000,55.32 +48.860000000,55.34 +48.860000000,55.36 +48.860000000,55.38 +48.860000000,55.4 +48.860000000,55.42 +48.860000000,55.44 +48.860000000,55.46 +48.860000000,55.48 +48.860000000,55.5 +48.860000000,55.52 +48.860000000,55.54 +48.860000000,55.56 +48.860000000,55.58 +48.860000000,55.6 +48.860000000,55.62 +48.860000000,55.64 +48.860000000,55.66 +48.860000000,55.68 +48.860000000,55.7 +48.860000000,55.72 +48.860000000,55.74 +48.860000000,55.76 +48.860000000,55.78 +48.860000000,55.8 +48.860000000,55.82 +48.860000000,55.84 +48.860000000,55.86 +48.860000000,55.88 +48.860000000,55.9 +48.860000000,55.92 +48.860000000,55.94 +48.860000000,55.96 +48.860000000,55.98 +48.860000000,56 +48.860000000,56.02 +48.860000000,56.04 +48.860000000,56.06 +48.860000000,56.08 +48.860000000,56.1 +48.860000000,56.12 +48.860000000,56.14 +48.860000000,56.16 +48.860000000,56.18 +48.860000000,56.2 +48.860000000,56.22 +48.860000000,56.24 +48.860000000,56.26 +48.860000000,56.28 +48.860000000,56.3 +48.860000000,56.32 +48.860000000,56.34 +48.860000000,56.36 +48.860000000,56.38 +48.860000000,56.4 +48.860000000,56.42 +48.860000000,56.44 +48.860000000,56.46 +48.860000000,56.48 +48.860000000,56.5 +48.860000000,56.52 +48.860000000,56.54 +48.860000000,56.56 +48.860000000,56.58 +48.860000000,56.6 +48.860000000,56.62 +48.860000000,56.64 +48.860000000,56.66 +48.860000000,56.68 +48.860000000,56.7 +48.860000000,56.72 +48.860000000,56.74 +48.860000000,56.76 +48.860000000,56.78 +48.860000000,56.8 +48.860000000,56.82 +48.860000000,56.84 +48.860000000,56.86 +48.860000000,56.88 +48.860000000,56.9 +48.860000000,56.92 +48.860000000,56.94 +48.860000000,56.96 +48.860000000,56.98 +48.860000000,57 +48.860000000,57.02 +48.860000000,57.04 +48.860000000,57.06 +48.860000000,57.08 +48.860000000,57.1 +48.860000000,57.12 +48.860000000,57.14 +48.860000000,57.16 +48.860000000,57.18 +48.860000000,57.2 +48.860000000,57.22 +48.860000000,57.24 +48.860000000,57.26 +48.860000000,57.28 +48.860000000,57.3 +48.860000000,57.32 +48.860000000,57.34 +48.860000000,57.36 +48.860000000,57.38 +48.860000000,57.4 +48.860000000,57.42 +48.860000000,57.44 +48.860000000,57.46 +48.860000000,57.48 +48.860000000,57.5 +48.860000000,57.52 +48.860000000,57.54 +48.860000000,57.56 +48.860000000,57.58 +48.860000000,57.6 +48.860000000,57.62 +48.860000000,57.64 +48.860000000,57.66 +48.860000000,57.68 +48.860000000,57.7 +48.860000000,57.72 +48.860000000,57.74 +48.860000000,57.76 +48.860000000,57.78 +48.860000000,57.8 +48.860000000,57.82 +48.860000000,57.84 +48.860000000,57.86 +48.860000000,57.88 +48.860000000,57.9 +48.860000000,57.92 +48.860000000,57.94 +48.860000000,57.96 +48.860000000,57.98 +48.860000000,58 +48.860000000,58.02 +48.860000000,58.04 +48.860000000,58.06 +48.860000000,58.08 +48.860000000,58.1 +48.860000000,58.12 +48.860000000,58.14 +48.860000000,58.16 +48.860000000,58.18 +48.860000000,58.2 +48.860000000,58.22 +48.860000000,58.24 +48.860000000,58.26 +48.860000000,58.28 +48.860000000,58.3 +48.860000000,58.32 +48.860000000,58.34 +48.860000000,58.36 +48.860000000,58.38 +48.860000000,58.4 +48.860000000,58.42 +48.860000000,58.44 +48.860000000,58.46 +48.860000000,58.48 +48.860000000,58.5 +48.860000000,58.52 +48.860000000,58.54 +48.860000000,58.56 +48.860000000,58.58 +48.860000000,58.6 +48.860000000,58.62 +48.860000000,58.64 +48.860000000,58.66 +48.860000000,58.68 +48.860000000,58.7 +48.860000000,58.72 +48.860000000,58.74 +48.860000000,58.76 +48.860000000,58.78 +48.860000000,58.8 +48.860000000,58.82 +48.860000000,58.84 +48.860000000,58.86 +48.860000000,58.88 +48.860000000,58.9 +48.860000000,58.92 +48.860000000,58.94 +48.860000000,58.96 +48.860000000,58.98 +48.860000000,59 +48.860000000,59.02 +48.860000000,59.04 +48.860000000,59.06 +48.860000000,59.08 +48.860000000,59.1 +48.860000000,59.12 +48.860000000,59.14 +48.860000000,59.16 +48.860000000,59.18 +48.860000000,59.2 +48.860000000,59.22 +48.860000000,59.24 +48.860000000,59.26 +48.860000000,59.28 +48.860000000,59.3 +48.860000000,59.32 +48.860000000,59.34 +48.860000000,59.36 +48.860000000,59.38 +48.860000000,59.4 +48.860000000,59.42 +48.860000000,59.44 +48.860000000,59.46 +48.860000000,59.48 +48.860000000,59.5 +48.860000000,59.52 +48.860000000,59.54 +48.860000000,59.56 +48.860000000,59.58 +48.860000000,59.6 +48.860000000,59.62 +48.860000000,59.64 +48.860000000,59.66 +48.860000000,59.68 +48.860000000,59.7 +48.860000000,59.72 +48.860000000,59.74 +48.860000000,59.76 +48.860000000,59.78 +48.860000000,59.8 +48.860000000,59.82 +48.860000000,59.84 +48.860000000,59.86 +48.860000000,59.88 +48.860000000,59.9 +48.860000000,59.92 +48.860000000,59.94 +48.860000000,59.96 +48.860000000,59.98 +48.860000000,60 +48.860000000,60.02 +48.860000000,60.04 +48.860000000,60.06 +48.860000000,60.08 +48.860000000,60.1 +48.860000000,60.12 +48.860000000,60.14 +48.860000000,60.16 +48.860000000,60.18 +48.860000000,60.2 +48.860000000,60.22 +48.860000000,60.24 +48.860000000,60.26 +48.860000000,60.28 +48.860000000,60.3 +48.860000000,60.32 +48.860000000,60.34 +48.860000000,60.36 +48.860000000,60.38 +48.860000000,60.4 +48.860000000,60.42 +48.860000000,60.44 +48.860000000,60.46 +48.860000000,60.48 +48.860000000,60.5 +48.860000000,60.52 +48.860000000,60.54 +48.860000000,60.56 +48.860000000,60.58 +48.860000000,60.6 +48.860000000,60.62 +48.860000000,60.64 +48.860000000,60.66 +48.860000000,60.68 +48.860000000,60.7 +48.860000000,60.72 +48.860000000,60.74 +48.860000000,60.76 +48.860000000,60.78 +48.860000000,60.8 +48.860000000,60.82 +48.860000000,60.84 +48.860000000,60.86 +48.860000000,60.88 +48.860000000,60.9 +48.860000000,60.92 +48.860000000,60.94 +48.860000000,60.96 +48.860000000,60.98 +48.860000000,61 +48.860000000,61.02 +48.860000000,61.04 +48.860000000,61.06 +48.860000000,61.08 +48.860000000,61.1 +48.860000000,61.12 +48.860000000,61.14 +48.860000000,61.16 +48.860000000,61.18 +48.860000000,61.2 +48.860000000,61.22 +48.860000000,61.24 +48.860000000,61.26 +48.860000000,61.28 +48.860000000,61.3 +48.860000000,61.32 +48.860000000,61.34 +48.860000000,61.36 +48.860000000,61.38 +48.860000000,61.4 +48.860000000,61.42 +48.860000000,61.44 +48.860000000,61.46 +48.860000000,61.48 +48.860000000,61.5 +48.860000000,61.52 +48.860000000,61.54 +48.880000000,61.56 +48.900000000,61.58 +48.920000000,61.6 +48.940000000,61.62 +48.960000000,61.64 +48.980000000,61.66 +49.000000000,61.68 +49.020000000,61.7 +49.040000000,61.72 +49.060000000,61.74 +49.080000000,61.76 +49.100000000,61.78 +49.120000000,61.8 +49.140000000,61.82 +49.160000000,61.84 +49.180000000,61.86 +49.200000000,61.88 +49.220000000,61.9 +49.240000000,61.92 +49.260000000,61.94 +49.280000000,61.96 +49.300000000,61.98 +49.320000000,62 +49.340000000,62.02 +49.360000000,62.04 +49.380000000,62.06 +49.400000000,62.08 +49.420000000,62.1 +49.440000000,62.12 +49.460000000,62.14 +49.480000000,62.16 +49.500000000,62.18 +49.520000000,62.2 +49.540000000,62.22 +49.560000000,62.24 +49.580000000,62.26 +49.600000000,62.28 +49.620000000,62.3 +49.640000000,62.32 +49.660000000,62.34 +49.680000000,62.36 +49.700000000,62.38 +49.720000000,62.4 +49.740000000,62.42 +49.760000000,62.44 +49.780000000,62.46 +49.800000000,62.48 +49.820000000,62.5 +49.840000000,62.52 +49.860000000,62.54 +49.880000000,62.56 +49.900000000,62.56 +49.920000000,62.56 +49.940000000,62.56 +49.960000000,62.56 +49.980000000,62.56 +50.000000000,62.56 +50.020000000,62.56 +50.040000000,62.56 +50.060000000,62.56 +50.080000000,62.56 +50.100000000,62.56 +50.120000000,62.56 +50.140000000,62.56 +50.160000000,62.56 +50.180000000,62.56 +50.200000000,62.56 +50.220000000,62.56 +50.240000000,62.56 +50.260000000,62.56 +50.280000000,62.56 +50.300000000,62.56 +50.320000000,62.56 +50.340000000,62.56 +50.360000000,62.56 +50.380000000,62.56 +50.400000000,62.56 +50.420000000,62.56 +50.440000000,62.56 +50.460000000,62.56 +50.480000000,62.56 +50.500000000,62.56 +50.520000000,62.56 +50.540000000,62.56 +50.560000000,62.56 +50.580000000,62.56 +50.600000000,62.56 +50.620000000,62.56 +50.640000000,62.56 +50.660000000,62.56 +50.680000000,62.56 +50.700000000,62.56 +50.720000000,62.56 +50.740000000,62.56 +50.760000000,62.56 +50.780000000,62.56 +50.800000000,62.56 +50.820000000,62.56 +50.840000000,62.56 +50.860000000,62.56 +50.880000000,62.56 +50.900000000,62.56 +50.920000000,62.56 +50.940000000,62.56 +50.960000000,62.56 +50.980000000,62.56 +51.000000000,62.56 +51.020000000,62.56 +51.040000000,62.56 +51.060000000,62.56 +51.080000000,62.56 +51.100000000,62.56 +51.120000000,62.56 +51.140000000,62.56 +51.160000000,62.56 +51.180000000,62.56 +51.200000000,62.56 +51.220000000,62.56 +51.240000000,62.56 +51.260000000,62.56 +51.280000000,62.56 +51.300000000,62.56 +51.320000000,62.56 +51.340000000,62.56 +51.360000000,62.56 +51.380000000,62.56 +51.400000000,62.56 +51.420000000,62.56 +51.440000000,62.56 +51.460000000,62.56 +51.480000000,62.56 +51.500000000,62.56 +51.520000000,62.56 +51.540000000,62.56 +51.560000000,62.56 +51.580000000,62.56 +51.600000000,62.56 +51.620000000,62.56 +51.640000000,62.56 +51.660000000,62.56 +51.680000000,62.56 +51.700000000,62.56 +51.720000000,62.56 +51.740000000,62.56 +51.760000000,62.56 +51.780000000,62.56 +51.800000000,62.56 +51.820000000,62.56 +51.840000000,62.56 +51.860000000,62.56 +51.880000000,62.56 +51.900000000,62.56 +51.920000000,62.56 +51.940000000,62.56 +51.960000000,62.56 +51.980000000,62.56 +52.000000000,62.56 +52.020000000,62.56 +52.040000000,62.56 +52.060000000,62.56 +52.080000000,62.56 +52.100000000,62.56 +52.120000000,62.56 +52.140000000,62.56 +52.160000000,62.56 +52.180000000,62.56 +52.200000000,62.56 +52.220000000,62.56 +52.240000000,62.56 +52.260000000,62.56 +52.280000000,62.56 +52.300000000,62.56 +52.320000000,62.56 +52.340000000,62.56 +52.360000000,62.56 +52.380000000,62.56 +52.400000000,62.56 +52.420000000,62.56 +52.440000000,62.56 +52.460000000,62.56 +52.480000000,62.56 +52.500000000,62.56 +52.520000000,62.56 +52.540000000,62.56 +52.560000000,62.56 +52.580000000,62.56 +52.600000000,62.56 +52.620000000,62.56 +52.640000000,62.56 +52.660000000,62.56 +52.680000000,62.56 +52.700000000,62.56 +52.720000000,62.56 +52.740000000,62.56 +52.760000000,62.56 +52.780000000,62.56 +52.800000000,62.56 +52.820000000,62.56 +52.840000000,62.56 +52.860000000,62.56 +52.880000000,62.56 +52.900000000,62.56 +52.920000000,62.56 +52.940000000,62.56 +52.960000000,62.56 +52.980000000,62.56 +53.000000000,62.56 +53.020000000,62.56 +53.040000000,62.56 +53.060000000,62.56 +53.080000000,62.56 +53.100000000,62.56 +53.120000000,62.56 +53.140000000,62.56 +53.160000000,62.56 +53.180000000,62.56 +53.200000000,62.56 +53.220000000,62.56 +53.240000000,62.56 +53.260000000,62.56 +53.280000000,62.56 +53.300000000,62.56 +53.320000000,62.56 +53.340000000,62.56 +53.360000000,62.56 +53.380000000,62.56 +53.400000000,62.56 +53.420000000,62.56 +53.440000000,62.56 +53.460000000,62.56 +53.480000000,62.56 +53.500000000,62.56 +53.520000000,62.56 +53.540000000,62.56 +53.560000000,62.56 +53.580000000,62.56 +53.600000000,62.56 +53.620000000,62.56 +53.640000000,62.56 +53.660000000,62.56 +53.680000000,62.56 +53.700000000,62.56 +53.720000000,62.56 +53.740000000,62.56 +53.760000000,62.56 +53.780000000,62.56 +53.800000000,62.56 +53.820000000,62.56 +53.840000000,62.56 +53.860000000,62.56 +53.880000000,62.56 +53.900000000,62.56 +53.920000000,62.56 +53.940000000,62.56 +53.960000000,62.56 +53.980000000,62.56 +54.000000000,62.56 +54.020000000,62.56 +54.040000000,62.56 +54.060000000,62.56 +54.080000000,62.56 +54.100000000,62.56 +54.120000000,62.56 +54.140000000,62.56 +54.160000000,62.56 +54.180000000,62.56 +54.200000000,62.56 +54.220000000,62.56 +54.240000000,62.56 +54.260000000,62.56 +54.280000000,62.56 +54.300000000,62.56 +54.320000000,62.56 +54.340000000,62.56 +54.360000000,62.56 +54.380000000,62.56 +54.400000000,62.56 +54.420000000,62.56 +54.440000000,62.56 +54.460000000,62.56 +54.480000000,62.56 +54.500000000,62.56 +54.520000000,62.56 +54.540000000,62.56 +54.560000000,62.56 +54.580000000,62.56 +54.600000000,62.56 +54.620000000,62.56 +54.640000000,62.56 +54.660000000,62.56 +54.680000000,62.56 +54.700000000,62.56 +54.720000000,62.56 +54.740000000,62.56 +54.760000000,62.56 +54.780000000,62.56 +54.800000000,62.56 +54.820000000,62.56 +54.840000000,62.56 +54.860000000,62.56 +54.880000000,62.56 +54.900000000,62.56 +54.920000000,62.56 +54.940000000,62.56 +54.960000000,62.56 +54.980000000,62.56 +55.000000000,62.56 +55.020000000,62.56 +55.040000000,62.56 +55.060000000,62.56 +55.080000000,62.56 +55.100000000,62.56 +55.120000000,62.56 +55.140000000,62.56 +55.160000000,62.56 +55.180000000,62.56 +55.200000000,62.56 +55.220000000,62.56 +55.240000000,62.56 +55.260000000,62.56 +55.280000000,62.56 +55.300000000,62.56 +55.320000000,62.56 +55.340000000,62.56 +55.360000000,62.56 +55.380000000,62.56 +55.400000000,62.56 +55.420000000,62.56 +55.440000000,62.56 +55.460000000,62.56 +55.480000000,62.56 +55.500000000,62.56 +55.520000000,62.56 +55.540000000,62.56 +55.560000000,62.56 +55.580000000,62.56 +55.600000000,62.56 +55.620000000,62.56 +55.640000000,62.56 +55.660000000,62.56 +55.680000000,62.56 +55.700000000,62.56 +55.720000000,62.56 +55.740000000,62.56 +55.760000000,62.56 +55.780000000,62.56 +55.800000000,62.56 +55.820000000,62.56 +55.840000000,62.56 +55.860000000,62.56 +55.880000000,62.56 +55.900000000,62.56 +55.920000000,62.56 +55.940000000,62.56 +55.960000000,62.56 +55.980000000,62.56 +56.000000000,62.56 +56.020000000,62.56 +56.040000000,62.56 +56.060000000,62.56 +56.080000000,62.56 +56.100000000,62.56 +56.120000000,62.56 +56.140000000,62.56 +56.160000000,62.56 +56.180000000,62.56 +56.200000000,62.56 +56.220000000,62.56 +56.240000000,62.56 +56.260000000,62.56 +56.280000000,62.56 +56.300000000,62.56 +56.320000000,62.56 +56.340000000,62.56 +56.360000000,62.56 +56.380000000,62.56 +56.400000000,62.56 +56.420000000,62.56 +56.440000000,62.56 +56.460000000,62.56 +56.480000000,62.56 +56.500000000,62.56 +56.520000000,62.56 +56.540000000,62.56 +56.560000000,62.56 +56.580000000,62.56 +56.600000000,62.56 +56.620000000,62.56 +56.640000000,62.56 +56.660000000,62.56 +56.680000000,62.56 +56.700000000,62.56 +56.720000000,62.56 +56.740000000,62.56 +56.760000000,62.56 +56.780000000,62.56 +56.800000000,62.56 +56.820000000,62.56 +56.840000000,62.56 +56.860000000,62.56 +56.880000000,62.56 +56.900000000,62.56 +56.920000000,62.56 +56.940000000,62.56 +56.960000000,62.56 +56.980000000,62.56 +57.000000000,62.56 +57.020000000,62.56 +57.040000000,62.56 +57.060000000,62.56 +57.080000000,62.56 +57.100000000,62.56 +57.120000000,62.56 +57.140000000,62.56 +57.160000000,62.56 +57.180000000,62.56 +57.200000000,62.56 +57.220000000,62.56 +57.240000000,62.56 +57.260000000,62.56 +57.280000000,62.56 +57.300000000,62.56 +57.320000000,62.56 +57.340000000,62.56 +57.360000000,62.56 +57.380000000,62.56 +57.400000000,62.56 +57.420000000,62.56 +57.440000000,62.56 +57.460000000,62.56 +57.480000000,62.56 +57.500000000,62.56 +57.520000000,62.56 +57.540000000,62.56 +57.560000000,62.56 +57.580000000,62.56 +57.600000000,62.56 +57.620000000,62.56 +57.640000000,62.56 +57.660000000,62.56 +57.680000000,62.56 +57.700000000,62.56 +57.720000000,62.56 +57.740000000,62.56 +57.760000000,62.56 +57.780000000,62.56 +57.800000000,62.56 +57.820000000,62.56 +57.840000000,62.56 +57.860000000,62.56 +57.880000000,62.56 +57.900000000,62.56 +57.920000000,62.56 +57.940000000,62.56 +57.960000000,62.56 +57.980000000,62.56 +58.000000000,62.56 +58.020000000,62.56 +58.040000000,62.56 +58.060000000,62.56 +58.080000000,62.56 +58.100000000,62.56 +58.120000000,62.56 +58.140000000,62.56 +58.160000000,62.56 +58.180000000,62.56 +58.200000000,62.56 +58.220000000,62.56 +58.240000000,62.56 +58.260000000,62.56 +58.280000000,62.56 +58.300000000,62.56 +58.320000000,62.56 +58.340000000,62.56 +58.360000000,62.56 +58.380000000,62.56 +58.400000000,62.56 +58.420000000,62.56 +58.440000000,62.56 +58.460000000,62.56 +58.480000000,62.56 +58.500000000,62.56 +58.520000000,62.56 +58.540000000,62.56 +58.560000000,62.56 +58.580000000,62.56 +58.600000000,62.56 +58.620000000,62.56 +58.640000000,62.56 +58.660000000,62.56 +58.680000000,62.56 +58.700000000,62.56 +58.720000000,62.56 +58.740000000,62.56 +58.760000000,62.56 +58.780000000,62.56 +58.800000000,62.56 +58.820000000,62.56 +58.840000000,62.56 +58.860000000,62.56 +58.880000000,62.56 +58.900000000,62.56 +58.920000000,62.56 +58.940000000,62.56 +58.960000000,62.56 +58.980000000,62.56 +59.000000000,62.56 +59.020000000,62.56 +59.040000000,62.56 +59.060000000,62.56 +59.080000000,62.56 +59.100000000,62.56 +59.120000000,62.56 +59.140000000,62.56 +59.160000000,62.56 +59.180000000,62.56 +59.200000000,62.56 +59.220000000,62.56 +59.240000000,62.56 +59.260000000,62.56 +59.280000000,62.56 +59.300000000,62.56 +59.320000000,62.56 +59.340000000,62.56 +59.360000000,62.56 +59.380000000,62.56 +59.400000000,62.56 +59.420000000,62.56 +59.440000000,62.56 +59.460000000,62.56 +59.480000000,62.56 +59.500000000,62.56 +59.520000000,62.56 +59.540000000,62.56 +59.560000000,62.56 +59.580000000,62.56 +59.600000000,62.56 +59.620000000,62.56 +59.640000000,62.56 +59.660000000,62.56 +59.680000000,62.56 +59.700000000,62.56 +59.720000000,62.56 +59.740000000,62.56 +59.760000000,62.56 +59.780000000,62.56 +59.800000000,62.58 +59.820000000,62.6 +59.840000000,62.62 +59.860000000,62.64 +59.880000000,62.66 +59.900000000,62.68 +59.920000000,62.7 +59.940000000,62.72 +59.960000000,62.74 +59.980000000,62.76 +60.000000000,62.78 +60.020000000,62.8 +60.040000000,62.82 +60.060000000,62.84 +60.080000000,62.86 +60.100000000,62.88 +60.120000000,62.9 +60.140000000,62.92 +60.160000000,62.94 +60.180000000,62.96 +60.200000000,62.98 +60.220000000,63 +60.240000000,63.02 +60.260000000,63.04 +60.280000000,63.06 +60.300000000,63.08 +60.320000000,63.1 +60.340000000,63.12 +60.360000000,63.14 +60.380000000,63.16 +60.400000000,63.18 +60.420000000,63.2 +60.440000000,63.22 +60.460000000,63.24 +60.480000000,63.26 +60.500000000,63.28 +60.520000000,63.3 +60.540000000,63.32 +60.560000000,63.34 +60.580000000,63.36 +60.600000000,63.38 +60.620000000,63.4 +60.640000000,63.42 +60.660000000,63.44 +60.680000000,63.46 +60.700000000,63.48 +60.720000000,63.5 +60.740000000,63.52 +60.760000000,63.54 +60.780000000,63.56 +60.800000000,63.58 +60.800000000,63.6 +60.800000000,63.62 +60.800000000,63.64 +60.800000000,63.66 +60.800000000,63.68 +60.800000000,63.7 +60.800000000,63.72 +60.800000000,63.74 +60.800000000,63.76 +60.800000000,63.78 +60.800000000,63.8 +60.800000000,63.82 +60.800000000,63.84 +60.800000000,63.86 +60.800000000,63.88 +60.800000000,63.9 +60.800000000,63.92 +60.800000000,63.94 +60.800000000,63.96 +60.800000000,63.98 +60.800000000,64 +60.800000000,64.02 +60.800000000,64.04 +60.800000000,64.06 +60.800000000,64.08 +60.800000000,64.1 +60.800000000,64.12 +60.800000000,64.14 +60.800000000,64.16 +60.800000000,64.18 +60.800000000,64.2 +60.800000000,64.22 +60.800000000,64.24 +60.800000000,64.26 +60.800000000,64.28 +60.800000000,64.3 +60.800000000,64.32 +60.800000000,64.34 +60.800000000,64.36 +60.800000000,64.38 +60.800000000,64.4 +60.800000000,64.42 +60.800000000,64.44 +60.800000000,64.46 +60.800000000,64.48 +60.800000000,64.5 +60.800000000,64.52 +60.800000000,64.54 +60.800000000,64.56 +60.800000000,64.58 +60.800000000,64.6 +60.800000000,64.62 +60.800000000,64.64 +60.800000000,64.66 +60.800000000,64.68 +60.800000000,64.7 +60.800000000,64.72 +60.800000000,64.74 +60.800000000,64.76 +60.800000000,64.78 +60.800000000,64.8 +60.800000000,64.82 +60.800000000,64.84 +60.800000000,64.86 +60.800000000,64.88 +60.800000000,64.9 +60.800000000,64.92 +60.800000000,64.94 +60.800000000,64.96 +60.800000000,64.98 +60.800000000,65 +60.800000000,65.02 +60.800000000,65.04 +60.800000000,65.06 +60.800000000,65.08 +60.800000000,65.1 +60.800000000,65.12 +60.800000000,65.14 +60.800000000,65.16 +60.800000000,65.18 +60.800000000,65.2 +60.800000000,65.22 +60.800000000,65.24 +60.800000000,65.26 +60.800000000,65.28 +60.800000000,65.3 +60.800000000,65.32 +60.800000000,65.34 +60.800000000,65.36 +60.800000000,65.38 +60.800000000,65.4 +60.800000000,65.42 +60.800000000,65.44 +60.800000000,65.46 +60.800000000,65.48 +60.800000000,65.5 +60.800000000,65.52 +60.800000000,65.54 +60.800000000,65.56 +60.800000000,65.58 +60.800000000,65.6 +60.800000000,65.62 +60.800000000,65.64 +60.800000000,65.66 +60.800000000,65.68 +60.800000000,65.7 +60.800000000,65.72 +60.800000000,65.74 +60.800000000,65.76 +60.800000000,65.78 +60.800000000,65.8 +60.800000000,65.82 +60.800000000,65.84 +60.800000000,65.86 +60.800000000,65.88 +60.800000000,65.9 +60.800000000,65.92 +60.800000000,65.94 +60.800000000,65.96 +60.800000000,65.98 +60.800000000,66 +60.800000000,66.02 +60.800000000,66.04 +60.800000000,66.06 +60.800000000,66.08 +60.800000000,66.1 +60.800000000,66.12 +60.800000000,66.14 +60.800000000,66.16 +60.800000000,66.18 +60.800000000,66.2 +60.800000000,66.22 +60.800000000,66.24 +60.800000000,66.26 +60.800000000,66.28 +60.800000000,66.3 +60.800000000,66.32 +60.800000000,66.34 +60.800000000,66.36 +60.800000000,66.38 +60.800000000,66.4 +60.800000000,66.42 +60.800000000,66.44 +60.800000000,66.46 +60.800000000,66.48 +60.800000000,66.5 +60.800000000,66.52 +60.800000000,66.54 +60.800000000,66.56 +60.800000000,66.58 +60.800000000,66.6 +60.800000000,66.62 +60.800000000,66.64 +60.800000000,66.66 +60.800000000,66.68 +60.800000000,66.7 +60.800000000,66.72 +60.800000000,66.74 +60.800000000,66.76 +60.800000000,66.78 +60.800000000,66.8 +60.800000000,66.82 +60.800000000,66.84 +60.800000000,66.86 +60.800000000,66.88 +60.800000000,66.9 +60.800000000,66.92 +60.800000000,66.94 +60.800000000,66.96 +60.800000000,66.98 +60.800000000,67 +60.800000000,67.02 +60.800000000,67.04 +60.800000000,67.06 +60.800000000,67.08 +60.800000000,67.1 +60.800000000,67.12 +60.800000000,67.14 +60.800000000,67.16 +60.800000000,67.18 +60.800000000,67.2 +60.800000000,67.22 +60.800000000,67.24 +60.800000000,67.26 +60.800000000,67.28 +60.800000000,67.3 +60.800000000,67.32 +60.800000000,67.34 +60.800000000,67.36 +60.800000000,67.38 +60.800000000,67.4 +60.800000000,67.42 +60.800000000,67.44 +60.800000000,67.46 +60.800000000,67.48 +60.800000000,67.5 +60.800000000,67.52 +60.800000000,67.54 +60.800000000,67.56 +60.800000000,67.58 +60.800000000,67.6 +60.800000000,67.62 +60.800000000,67.64 +60.800000000,67.66 +60.800000000,67.68 +60.800000000,67.7 +60.800000000,67.72 +60.800000000,67.74 +60.800000000,67.76 +60.800000000,67.78 +60.800000000,67.8 +60.800000000,67.82 +60.800000000,67.84 +60.800000000,67.86 +60.800000000,67.88 +60.800000000,67.9 +60.800000000,67.92 +60.800000000,67.94 +60.800000000,67.96 +60.800000000,67.98 +60.800000000,68 +60.800000000,68.02 +60.800000000,68.04 +60.800000000,68.06 +60.800000000,68.08 +60.800000000,68.1 +60.800000000,68.12 +60.800000000,68.14 +60.800000000,68.16 +60.800000000,68.18 +60.800000000,68.2 +60.800000000,68.22 +60.800000000,68.24 +60.800000000,68.26 +60.800000000,68.28 +60.800000000,68.3 +60.800000000,68.32 +60.800000000,68.34 +60.800000000,68.36 +60.800000000,68.38 +60.800000000,68.4 +60.800000000,68.42 +60.800000000,68.44 +60.800000000,68.46 +60.800000000,68.48 +60.800000000,68.5 +60.800000000,68.52 +60.800000000,68.54 +60.800000000,68.56 +60.800000000,68.58 +60.800000000,68.6 +60.800000000,68.62 +60.800000000,68.64 +60.800000000,68.66 +60.800000000,68.68 +60.800000000,68.7 +60.800000000,68.72 +60.800000000,68.74 +60.800000000,68.76 +60.800000000,68.78 +60.800000000,68.8 +60.800000000,68.82 +60.800000000,68.84 +60.800000000,68.86 +60.800000000,68.88 +60.800000000,68.9 +60.800000000,68.92 +60.800000000,68.94 +60.800000000,68.96 +60.800000000,68.98 +60.800000000,69 +60.800000000,69.02 +60.800000000,69.04 +60.800000000,69.06 +60.800000000,69.08 +60.800000000,69.1 +60.800000000,69.12 +60.800000000,69.14 +60.800000000,69.16 +60.800000000,69.18 +60.800000000,69.2 +60.800000000,69.22 +60.800000000,69.24 +60.800000000,69.26 +60.800000000,69.28 +60.800000000,69.3 +60.800000000,69.32 +60.800000000,69.34 +60.800000000,69.36 +60.800000000,69.38 +60.800000000,69.4 +60.800000000,69.42 +60.800000000,69.44 +60.800000000,69.46 +60.800000000,69.48 +60.800000000,69.5 +60.800000000,69.52 +60.800000000,69.54 +60.800000000,69.56 +60.800000000,69.58 +60.800000000,69.6 +60.800000000,69.62 +60.800000000,69.64 +60.800000000,69.66 +60.800000000,69.68 +60.800000000,69.7 +60.800000000,69.72 +60.800000000,69.74 +60.800000000,69.76 +60.800000000,69.78 +60.800000000,69.8 +60.800000000,69.82 +60.800000000,69.84 +60.800000000,69.86 +60.800000000,69.88 +60.800000000,69.9 +60.800000000,69.92 +60.800000000,69.94 +60.800000000,69.96 +60.800000000,69.98 +60.800000000,70 +60.800000000,70.02 +60.800000000,70.04 +60.800000000,70.06 +60.800000000,70.08 +60.800000000,70.1 +60.800000000,70.12 +60.800000000,70.14 +60.800000000,70.16 +60.800000000,70.18 +60.800000000,70.2 +60.800000000,70.22 +60.800000000,70.24 +60.800000000,70.26 +60.800000000,70.28 +60.800000000,70.3 +60.800000000,70.32 +60.800000000,70.34 +60.800000000,70.36 +60.800000000,70.38 +60.800000000,70.4 +60.800000000,70.42 +60.800000000,70.44 +60.800000000,70.46 +60.800000000,70.48 +60.800000000,70.5 +60.800000000,70.52 +60.800000000,70.54 +60.800000000,70.56 +60.800000000,70.58 +60.800000000,70.6 +60.800000000,70.62 +60.800000000,70.64 +60.800000000,70.66 +60.800000000,70.68 +60.800000000,70.7 +60.800000000,70.72 +60.800000000,70.74 +60.800000000,70.76 +60.800000000,70.78 +60.800000000,70.8 +60.800000000,70.82 +60.800000000,70.84 +60.800000000,70.86 +60.800000000,70.88 +60.800000000,70.9 +60.800000000,70.92 +60.800000000,70.94 +60.800000000,70.96 +60.800000000,70.98 +60.800000000,71 +60.800000000,71.02 +60.800000000,71.04 +60.800000000,71.06 +60.800000000,71.08 +60.800000000,71.1 +60.800000000,71.12 +60.800000000,71.14 +60.800000000,71.16 +60.800000000,71.18 +60.800000000,71.2 +60.800000000,71.22 +60.800000000,71.24 +60.800000000,71.26 +60.800000000,71.28 +60.800000000,71.3 +60.800000000,71.32 +60.800000000,71.34 +60.800000000,71.36 +60.800000000,71.38 +60.800000000,71.4 +60.800000000,71.42 +60.800000000,71.44 +60.800000000,71.46 +60.800000000,71.48 +60.800000000,71.5 +60.800000000,71.52 +60.800000000,71.54 +60.800000000,71.56 +60.800000000,71.58 +60.800000000,71.6 +60.800000000,71.62 +60.800000000,71.64 +60.800000000,71.66 +60.800000000,71.68 +60.800000000,71.7 +60.800000000,71.72 +60.800000000,71.74 +60.800000000,71.76 +60.800000000,71.78 +60.800000000,71.8 +60.800000000,71.82 +60.800000000,71.84 +60.800000000,71.86 +60.800000000,71.88 +60.800000000,71.9 +60.800000000,71.92 +60.800000000,71.94 +60.800000000,71.96 +60.800000000,71.98 +60.800000000,72 +60.800000000,72.02 +60.800000000,72.04 +60.800000000,72.06 +60.800000000,72.08 +60.800000000,72.1 +60.800000000,72.12 +60.800000000,72.14 +60.800000000,72.16 +60.800000000,72.18 +60.800000000,72.2 +60.800000000,72.22 +60.800000000,72.24 +60.800000000,72.26 +60.800000000,72.28 +60.800000000,72.3 +60.800000000,72.32 +60.800000000,72.34 +60.800000000,72.36 +60.800000000,72.38 +60.800000000,72.4 +60.800000000,72.42 +60.800000000,72.44 +60.800000000,72.46 +60.800000000,72.48 +60.800000000,72.5 +60.800000000,72.52 +60.800000000,72.54 +60.800000000,72.56 +60.800000000,72.58 +60.800000000,72.6 +60.800000000,72.62 +60.800000000,72.64 +60.800000000,72.66 +60.800000000,72.68 +60.800000000,72.7 +60.800000000,72.72 +60.800000000,72.74 +60.800000000,72.76 +60.800000000,72.78 +60.800000000,72.8 +60.800000000,72.82 +60.800000000,72.84 +60.800000000,72.86 +60.800000000,72.88 +60.800000000,72.9 +60.800000000,72.92 +60.800000000,72.94 +60.800000000,72.96 +60.800000000,72.98 +60.800000000,73 +60.800000000,73.02 +60.800000000,73.04 +60.800000000,73.06 +60.800000000,73.08 +60.800000000,73.1 +60.800000000,73.12 +60.800000000,73.14 +60.800000000,73.16 +60.800000000,73.18 +60.800000000,73.2 +60.800000000,73.22 +60.800000000,73.24 +60.800000000,73.26 +60.800000000,73.28 +60.800000000,73.3 +60.800000000,73.32 +60.800000000,73.34 +60.800000000,73.36 +60.800000000,73.38 +60.800000000,73.4 +60.800000000,73.42 +60.800000000,73.44 +60.800000000,73.46 +60.800000000,73.48 +60.800000000,73.5 +60.800000000,73.52 +60.800000000,73.54 +60.800000000,73.56 +60.800000000,73.58 +60.800000000,73.6 +60.800000000,73.62 +60.800000000,73.64 +60.800000000,73.66 +60.800000000,73.68 +60.800000000,73.7 +60.800000000,73.72 +60.800000000,73.74 +60.800000000,73.76 +60.800000000,73.78 +60.800000000,73.8 +60.800000000,73.82 +60.800000000,73.84 +60.800000000,73.86 +60.800000000,73.88 +60.800000000,73.9 +60.800000000,73.92 +60.820000000,73.94 +60.840000000,73.96 +60.860000000,73.98 +60.880000000,74 +60.900000000,74.02 +60.920000000,74.04 +60.940000000,74.06 +60.960000000,74.08 +60.980000000,74.1 +61.000000000,74.12 +61.020000000,74.14 +61.040000000,74.16 +61.060000000,74.18 +61.080000000,74.2 +61.100000000,74.22 +61.120000000,74.24 +61.140000000,74.26 +61.160000000,74.28 +61.180000000,74.3 +61.200000000,74.32 +61.220000000,74.34 +61.240000000,74.36 +61.260000000,74.38 +61.280000000,74.4 +61.300000000,74.42 +61.320000000,74.44 +61.340000000,74.46 +61.360000000,74.48 +61.380000000,74.5 +61.400000000,74.52 +61.420000000,74.54 +61.440000000,74.56 +61.460000000,74.58 +61.480000000,74.6 +61.500000000,74.62 +61.520000000,74.64 +61.540000000,74.66 +61.560000000,74.68 +61.580000000,74.7 +61.600000000,74.72 +61.620000000,74.74 +61.640000000,74.76 +61.660000000,74.78 +61.680000000,74.8 +61.700000000,74.82 +61.720000000,74.84 +61.740000000,74.86 +61.760000000,74.88 +61.780000000,74.9 +61.800000000,74.92 +61.820000000,74.94 +61.840000000,74.94 +61.860000000,74.94 +61.880000000,74.94 +61.900000000,74.94 +61.920000000,74.94 +61.940000000,74.94 +61.960000000,74.94 +61.980000000,74.94 +62.000000000,74.94 +62.020000000,74.94 +62.040000000,74.94 +62.060000000,74.94 +62.080000000,74.94 +62.100000000,74.94 +62.120000000,74.94 +62.140000000,74.94 +62.160000000,74.94 +62.180000000,74.94 +62.200000000,74.94 +62.220000000,74.94 +62.240000000,74.94 +62.260000000,74.94 +62.280000000,74.94 +62.300000000,74.94 +62.320000000,74.94 +62.340000000,74.94 +62.360000000,74.94 +62.380000000,74.94 +62.400000000,74.94 +62.420000000,74.94 +62.440000000,74.94 +62.460000000,74.94 +62.480000000,74.94 +62.500000000,74.94 +62.520000000,74.94 +62.540000000,74.94 +62.560000000,74.94 +62.580000000,74.94 +62.600000000,74.94 +62.620000000,74.94 +62.640000000,74.94 +62.660000000,74.94 +62.680000000,74.94 +62.700000000,74.94 +62.720000000,74.94 +62.740000000,74.94 +62.760000000,74.94 +62.780000000,74.94 +62.800000000,74.94 +62.820000000,74.94 +62.840000000,74.94 +62.860000000,74.94 +62.880000000,74.94 +62.900000000,74.94 +62.920000000,74.94 +62.940000000,74.94 +62.960000000,74.94 +62.980000000,74.94 +63.000000000,74.94
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/old/regressiontest.sh Fri Feb 27 09:29:37 2015 +0000 @@ -0,0 +1,17 @@ +#!/bin/bash + +mydir=$(dirname "$0") + +sonic-annotator --minversion 1.1 || exit 1 + +VAMP_PATH="${mydir}/../.." \ + sonic-annotator \ + -d vamp:match-vamp-plugin:match \ + --multiplex \ + ~/Music/cc-kids-abrsm-dataset/ABRSM/Allegro\ in\ G.mp3 \ + ~/Music/cc-kids-abrsm-dataset/Kids/Allegro\ in\ G.mp3 \ + -w csv --csv-stdout 2>/dev/null | sed 's/^[^,]*,//' > /tmp/$$ || exit 1 + +sdiff -w 78 /tmp/$$ `dirname $0`/expected.csv && echo Passed + +rm /tmp/$$
--- a/test/regressiontest.sh Fri Nov 14 10:24:13 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -#!/bin/bash - -mydir=$(dirname "$0") - -sonic-annotator --minversion 1.1 || exit 1 - -VAMP_PATH="${mydir}/.." \ - sonic-annotator \ - -d vamp:match-vamp-plugin:match \ - --multiplex \ - ~/Music/cc-kids-abrsm-dataset/ABRSM/Allegro\ in\ G.mp3 \ - ~/Music/cc-kids-abrsm-dataset/Kids/Allegro\ in\ G.mp3 \ - -w csv --csv-stdout 2>/dev/null | sed 's/^[^,]*,//' > /tmp/$$ || exit 1 - -sdiff -w 78 /tmp/$$ `dirname $0`/expected.csv && echo Passed - -rm /tmp/$$