Mercurial > hg > pyin
changeset 144:9ec558ed83d4
Merge from branch fixedlag
author | Chris Cannam |
---|---|
date | Fri, 24 Mar 2017 15:08:12 +0000 |
parents | 5c1572dd225a (current diff) 218bfe953159 (diff) |
children | 0432723faf03 |
files | MonoPitch.cpp MonoPitch.h |
diffstat | 24 files changed, 5313 insertions(+), 459 deletions(-) [+] |
line wrap: on
line diff
--- a/LocalCandidatePYIN.cpp Thu Aug 20 16:06:01 2015 +0100 +++ b/LocalCandidatePYIN.cpp Fri Mar 24 15:08:12 2017 +0000 @@ -12,7 +12,7 @@ */ #include "LocalCandidatePYIN.h" -#include "MonoPitch.h" +#include "MonoPitchHMM.h" #include "YinUtil.h" #include "vamp-sdk/FFT.h" @@ -48,12 +48,14 @@ m_preciseTime(0.0f), m_pitchProb(0), m_timestamp(0), - m_nCandidate(13) + m_nCandidate(13), + m_yinUtil(0) { } LocalCandidatePYIN::~LocalCandidatePYIN() { + delete m_yinUtil; } string @@ -85,7 +87,7 @@ { // Increment this each time you release a version that behaves // differently from the previous one - return 2; + return 3; } string @@ -226,7 +228,7 @@ } void -LocalCandidatePYIN::selectProgram(string name) +LocalCandidatePYIN::selectProgram(string) { } @@ -268,6 +270,8 @@ m_channels = channels; m_stepSize = stepSize; m_blockSize = blockSize; + + m_yinUtil = new YinUtil(m_blockSize/2); reset(); @@ -297,20 +301,19 @@ size_t yinBufferSize = m_blockSize/2; double* yinBuffer = new double[yinBufferSize]; - if (!m_preciseTime) YinUtil::fastDifference(dInputBuffers, yinBuffer, yinBufferSize); - else YinUtil::slowDifference(dInputBuffers, yinBuffer, yinBufferSize); + if (!m_preciseTime) m_yinUtil->fastDifference(dInputBuffers, yinBuffer); + else m_yinUtil->slowDifference(dInputBuffers, yinBuffer); delete [] dInputBuffers; - YinUtil::cumulativeDifference(yinBuffer, yinBufferSize); + m_yinUtil->cumulativeDifference(yinBuffer); float minFrequency = 60; float maxFrequency = 900; - vector<double> peakProbability = YinUtil::yinProb(yinBuffer, - m_threshDistr, - yinBufferSize, - m_inputSampleRate/maxFrequency, - m_inputSampleRate/minFrequency); + vector<double> peakProbability = m_yinUtil->yinProb(yinBuffer, + m_threshDistr, + m_inputSampleRate/maxFrequency, + m_inputSampleRate/minFrequency); vector<pair<double, double> > tempPitchProb; for (size_t iBuf = 0; iBuf < yinBufferSize; ++iBuf) @@ -319,7 +322,7 @@ { double currentF0 = m_inputSampleRate * (1.0 / - YinUtil::parabolicInterpolation(yinBuffer, iBuf, yinBufferSize)); + m_yinUtil->parabolicInterpolation(yinBuffer, iBuf)); double tempPitch = 12 * std::log(currentF0/440)/std::log(2.) + 69; tempPitchProb.push_back(pair<double, double>(tempPitch, peakProbability[iBuf])); } @@ -345,7 +348,7 @@ } // MONO-PITCH STUFF - MonoPitch mp; + MonoPitchHMM hmm(0); size_t nFrame = m_timestamp.size(); vector<vector<float> > pitchTracks; vector<float> freqSum = vector<float>(m_nCandidate); @@ -359,11 +362,11 @@ for (size_t iCandidate = 0; iCandidate < m_nCandidate; ++iCandidate) { pitchTracks.push_back(vector<float>(nFrame)); - vector<vector<pair<double,double> > > tempPitchProb; + vector<pair<double,double> > tempPitchProb; + vector<vector<double> > tempObsProb; float centrePitch = 45 + 3 * iCandidate; for (size_t iFrame = 0; iFrame < nFrame; ++iFrame) { - tempPitchProb.push_back(vector<pair<double,double> >()); float sumProb = 0; float pitch = 0; float prob = 0; @@ -374,26 +377,33 @@ boost::math::pdf(normalDist, pitch-centrePitch) / maxNormalDist * 2; sumProb += prob; - tempPitchProb[iFrame].push_back( + tempPitchProb.push_back( pair<double,double>(pitch,prob)); } for (size_t iProb = 0; iProb < m_pitchProb[iFrame].size(); ++iProb) { - tempPitchProb[iFrame][iProb].second /= sumProb; + tempPitchProb[iProb].second /= sumProb; } + tempObsProb.push_back(hmm.calculateObsProb(tempPitchProb)); } - vector<float> mpOut = mp.process(tempPitchProb); - float prevFreq = 0; - for (size_t iFrame = 0; iFrame < nFrame; ++iFrame) + vector<int> rawPitchPath = hmm.decodeViterbi(tempObsProb); + vector<float> mpOut; + + for (size_t iFrame = 0; iFrame < rawPitchPath.size(); ++iFrame) + { + float freq = hmm.nearestFreq(rawPitchPath[iFrame], + m_pitchProb[iFrame]); + mpOut.push_back(freq); // for note processing below + } + + for (size_t iFrame = 0; iFrame < rawPitchPath.size(); ++iFrame) { if (mpOut[iFrame] > 0) { pitchTracks[iCandidate][iFrame] = mpOut[iFrame]; freqSum[iCandidate] += mpOut[iFrame]; freqNumber[iCandidate]++; - prevFreq = mpOut[iFrame]; - } } freqMean[iCandidate] = freqSum[iCandidate]*1.0/freqNumber[iCandidate];
--- a/LocalCandidatePYIN.h Thu Aug 20 16:06:01 2015 +0100 +++ b/LocalCandidatePYIN.h Fri Mar 24 15:08:12 2017 +0000 @@ -18,6 +18,8 @@ #include "Yin.h" +class YinUtil; + class LocalCandidatePYIN : public Vamp::Plugin { public: @@ -70,6 +72,8 @@ vector<vector<pair<double, double> > > m_pitchProb; vector<Vamp::RealTime> m_timestamp; size_t m_nCandidate; + + YinUtil *m_yinUtil; }; #endif
--- a/Makefile.inc Thu Aug 20 16:06:01 2015 +0100 +++ b/Makefile.inc Fri Mar 24 15:08:12 2017 +0000 @@ -15,7 +15,6 @@ Yin.cpp \ YinUtil.cpp \ MonoNote.cpp \ - MonoPitch.cpp \ MonoNoteParameters.cpp \ SparseHMM.cpp \ MonoNoteHMM.cpp \ @@ -27,14 +26,15 @@ test/test-fft \ test/test-yin \ test/test-mononote - + OBJECTS := $(SOURCES:.cpp=.o) OBJECTS := $(OBJECTS:.c=.o) PLUGIN_OBJECTS := $(OBJECTS) $(PLUGIN_MAIN:.cpp=.o) all: $(PLUGIN) $(TESTS) - for t in $(TESTS); do echo "Running $$t"; ./"$$t" || exit 1; done + @for t in $(TESTS); do echo; echo "Running $$t"; ./"$$t" || exit 1; done + @echo; bash ./test/regression.sh plugin: $(PLUGIN) @@ -65,15 +65,14 @@ # DO NOT DELETE libmain.o: PYinVamp.h Yin.h MeanFilter.h YinVamp.h LocalCandidatePYIN.h -LocalCandidatePYIN.o: LocalCandidatePYIN.h Yin.h MeanFilter.h MonoPitch.h +LocalCandidatePYIN.o: LocalCandidatePYIN.h Yin.h MeanFilter.h LocalCandidatePYIN.o: MonoPitchHMM.h SparseHMM.h YinUtil.h MonoNote.o: MonoNote.h MonoNoteHMM.h MonoNoteParameters.h SparseHMM.h MonoNoteHMM.o: MonoNoteHMM.h MonoNoteParameters.h SparseHMM.h MonoNoteParameters.o: MonoNoteParameters.h -MonoPitch.o: MonoPitch.h MonoPitchHMM.h SparseHMM.h MonoPitchHMM.o: MonoPitchHMM.h SparseHMM.h PYinVamp.o: PYinVamp.h Yin.h MeanFilter.h MonoNote.h MonoNoteHMM.h -PYinVamp.o: MonoNoteParameters.h SparseHMM.h MonoPitch.h MonoPitchHMM.h +PYinVamp.o: MonoNoteParameters.h SparseHMM.h MonoPitchHMM.h SparseHMM.o: SparseHMM.h Yin.o: Yin.h MeanFilter.h YinUtil.h YinUtil.o: YinUtil.h MeanFilter.h @@ -90,7 +89,6 @@ LocalCandidatePYIN.o: Yin.h MeanFilter.h MonoNote.o: MonoNoteHMM.h MonoNoteParameters.h SparseHMM.h MonoNoteHMM.o: MonoNoteParameters.h SparseHMM.h -MonoPitch.o: MonoPitchHMM.h SparseHMM.h MonoPitchHMM.o: SparseHMM.h PYinVamp.o: Yin.h MeanFilter.h Yin.o: MeanFilter.h
--- a/Makefile.linux64 Thu Aug 20 16:06:01 2015 +0100 +++ b/Makefile.linux64 Fri Mar 24 15:08:12 2017 +0000 @@ -1,5 +1,6 @@ -CFLAGS := $(CFLAGS) -Wall -O3 -fPIC -I../vamp-plugin-sdk/ -I../../vamp-plugin-sdk/ +CFLAGS := $(CFLAGS) -Wall -O3 -ffast-math -fPIC -I../vamp-plugin-sdk/ -I../../vamp-plugin-sdk/ +#CFLAGS := $(CFLAGS) -Wall -Wextra -Werror -g -fPIC -I../vamp-plugin-sdk/ -I../../vamp-plugin-sdk/ CXXFLAGS := $(CXXFLAGS) $(CFLAGS)
--- a/Makefile.osx Thu Aug 20 16:06:01 2015 +0100 +++ b/Makefile.osx Fri Mar 24 15:08:12 2017 +0000 @@ -2,7 +2,7 @@ CFLAGS := $(ARCHFLAGS) -O3 -I../vamp-plugin-sdk -I../../vamp-plugin-sdk -I/usr/local/boost -Wall -fPIC CXXFLAGS := $(CFLAGS) -LDFLAGS := -L../vamp-plugin-sdk -L../../vamp-plugin-sdk -lvamp-sdk $(ARCHFLAGS) +LDFLAGS := -L../vamp-plugin-sdk -L../vamp-plugin-sdk -lvamp-sdk $(ARCHFLAGS) -L/usr/local/lib PLUGIN_LDFLAGS := -dynamiclib $(LDFLAGS) -exported_symbols_list vamp-plugin.list TEST_LDFLAGS := $(LDFLAGS) -lboost_unit_test_framework PLUGIN_EXT := .dylib
--- a/MonoNote.cpp Thu Aug 20 16:06:01 2015 +0100 +++ b/MonoNote.cpp Fri Mar 24 15:08:12 2017 +0000 @@ -22,7 +22,7 @@ using std::pair; MonoNote::MonoNote() : - hmm() + hmm(0) { } @@ -39,11 +39,9 @@ obsProb.push_back(hmm.calculateObsProb(pitchProb[iFrame])); } - vector<double> *scale = new vector<double>(pitchProb.size()); - vector<MonoNote::FrameOutput> out; - vector<int> path = hmm.decodeViterbi(obsProb, scale); + vector<int> path = hmm.decodeViterbi(obsProb); for (size_t iFrame = 0; iFrame < path.size(); ++iFrame) { @@ -54,8 +52,6 @@ stateKind = (path[iFrame]) % hmm.par.nSPP + 1; out.push_back(FrameOutput(iFrame, currPitch, stateKind)); - // std::cerr << path[iFrame] << " -- "<< pitchProb[iFrame][0].first << " -- "<< currPitch << " -- " << stateKind << std::endl; } - delete scale; return(out); }
--- a/MonoNoteHMM.cpp Thu Aug 20 16:06:01 2015 +0100 +++ b/MonoNoteHMM.cpp Fri Mar 24 15:08:12 2017 +0000 @@ -21,7 +21,8 @@ using std::vector; using std::pair; -MonoNoteHMM::MonoNoteHMM() : +MonoNoteHMM::MonoNoteHMM(int fixedLag) : + SparseHMM(fixedLag), par() { build(); @@ -36,14 +37,13 @@ // what is the probability of pitched double pIsPitched = 0; - for (size_t iCandidate = 0; iCandidate < nCandidate; ++iCandidate) + for (size_t iCand = 0; iCand < nCandidate; ++iCand) { - // pIsPitched = pitchProb[iCandidate].second > pIsPitched ? pitchProb[iCandidate].second : pIsPitched; - pIsPitched += pitchProb[iCandidate].second; + pIsPitched += pitchProb[iCand].second; } - // pIsPitched = std::pow(pIsPitched, (1-par.priorWeight)) * std::pow(par.priorPitchedProb, par.priorWeight); - pIsPitched = pIsPitched * (1-par.priorWeight) + par.priorPitchedProb * par.priorWeight; + pIsPitched = pIsPitched * (1-par.priorWeight) + + par.priorPitchedProb * par.priorWeight; vector<double> out = vector<double>(par.n); double tempProbSum = 0; @@ -58,14 +58,15 @@ double minDist = 10000.0; double minDistProb = 0; size_t minDistCandidate = 0; - for (size_t iCandidate = 0; iCandidate < nCandidate; ++iCandidate) + for (size_t iCand = 0; iCand < nCandidate; ++iCand) { - double currDist = std::abs(getMidiPitch(i)-pitchProb[iCandidate].first); + double currDist = std::abs(getMidiPitch(i)- + pitchProb[iCand].first); if (currDist < minDist) { minDist = currDist; - minDistProb = pitchProb[iCandidate].second; - minDistCandidate = iCandidate; + minDistProb = pitchProb[iCand].second; + minDistCandidate = iCand; } } tempProb = std::pow(minDistProb, par.yinTrust) * @@ -107,6 +108,8 @@ // 3. attack state // ... + m_nState = par.n; + // observation distributions for (size_t iState = 0; iState < par.n; ++iState) { @@ -114,9 +117,9 @@ if (iState % par.nSPP == 2) { // silent state starts tracking - init.push_back(1.0/(par.nS * par.nPPS)); + m_init.push_back(1.0/(par.nS * par.nPPS)); } else { - init.push_back(0.0); + m_init.push_back(0.0); } } @@ -137,27 +140,27 @@ size_t index = iPitch * par.nSPP; // transitions from attack state - from.push_back(index); - to.push_back(index); - transProb.push_back(par.pAttackSelftrans); + m_from.push_back(index); + m_to.push_back(index); + m_transProb.push_back(par.pAttackSelftrans); - from.push_back(index); - to.push_back(index+1); - transProb.push_back(1-par.pAttackSelftrans); + m_from.push_back(index); + m_to.push_back(index+1); + m_transProb.push_back(1-par.pAttackSelftrans); // transitions from stable state - from.push_back(index+1); - to.push_back(index+1); // to itself - transProb.push_back(par.pStableSelftrans); + m_from.push_back(index+1); + m_to.push_back(index+1); // to itself + m_transProb.push_back(par.pStableSelftrans); - from.push_back(index+1); - to.push_back(index+2); // to silent - transProb.push_back(par.pStable2Silent); + m_from.push_back(index+1); + m_to.push_back(index+2); // to silent + m_transProb.push_back(par.pStable2Silent); // the "easy" transitions from silent state - from.push_back(index+2); - to.push_back(index+2); - transProb.push_back(par.pSilentSelftrans); + m_from.push_back(index+2); + m_to.push_back(index+2); + m_transProb.push_back(par.pSilentSelftrans); // the more complicated transitions from the silent @@ -171,7 +174,7 @@ double semitoneDistance = std::abs(fromPitch - toPitch) * 1.0 / par.nPPS; - // if (std::fmod(semitoneDistance, 1) == 0 && semitoneDistance > par.minSemitoneDistance) + if (semitoneDistance == 0 || (semitoneDistance > par.minSemitoneDistance && semitoneDistance < par.maxJump)) @@ -184,15 +187,19 @@ tempTransProbSilent.push_back(tempWeightSilent); - from.push_back(index+2); - to.push_back(toIndex); + m_from.push_back(index+2); + m_to.push_back(toIndex); } } for (size_t i = 0; i < tempTransProbSilent.size(); ++i) { - transProb.push_back((1-par.pSilentSelftrans) * tempTransProbSilent[i]/probSumSilent); + m_transProb.push_back((1-par.pSilentSelftrans) * + tempTransProbSilent[i]/probSumSilent); } } + m_nTrans = m_transProb.size(); + m_delta = vector<double>(m_nState); + m_oldDelta = vector<double>(m_nState); } double
--- a/MonoNoteHMM.h Thu Aug 20 16:06:01 2015 +0100 +++ b/MonoNoteHMM.h Fri Mar 24 15:08:12 2017 +0000 @@ -27,8 +27,9 @@ class MonoNoteHMM : public SparseHMM { public: - MonoNoteHMM(); + MonoNoteHMM(int fixedLag); const std::vector<double> calculateObsProb(const vector<pair<double, double> >); + double getMidiPitch(size_t index); double getFrequency(size_t index); void build();
--- a/MonoPitch.cpp Thu Aug 20 16:06:01 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - pYIN - A fundamental frequency estimator for monophonic audio - 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 "MonoPitch.h" -#include "MonoPitchHMM.h" -#include <vector> - -#include <cstdio> -#include <cmath> -#include <complex> - -using std::vector; -using std::pair; - -MonoPitch::MonoPitch() : - hmm() -{ -} - -MonoPitch::~MonoPitch() -{ -} - -const vector<float> -MonoPitch::process(const vector<vector<pair<double, double> > > pitchProb) -{ - // std::cerr << "before observation prob calculation" << std::endl; - vector<vector<double> > obsProb; - for (size_t iFrame = 0; iFrame < pitchProb.size(); ++iFrame) - { - obsProb.push_back(hmm.calculateObsProb(pitchProb[iFrame])); - } - - vector<double> *scale = new vector<double>(0); - - vector<float> out; - - // std::cerr << "before Viterbi decoding" << obsProb.size() << "ng" << obsProb[1].size() << std::endl; - vector<int> path = hmm.decodeViterbi(obsProb, scale); - // std::cerr << "after Viterbi decoding" << std::endl; - - for (size_t iFrame = 0; iFrame < path.size(); ++iFrame) - { - // std::cerr << path[iFrame] << " " << hmm.m_freqs[path[iFrame]] << std::endl; - float hmmFreq = hmm.m_freqs[path[iFrame]]; - float bestFreq = 0; - float leastDist = 10000; - if (hmmFreq > 0) - { - // This was a Yin estimate, so try to get original pitch estimate back - // ... a bit hacky, since we could have direclty saved the frequency - // that was assigned to the HMM bin in hmm.calculateObsProb -- but would - // have had to rethink the interface of that method. - for (size_t iPitch = 0; iPitch < pitchProb[iFrame].size(); ++iPitch) - { - float freq = 440. * std::pow(2, (pitchProb[iFrame][iPitch].first - 69)/12); - float dist = std::abs(hmmFreq-freq); - if (dist < leastDist) - { - leastDist = dist; - bestFreq = freq; - } - } - } else { - bestFreq = hmmFreq; - } - out.push_back(bestFreq); - } - delete scale; - return(out); -}
--- a/MonoPitch.h Thu Aug 20 16:06:01 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - pYIN - A fundamental frequency estimator for monophonic audio - 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 _MONOPITCH_H_ -#define _MONOPITCH_H_ - -#include "MonoPitchHMM.h" - -#include <iostream> -#include <vector> -#include <exception> - -using std::vector; -using std::pair; - -class MonoPitch { -public: - MonoPitch(); - virtual ~MonoPitch(); - - // pitchProb is a frame-wise vector carrying a vector of pitch-probability pairs - const vector<float> process(const vector<vector<pair<double, double> > > pitchProb); -private: - MonoPitchHMM hmm; -}; - -#endif
--- a/MonoPitchHMM.cpp Thu Aug 20 16:06:01 2015 +0100 +++ b/MonoPitchHMM.cpp Fri Mar 24 15:08:12 2017 +0000 @@ -17,23 +17,26 @@ #include <cstdio> #include <cmath> +#include <iostream> using std::vector; using std::pair; -MonoPitchHMM::MonoPitchHMM() : -m_minFreq(61.735), -m_nBPS(5), -m_nPitch(0), -m_transitionWidth(0), -m_selfTrans(0.99), -m_yinTrust(.5), -m_freqs(0) +MonoPitchHMM::MonoPitchHMM(int fixedLag) : + SparseHMM(fixedLag), + m_minFreq(61.735), + m_nBPS(5), + m_nPitch(0), + m_transitionWidth(0), + m_selfTrans(0.99), + m_yinTrust(.5), + m_freqs(0) { m_transitionWidth = 5*(m_nBPS/2) + 1; m_nPitch = 69 * m_nBPS; + m_nState = 2 * m_nPitch; // voiced and unvoiced m_freqs = vector<double>(2*m_nPitch); - for (size_t iPitch = 0; iPitch < m_nPitch; ++iPitch) + for (int iPitch = 0; iPitch < m_nPitch; ++iPitch) { m_freqs[iPitch] = m_minFreq * std::pow(2, iPitch * 1.0 / (12 * m_nBPS)); m_freqs[iPitch+m_nPitch] = -m_freqs[iPitch]; @@ -47,13 +50,13 @@ vector<double> out = vector<double>(2*m_nPitch+1); double probYinPitched = 0; // BIN THE PITCHES - for (size_t iPair = 0; iPair < pitchProb.size(); ++iPair) + for (int iPair = 0; iPair < int(pitchProb.size()); ++iPair) { double freq = 440. * std::pow(2, (pitchProb[iPair].first - 69)/12); if (freq <= m_minFreq) continue; double d = 0; double oldd = 1000; - for (size_t iPitch = 0; iPitch < m_nPitch; ++iPitch) + for (int iPitch = 0; iPitch < m_nPitch; ++iPitch) { d = std::abs(freq-m_freqs[iPitch]); if (oldd < d && iPitch > 0) @@ -70,7 +73,7 @@ double probReallyPitched = m_yinTrust * probYinPitched; // std::cerr << probReallyPitched << " " << probYinPitched << std::endl; // damn, I forget what this is all about... - for (size_t iPitch = 0; iPitch < m_nPitch; ++iPitch) + for (int iPitch = 0; iPitch < m_nPitch; ++iPitch) { if (probYinPitched > 0) out[iPitch] *= (probReallyPitched/probYinPitched) ; out[iPitch+m_nPitch] = (1 - probReallyPitched) / m_nPitch; @@ -83,19 +86,19 @@ MonoPitchHMM::build() { // INITIAL VECTOR - init = vector<double>(2*m_nPitch, 1.0 / 2*m_nPitch); + m_init = vector<double>(2*m_nPitch, 1.0 / 2*m_nPitch); // TRANSITIONS - for (size_t iPitch = 0; iPitch < m_nPitch; ++iPitch) + for (int iPitch = 0; iPitch < int(m_nPitch); ++iPitch) { - int theoreticalMinNextPitch = static_cast<int>(iPitch)-static_cast<int>(m_transitionWidth/2); + int theoreticalMinNextPitch = iPitch-m_transitionWidth/2; int minNextPitch = iPitch>m_transitionWidth/2 ? iPitch-m_transitionWidth/2 : 0; int maxNextPitch = iPitch<m_nPitch-m_transitionWidth/2 ? iPitch+m_transitionWidth/2 : m_nPitch-1; // WEIGHT VECTOR double weightSum = 0; vector<double> weights; - for (size_t i = minNextPitch; i <= maxNextPitch; ++i) + for (int i = minNextPitch; i <= maxNextPitch; ++i) { if (i <= iPitch) { @@ -110,24 +113,24 @@ // std::cerr << minNextPitch << " " << maxNextPitch << std::endl; // TRANSITIONS TO CLOSE PITCH - for (size_t i = minNextPitch; i <= maxNextPitch; ++i) + for (int i = minNextPitch; i <= maxNextPitch; ++i) { - from.push_back(iPitch); - to.push_back(i); - transProb.push_back(weights[i-minNextPitch] / weightSum * m_selfTrans); + m_from.push_back(iPitch); + m_to.push_back(i); + m_transProb.push_back(weights[i-minNextPitch] / weightSum * m_selfTrans); - from.push_back(iPitch); - to.push_back(i+m_nPitch); - transProb.push_back(weights[i-minNextPitch] / weightSum * (1-m_selfTrans)); + m_from.push_back(iPitch); + m_to.push_back(i+m_nPitch); + m_transProb.push_back(weights[i-minNextPitch] / weightSum * (1-m_selfTrans)); - from.push_back(iPitch+m_nPitch); - to.push_back(i+m_nPitch); - transProb.push_back(weights[i-minNextPitch] / weightSum * m_selfTrans); + m_from.push_back(iPitch+m_nPitch); + m_to.push_back(i+m_nPitch); + m_transProb.push_back(weights[i-minNextPitch] / weightSum * m_selfTrans); // transProb.push_back(weights[i-minNextPitch] / weightSum * 0.5); - from.push_back(iPitch+m_nPitch); - to.push_back(i); - transProb.push_back(weights[i-minNextPitch] / weightSum * (1-m_selfTrans)); + m_from.push_back(iPitch+m_nPitch); + m_to.push_back(i); + m_transProb.push_back(weights[i-minNextPitch] / weightSum * (1-m_selfTrans)); // transProb.push_back(weights[i-minNextPitch] / weightSum * 0.5); } @@ -146,8 +149,48 @@ // to.push_back(2*m_nPitch); // transProb.push_back(m_selfTrans); - // for (size_t i = 0; i < from.size(); ++i) { + // for (int i = 0; i < from.size(); ++i) { // std::cerr << "P(["<< from[i] << " --> " << to[i] << "]) = " << transProb[i] << std::endl; // } - + m_nTrans = m_transProb.size(); + m_delta = vector<double>(m_nState); + m_oldDelta = vector<double>(m_nState); } + +/* +Takes a state number and a pitch-prob vector, then finds the pitch that would +have been closest to the pitch of the state. Easy to understand? ;) +*/ +const float +MonoPitchHMM::nearestFreq(int state, vector<pair<double, double> > pitchProb) +{ + float hmmFreq = m_freqs[state]; + // std::cerr << "hmmFreq " << hmmFreq << std::endl; + float bestFreq = 0; + float leastDist = 10000; + if (hmmFreq > 0) + { + // This was a Yin estimate, so try to get original pitch estimate back + // ... a bit hacky, since we could have direclty saved the frequency + // that was assigned to the HMM bin in hmm.calculateObsProb -- but would + // have had to rethink the interface of that method. + + // std::cerr << "pitch prob size " << pitchProb.size() << std::endl; + + for (size_t iPt = 0; iPt < pitchProb.size(); ++iPt) + { + float freq = 440. * + std::pow(2, + (pitchProb[iPt].first - 69)/12); + float dist = std::abs(hmmFreq-freq); + if (dist < leastDist) + { + leastDist = dist; + bestFreq = freq; + } + } + } else { + bestFreq = hmmFreq; + } + return bestFreq; +}
--- a/MonoPitchHMM.h Thu Aug 20 16:06:01 2015 +0100 +++ b/MonoPitchHMM.h Fri Mar 24 15:08:12 2017 +0000 @@ -26,15 +26,14 @@ class MonoPitchHMM : public SparseHMM { public: - MonoPitchHMM(); + MonoPitchHMM(int fixedLag); const std::vector<double> calculateObsProb(const vector<pair<double, double> >); - // double getMidiPitch(size_t index); - // double getFrequency(size_t index); + const float nearestFreq(int state, vector<pair<double, double> > pitchProb); void build(); double m_minFreq; // 82.40689f/2 - size_t m_nBPS; - size_t m_nPitch; - size_t m_transitionWidth; + int m_nBPS; + int m_nPitch; + int m_transitionWidth; double m_selfTrans; double m_yinTrust; vector<double> m_freqs;
--- a/PYinVamp.cpp Thu Aug 20 16:06:01 2015 +0100 +++ b/PYinVamp.cpp Fri Mar 24 15:08:12 2017 +0000 @@ -13,9 +13,7 @@ #include "PYinVamp.h" #include "MonoNote.h" -#include "MonoPitch.h" - -#include "vamp-sdk/FFT.h" +#include "MonoPitchHMM.h" #include <vector> #include <algorithm> @@ -44,14 +42,17 @@ m_oSmoothedPitchTrack(0), m_oNotes(0), m_threshDistr(2.0f), + m_fixedLag(1.0f), m_outputUnvoiced(0.0f), m_preciseTime(0.0f), m_lowAmp(0.1f), m_onsetSensitivity(0.7f), m_pruneThresh(0.1f), + m_pitchHmm(0), m_pitchProb(0), m_timestamp(0), - m_level(0) + m_level(0), + m_pitchTrack(0) { } @@ -88,7 +89,7 @@ { // Increment this each time you release a version that behaves // differently from the previous one - return 2; + return 3; } string @@ -153,6 +154,19 @@ d.valueNames.push_back("Single Value 0.20"); list.push_back(d); + d.valueNames.clear(); + + d.identifier = "fixedlag"; + d.name = "Fixed-lag smoothing"; + d.description = "Use fixed lag smoothing, not full Viterbi smoothing."; + d.unit = ""; + d.minValue = 0.0f; + d.maxValue = 1.0f; + d.defaultValue = 0.0f; + d.isQuantized = true; + d.quantizeStep = 1.0f; + list.push_back(d); + d.identifier = "outputunvoiced"; d.valueNames.clear(); d.name = "Output estimates classified as unvoiced?"; @@ -222,6 +236,9 @@ if (identifier == "threshdistr") { return m_threshDistr; } + if (identifier == "fixedlag") { + return m_fixedLag; + } if (identifier == "outputunvoiced") { return m_outputUnvoiced; } @@ -247,6 +264,10 @@ { m_threshDistr = value; } + if (identifier == "fixedlag") + { + m_fixedLag = value; + } if (identifier == "outputunvoiced") { m_outputUnvoiced = value; @@ -283,7 +304,7 @@ } void -PYinVamp::selectProgram(string name) +PYinVamp::selectProgram(string) { } @@ -419,10 +440,14 @@ m_yin.setThresholdDistr(m_threshDistr); m_yin.setFrameSize(m_blockSize); m_yin.setFast(!m_preciseTime); + + if (m_fixedLag == 1.f) m_pitchHmm = MonoPitchHMM(100); + else m_pitchHmm = MonoPitchHMM(0); m_pitchProb.clear(); m_timestamp.clear(); m_level.clear(); + m_pitchTrack.clear(); /* std::cerr << "PYinVamp::reset" << ", blockSize = " << m_blockSize @@ -433,8 +458,10 @@ PYinVamp::FeatureSet PYinVamp::process(const float *const *inputBuffers, RealTime timestamp) { + std::cerr << timestamp << std::endl; int offset = m_preciseTime == 1.0 ? m_blockSize/2 : m_blockSize/4; - timestamp = timestamp + Vamp::RealTime::frame2RealTime(offset, lrintf(m_inputSampleRate)); + timestamp = timestamp + Vamp::RealTime::frame2RealTime(offset, + lrintf(m_inputSampleRate)); FeatureSet fs; @@ -455,8 +482,6 @@ m_level.push_back(yo.rms); - // First, get the things out of the way that we don't want to output - // immediately, but instead save for later. vector<pair<double, double> > tempPitchProb; for (size_t iCandidate = 0; iCandidate < yo.freqProb.size(); ++iCandidate) { @@ -471,9 +496,53 @@ (tempPitch, yo.freqProb[iCandidate].second*factor)); } } + + vector<double> tempObsProb = m_pitchHmm.calculateObsProb(tempPitchProb); + if (m_timestamp.empty()) + { + m_pitchHmm.initialise(tempObsProb); + } else { + m_pitchHmm.process(tempObsProb); + } + m_pitchProb.push_back(tempPitchProb); m_timestamp.push_back(timestamp); + int lag = m_pitchHmm.m_fixedLag; + + if (m_fixedLag == 1.f) // do fixed-lag smoothing instead of full Viterbi + { + if (int(m_timestamp.size()) == lag + 1) + { + m_timestamp.pop_front(); + m_pitchProb.pop_front(); + + Feature f; + f.hasTimestamp = true; + vector<int> rawPitchPath = m_pitchHmm.track(); + float freq = m_pitchHmm.nearestFreq(rawPitchPath[0], + m_pitchProb[0]); + m_pitchTrack.push_back(freq); + f.timestamp = m_timestamp[0]; + f.values.clear(); + + // different output modes + if (freq < 0 && (m_outputUnvoiced==0)) + { + + } else { + if (m_outputUnvoiced == 1) + { + f.values.push_back(fabs(freq)); + } else { + f.values.push_back(freq); + } + fs[m_oSmoothedPitchTrack].push_back(f); + } + } + } + + // F0 CANDIDATES Feature f; f.hasTimestamp = true; @@ -523,39 +592,49 @@ return fs; } - // MONO-PITCH STUFF - MonoPitch mp; - vector<float> mpOut = mp.process(m_pitchProb); - for (size_t iFrame = 0; iFrame < mpOut.size(); ++iFrame) + // ================== P I T C H T R A C K ================================= + + vector<int> rawPitchPath = m_pitchHmm.track(); + + for (size_t iFrame = 0; iFrame < rawPitchPath.size(); ++iFrame) { - if (mpOut[iFrame] < 0 && (m_outputUnvoiced==0)) continue; + float freq = m_pitchHmm.nearestFreq(rawPitchPath[iFrame], + m_pitchProb[iFrame]); + m_pitchTrack.push_back(freq); // for note processing below + f.timestamp = m_timestamp[iFrame]; f.values.clear(); + + // different output modes + if (freq < 0 && (m_outputUnvoiced==0)) continue; if (m_outputUnvoiced == 1) { - f.values.push_back(fabs(mpOut[iFrame])); + f.values.push_back(fabs(freq)); } else { - f.values.push_back(mpOut[iFrame]); + f.values.push_back(freq); } - fs[m_oSmoothedPitchTrack].push_back(f); } - // MONO-NOTE STUFF -// std::cerr << "Mono Note Stuff" << std::endl; + // ======================== N O T E S ====================================== MonoNote mn; std::vector<std::vector<std::pair<double, double> > > smoothedPitch; - for (size_t iFrame = 0; iFrame < mpOut.size(); ++iFrame) { + for (size_t iFrame = 0; iFrame < m_pitchTrack.size(); ++iFrame) { std::vector<std::pair<double, double> > temp; - if (mpOut[iFrame] > 0) + if (m_pitchTrack[iFrame] > 0) { - double tempPitch = 12 * std::log(mpOut[iFrame]/440)/std::log(2.) + 69; + double tempPitch = 12 * + std::log(m_pitchTrack[iFrame]/440)/std::log(2.) + 69; temp.push_back(std::pair<double,double>(tempPitch, .9)); + // std::cerr << "tempPitch: " << tempPitch << std::endl; } + // std::cerr << "temp size: " << temp.size() << std::endl; smoothedPitch.push_back(temp); } - // vector<MonoNote::FrameOutput> mnOut = mn.process(m_pitchProb); + vector<MonoNote::FrameOutput> mnOut = mn.process(smoothedPitch); + std::cerr << "mnOut size: " << mnOut.size() << std::endl; + std::cerr << "m_pitchTrack size: " << m_pitchTrack.size() << std::endl; // turning feature into a note feature f.hasTimestamp = true; @@ -565,18 +644,30 @@ int onsetFrame = 0; bool isVoiced = 0; bool oldIsVoiced = 0; - size_t nFrame = m_pitchProb.size(); + size_t nFrame = m_pitchTrack.size(); float minNoteFrames = (m_inputSampleRate*m_pruneThresh) / m_stepSize; - std::vector<float> notePitchTrack; // collects pitches for one note at a time + // the body of the loop below should be in a function/method + // but what does it actually do?? + // * takes the result of the note tracking HMM + // * collects contiguously pitched pitches + // * writes a note once it notices the voiced segment has ended + // complications: + // * it needs a lookahead of two frames for m_level (wtf was I thinking) + // * it needs to know the timestamp (which can be guessed from the frame no) + // * + int offset = m_preciseTime == 1.0 ? m_blockSize/2 : m_blockSize/4; + RealTime timestampOffset = Vamp::RealTime::frame2RealTime(offset, + lrintf(m_inputSampleRate)); + + std::vector<float> notePitchTrack; // collects pitches for 1 note at a time for (size_t iFrame = 0; iFrame < nFrame; ++iFrame) { - isVoiced = mnOut[iFrame].noteState < 3 - && smoothedPitch[iFrame].size() > 0 - && (iFrame >= nFrame-2 - || ((m_level[iFrame]/m_level[iFrame+2]) > m_onsetSensitivity)); - // std::cerr << m_level[iFrame]/m_level[iFrame-1] << " " << isVoiced << std::endl; + isVoiced = mnOut[iFrame].noteState < 3 + && smoothedPitch[iFrame].size() > 0 + && (iFrame >= nFrame-2 + || ((m_level[iFrame]/m_level[iFrame+2]) > m_onsetSensitivity)); if (isVoiced && iFrame != nFrame-1) { if (oldIsVoiced == 0) // beginning of a note @@ -588,16 +679,22 @@ } else { // not currently voiced if (oldIsVoiced == 1) // end of note { - // std::cerr << notePitchTrack.size() << " " << minNoteFrames << std::endl; if (notePitchTrack.size() >= minNoteFrames) { std::sort(notePitchTrack.begin(), notePitchTrack.end()); float medianPitch = notePitchTrack[notePitchTrack.size()/2]; - float medianFreq = std::pow(2,(medianPitch - 69) / 12) * 440; + float medianFreq = + std::pow(2,(medianPitch - 69) / 12) * 440; f.values.clear(); f.values.push_back(medianFreq); - f.timestamp = m_timestamp[onsetFrame]; - f.duration = m_timestamp[iFrame] - m_timestamp[onsetFrame]; + RealTime start = RealTime::frame2RealTime( + onsetFrame * m_stepSize, lrintf(m_inputSampleRate)) + + timestampOffset; + RealTime end = RealTime::frame2RealTime( + iFrame * m_stepSize, lrintf(m_inputSampleRate)) + + timestampOffset; + f.timestamp = start; + f.duration = end - start; fs[m_oNotes].push_back(f); } notePitchTrack.clear();
--- a/PYinVamp.h Thu Aug 20 16:06:01 2015 +0100 +++ b/PYinVamp.h Fri Mar 24 15:08:12 2017 +0000 @@ -17,6 +17,7 @@ #include <vamp-sdk/Plugin.h> #include "Yin.h" +#include "MonoPitchHMM.h" class PYinVamp : public Vamp::Plugin { @@ -71,14 +72,23 @@ mutable int m_oNotes; float m_threshDistr; + float m_fixedLag; float m_outputUnvoiced; float m_preciseTime; float m_lowAmp; float m_onsetSensitivity; float m_pruneThresh; - vector<vector<pair<double, double> > > m_pitchProb; - vector<Vamp::RealTime> m_timestamp; + + MonoPitchHMM m_pitchHmm; + + deque<vector<pair<double, double> > > m_pitchProb; + deque<Vamp::RealTime> m_timestamp; vector<float> m_level; + vector<float> m_pitchTrack; + + // for note writing + // vector<float> m_notePitchTrack; // contains pitches of one current note + // bool m_oldIsVoiced; }; #endif
--- a/SparseHMM.cpp Thu Aug 20 16:06:01 2015 +0100 +++ b/SparseHMM.cpp Fri Mar 24 15:08:12 2017 +0000 @@ -19,110 +19,167 @@ using std::vector; using std::pair; +SparseHMM::SparseHMM(int fixedLag) : + m_fixedLag(fixedLag), + m_nState(0), + m_nTrans(0), + m_init(0), + m_from(0), + m_to(0), + m_transProb(0), + m_scale(0), + m_psi(0), + m_delta(0), + m_oldDelta(0) +{ + +} + const vector<double> -SparseHMM::calculateObsProb(const vector<pair<double, double> > data) +SparseHMM::calculateObsProb(const vector<pair<double, double> > ) { // dummy (virtual?) implementation to be overloaded return(vector<double>()); } +void +SparseHMM::build() +{ } + const std::vector<int> -SparseHMM::decodeViterbi(std::vector<vector<double> > obsProb, - vector<double> *scale) +SparseHMM::decodeViterbi(std::vector<vector<double> > obsProb) { - if (obsProb.size() < 1) { + int nFrame = obsProb.size(); + if (nFrame < 1) { return vector<int>(); } - size_t nState = init.size(); - size_t nFrame = obsProb.size(); - - // check for consistency - size_t nTrans = transProb.size(); - - // declaring variables - std::vector<double> delta = std::vector<double>(nState); - std::vector<double> oldDelta = std::vector<double>(nState); - vector<vector<int> > psi; // "matrix" of remembered indices of the best transitions - vector<int> path = vector<int>(nFrame, nState-1); // the final output path (current assignment arbitrary, makes sense only for Chordino, where nChord-1 is the "no chord" label) + initialise(obsProb[0]); + + // rest of forward step + for (int iFrame = 1; iFrame < nFrame; ++iFrame) + { + process(obsProb[iFrame]); + } + + vector<int> path = track(); + return(path); +} + +void +SparseHMM::reset() +{ + m_scale.clear(); + m_psi.clear(); + for (int i = 0; i < int(m_delta.size()); ++i) m_delta[i] = 0; + for (int i = 0; i < int(m_oldDelta.size()); ++i) m_oldDelta[i] = 0; +} + +void +SparseHMM::initialise(vector<double> firstObs) +{ + reset(); double deltasum = 0; // initialise first frame - for (size_t iState = 0; iState < nState; ++iState) + for (int iState = 0; iState < m_nState; ++iState) { - oldDelta[iState] = init[iState] * obsProb[0][iState]; - // std::cerr << iState << " ----- " << init[iState] << std::endl; - deltasum += oldDelta[iState]; + m_oldDelta[iState] = m_init[iState] * firstObs[iState]; + deltasum += m_oldDelta[iState]; } - for (size_t iState = 0; iState < nState; ++iState) + for (int iState = 0; iState < m_nState; ++iState) { - oldDelta[iState] /= deltasum; // normalise (scale) - // std::cerr << oldDelta[iState] << std::endl; + m_oldDelta[iState] /= deltasum; // normalise (scale) } - scale->push_back(1.0/deltasum); - psi.push_back(vector<int>(nState,0)); + m_scale.push_back(1.0/deltasum); + m_psi.push_back(vector<int>(m_nState,0)); +} - // rest of forward step - for (size_t iFrame = 1; iFrame < nFrame; ++iFrame) +int +SparseHMM::process(vector<double> newObs) +{ + vector<int> tempPsi = vector<int>(m_nState,0); + + // calculate best previous state for every current state + int fromState; + int toState; + double currentTransProb; + double currentValue; + + // this is the "sparse" loop + for (int iTrans = 0; iTrans < m_nTrans; ++iTrans) { - deltasum = 0; - psi.push_back(vector<int>(nState,0)); - - // calculate best previous state for every current state - size_t fromState; - size_t toState; - double currentTransProb; - double currentValue; + fromState = m_from[iTrans]; + toState = m_to[iTrans]; + currentTransProb = m_transProb[iTrans]; - // this is the "sparse" loop - for (size_t iTrans = 0; iTrans < nTrans; ++iTrans) + currentValue = m_oldDelta[fromState] * currentTransProb; + if (currentValue > m_delta[toState]) { - fromState = from[iTrans]; - toState = to[iTrans]; - currentTransProb = transProb[iTrans]; - - currentValue = oldDelta[fromState] * currentTransProb; - if (currentValue > delta[toState]) - { - delta[toState] = currentValue; // will be multiplied by the right obs later! - psi[iFrame][toState] = fromState; - } - } - - for (size_t jState = 0; jState < nState; ++jState) - { - delta[jState] *= obsProb[iFrame][jState]; - deltasum += delta[jState]; - } - - if (deltasum > 0) - { - for (size_t iState = 0; iState < nState; ++iState) - { - oldDelta[iState] = delta[iState] / deltasum; // normalise (scale) - delta[iState] = 0; - } - scale->push_back(1.0/deltasum); - } else - { - std::cerr << "WARNING: Viterbi has been fed some zero probabilities, at least they become zero at frame " << iFrame << " in combination with the model." << std::endl; - for (size_t iState = 0; iState < nState; ++iState) - { - oldDelta[iState] = 1.0/nState; - delta[iState] = 0; - } - scale->push_back(1.0); + // will be multiplied by the right obs later! + m_delta[toState] = currentValue; + tempPsi[toState] = fromState; } } + m_psi.push_back(tempPsi); + + double deltasum = 0; + for (int jState = 0; jState < m_nState; ++jState) + { + m_delta[jState] *= newObs[jState]; + deltasum += m_delta[jState]; + } + + if (deltasum > 0) + { + for (int iState = 0; iState < m_nState; ++iState) + { + m_oldDelta[iState] = m_delta[iState] / deltasum;// normalise (scale) + m_delta[iState] = 0; + } + m_scale.push_back(1.0/deltasum); + } else + { + std::cerr << "WARNING: Viterbi has been fed some zero " + "probabilities, at least they become zero " + "in combination with the model." << std::endl; + for (int iState = 0; iState < m_nState; ++iState) + { + m_oldDelta[iState] = 1.0/m_nState; + m_delta[iState] = 0; + } + m_scale.push_back(1.0); + } + + if (m_fixedLag > 0 && int(m_psi.size()) > m_fixedLag) + { + m_psi.pop_front(); + m_scale.pop_front(); + } + + // std::cerr << m_fixedLag << " " << m_psi.size() << std::endl; + + return 0; +} + +const vector<int> +SparseHMM::track() +{ // initialise backward step + int nFrame = m_psi.size(); + + // The final output path (current assignment arbitrary, makes sense only for + // Chordino, where nChord-1 is the "no chord" label) + vector<int> path = vector<int>(nFrame, m_nState-1); + double bestValue = 0; - for (size_t iState = 0; iState < nState; ++iState) + for (int iState = 0; iState < m_nState; ++iState) { - double currentValue = oldDelta[iState]; + double currentValue = m_oldDelta[iState]; if (currentValue > bestValue) { bestValue = currentValue; @@ -130,16 +187,11 @@ } } - // rest of backward step + // Rest of backward step for (int iFrame = nFrame-2; iFrame != -1; --iFrame) { - path[iFrame] = psi[iFrame+1][path[iFrame+1]]; + path[iFrame] = m_psi[iFrame+1][path[iFrame+1]]; } - - // for (size_t iState = 0; iState < nState; ++iState) - // { - // // std::cerr << psi[2][iState] << std::endl; - // } - + return path; }
--- a/SparseHMM.h Thu Aug 20 16:06:01 2015 +0100 +++ b/SparseHMM.h Fri Mar 24 15:08:12 2017 +0000 @@ -15,21 +15,39 @@ #define _SPARSEHMM_H_ #include <vector> +#include <queue> #include <cstdio> using std::vector; +using std::deque; using std::pair; class SparseHMM { public: - virtual const std::vector<double> calculateObsProb(const vector<pair<double, double> >); - const std::vector<int> decodeViterbi(std::vector<vector<double> > obs, - vector<double> *scale); - vector<double> init; - vector<size_t> from; - vector<size_t> to; - vector<double> transProb; + SparseHMM(int fixedLag); + virtual const std::vector<double> + calculateObsProb(const vector<pair<double, double> >); + virtual void build(); + const std::vector<int> decodeViterbi(std::vector<vector<double> > obs); + void reset(); + void initialise(vector<double> firstObs); + int process(vector<double> newObs); + const vector<int> track(); + // "sparse" HMM definition + int m_fixedLag; + int m_nState; + int m_nTrans; + vector<double> m_init; + vector<size_t> m_from; + vector<size_t> m_to; + vector<double> m_transProb; + + // variables for decoding + deque<double> m_scale; + deque<vector<int> > m_psi; + vector<double> m_delta; + vector<double> m_oldDelta; }; #endif
--- a/Yin.cpp Thu Aug 20 16:06:01 2015 +0100 +++ b/Yin.cpp Fri Mar 24 15:08:12 2017 +0000 @@ -31,7 +31,8 @@ m_thresh(thresh), m_threshDistr(2), m_yinBufferSize(frameSize/2), - m_fast(fast) + m_fast(fast), + m_yinUtil(new YinUtil(m_yinBufferSize)) { if (frameSize & (frameSize-1)) { // throw "N must be a power of two"; @@ -40,6 +41,7 @@ Yin::~Yin() { + delete m_yinUtil; } Yin::YinOutput @@ -48,13 +50,13 @@ double* yinBuffer = new double[m_yinBufferSize]; // calculate aperiodicity function for all periods - if (m_fast) YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize); - else YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize); + if (m_fast) m_yinUtil->fastDifference(in, yinBuffer); + else m_yinUtil->slowDifference(in, yinBuffer); - YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize); + m_yinUtil->cumulativeDifference(yinBuffer); int tau = 0; - tau = YinUtil::absoluteThreshold(yinBuffer, m_yinBufferSize, m_thresh); + tau = m_yinUtil->absoluteThreshold(yinBuffer, m_thresh); double interpolatedTau; double aperiodicity; @@ -62,13 +64,13 @@ if (tau!=0) { - interpolatedTau = YinUtil::parabolicInterpolation(yinBuffer, abs(tau), m_yinBufferSize); + interpolatedTau = m_yinUtil->parabolicInterpolation(yinBuffer, abs(tau)); f0 = m_inputSampleRate * (1.0 / interpolatedTau); } else { interpolatedTau = 0; f0 = 0; } - double rms = std::sqrt(YinUtil::sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize); + double rms = std::sqrt(m_yinUtil->sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize); aperiodicity = yinBuffer[abs(tau)]; // std::cerr << aperiodicity << std::endl; if (tau < 0) f0 = -f0; @@ -89,12 +91,12 @@ double* yinBuffer = new double[m_yinBufferSize]; // calculate aperiodicity function for all periods - if (m_fast) YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize); - else YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize); + if (m_fast) m_yinUtil->fastDifference(in, yinBuffer); + else m_yinUtil->slowDifference(in, yinBuffer); - YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize); + m_yinUtil->cumulativeDifference(yinBuffer); - vector<double> peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize); + vector<double> peakProbability = m_yinUtil->yinProb(yinBuffer, m_threshDistr); // calculate overall "probability" from peak probability double probSum = 0; @@ -102,7 +104,7 @@ { probSum += peakProbability[iBin]; } - double rms = std::sqrt(YinUtil::sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize); + double rms = std::sqrt(m_yinUtil->sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize); Yin::YinOutput yo(0,0,rms); for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf) { @@ -111,7 +113,7 @@ { double currentF0 = m_inputSampleRate * (1.0 / - YinUtil::parabolicInterpolation(yinBuffer, iBuf, m_yinBufferSize)); + m_yinUtil->parabolicInterpolation(yinBuffer, iBuf)); yo.freqProb.push_back(pair<double, double>(currentF0, peakProbability[iBuf])); } }
--- a/Yin.h Thu Aug 20 16:06:01 2015 +0100 +++ b/Yin.h Fri Mar 24 15:08:12 2017 +0000 @@ -26,7 +26,7 @@ using std::vector; using std::pair; - +class YinUtil; class Yin { @@ -66,6 +66,7 @@ mutable size_t m_yinBufferSize; mutable bool m_fast; // mutable bool m_removeUnvoiced; + YinUtil *m_yinUtil; }; #endif
--- a/YinUtil.cpp Thu Aug 20 16:06:01 2015 +0100 +++ b/YinUtil.cpp Fri Mar 24 15:08:12 2017 +0000 @@ -21,17 +21,27 @@ #include <boost/math/distributions.hpp> +YinUtil::YinUtil(int yinBufferSize) : + m_yinBufferSize(yinBufferSize), + m_fft(yinBufferSize * 2) +{ +} + +YinUtil::~YinUtil() +{ +} + void -YinUtil::slowDifference(const double *in, double *yinBuffer, const size_t yinBufferSize) +YinUtil::slowDifference(const double *in, double *yinBuffer) { yinBuffer[0] = 0; double delta ; int startPoint = 0; int endPoint = 0; - for (int i = 1; i < yinBufferSize; ++i) { + for (int i = 1; i < int(m_yinBufferSize); ++i) { yinBuffer[i] = 0; - startPoint = yinBufferSize/2 - i/2; - endPoint = startPoint + yinBufferSize; + startPoint = m_yinBufferSize/2 - i/2; + endPoint = startPoint + m_yinBufferSize; for (int j = startPoint; j < endPoint; ++j) { delta = in[i+j] - in[j]; yinBuffer[i] += delta * delta; @@ -40,99 +50,86 @@ } void -YinUtil::fastDifference(const double *in, double *yinBuffer, const size_t yinBufferSize) +YinUtil::fastDifference(const double *in, double *yinBuffer) { - // DECLARE AND INITIALISE // initialisation of most of the arrays here was done in a separate function, // with all the arrays as members of the class... moved them back here. - size_t frameSize = 2 * yinBufferSize; - - double *audioTransformedReal = new double[frameSize]; - double *audioTransformedImag = new double[frameSize]; - double *nullImag = new double[frameSize]; + int frameSize = 2 * m_yinBufferSize; + int halfSize = m_yinBufferSize; + + double *audioTransformedComplex = new double[frameSize + 2]; + double *audioOutReal = new double[frameSize]; double *kernel = new double[frameSize]; - double *kernelTransformedReal = new double[frameSize]; - double *kernelTransformedImag = new double[frameSize]; - double *yinStyleACFReal = new double[frameSize]; - double *yinStyleACFImag = new double[frameSize]; - double *powerTerms = new double[yinBufferSize]; - - for (size_t j = 0; j < yinBufferSize; ++j) - { - yinBuffer[j] = 0.; // set to zero - powerTerms[j] = 0.; // set to zero - } - - for (size_t j = 0; j < frameSize; ++j) - { - nullImag[j] = 0.; - audioTransformedReal[j] = 0.; - audioTransformedImag[j] = 0.; - kernel[j] = 0.; - kernelTransformedReal[j] = 0.; - kernelTransformedImag[j] = 0.; - yinStyleACFReal[j] = 0.; - yinStyleACFImag[j] = 0.; - } + double *kernelTransformedComplex = new double[frameSize + 2]; + double *yinStyleACFComplex = new double[frameSize + 2]; + double *powerTerms = new double[m_yinBufferSize]; // POWER TERM CALCULATION // ... for the power terms in equation (7) in the Yin paper powerTerms[0] = 0.0; - for (size_t j = 0; j < yinBufferSize; ++j) { + for (int j = 0; j < m_yinBufferSize; ++j) { powerTerms[0] += in[j] * in[j]; } // now iteratively calculate all others (saves a few multiplications) - for (size_t tau = 1; tau < yinBufferSize; ++tau) { - powerTerms[tau] = powerTerms[tau-1] - in[tau-1] * in[tau-1] + in[tau+yinBufferSize] * in[tau+yinBufferSize]; + for (int tau = 1; tau < m_yinBufferSize; ++tau) { + powerTerms[tau] = powerTerms[tau-1] - + in[tau-1] * in[tau-1] + + in[tau+m_yinBufferSize] * in[tau+m_yinBufferSize]; } // YIN-STYLE AUTOCORRELATION via FFT // 1. data - Vamp::FFT::forward(frameSize, in, nullImag, audioTransformedReal, audioTransformedImag); + m_fft.forward(in, audioTransformedComplex); // 2. half of the data, disguised as a convolution kernel - for (size_t j = 0; j < yinBufferSize; ++j) { - kernel[j] = in[yinBufferSize-1-j]; + for (int j = 0; j < m_yinBufferSize; ++j) { + kernel[j] = in[m_yinBufferSize-1-j]; } - Vamp::FFT::forward(frameSize, kernel, nullImag, kernelTransformedReal, kernelTransformedImag); + for (int j = m_yinBufferSize; j < frameSize; ++j) { + kernel[j] = 0.; + } + m_fft.forward(kernel, kernelTransformedComplex); // 3. convolution via complex multiplication -- written into - for (size_t j = 0; j < frameSize; ++j) { - yinStyleACFReal[j] = audioTransformedReal[j]*kernelTransformedReal[j] - audioTransformedImag[j]*kernelTransformedImag[j]; // real - yinStyleACFImag[j] = audioTransformedReal[j]*kernelTransformedImag[j] + audioTransformedImag[j]*kernelTransformedReal[j]; // imaginary + for (int j = 0; j <= halfSize; ++j) { + yinStyleACFComplex[j*2] = // real + audioTransformedComplex[j*2] * kernelTransformedComplex[j*2] - + audioTransformedComplex[j*2+1] * kernelTransformedComplex[j*2+1]; + yinStyleACFComplex[j*2+1] = // imaginary + audioTransformedComplex[j*2] * kernelTransformedComplex[j*2+1] + + audioTransformedComplex[j*2+1] * kernelTransformedComplex[j*2]; } - Vamp::FFT::inverse(frameSize, yinStyleACFReal, yinStyleACFImag, audioTransformedReal, audioTransformedImag); + + m_fft.inverse(yinStyleACFComplex, audioOutReal); // CALCULATION OF difference function // ... according to (7) in the Yin paper. - for (size_t j = 0; j < yinBufferSize; ++j) { - // taking only the real part - yinBuffer[j] = powerTerms[0] + powerTerms[j] - 2 * audioTransformedReal[j+yinBufferSize-1]; + for (int j = 0; j < m_yinBufferSize; ++j) { + yinBuffer[j] = powerTerms[0] + powerTerms[j] - 2 * + audioOutReal[j+m_yinBufferSize-1]; } - delete [] audioTransformedReal; - delete [] audioTransformedImag; - delete [] nullImag; + delete [] audioTransformedComplex; + delete [] audioOutReal; delete [] kernel; - delete [] kernelTransformedReal; - delete [] kernelTransformedImag; - delete [] yinStyleACFReal; - delete [] yinStyleACFImag; + delete [] kernelTransformedComplex; + delete [] yinStyleACFComplex; delete [] powerTerms; } + void -YinUtil::cumulativeDifference(double *yinBuffer, const size_t yinBufferSize) +YinUtil::cumulativeDifference(double *yinBuffer) { - size_t tau; + int tau; yinBuffer[0] = 1; double runningSum = 0; - for (tau = 1; tau < yinBufferSize; ++tau) { + for (tau = 1; tau < m_yinBufferSize; ++tau) { runningSum += yinBuffer[tau]; if (runningSum == 0) { @@ -144,19 +141,19 @@ } int -YinUtil::absoluteThreshold(const double *yinBuffer, const size_t yinBufferSize, const double thresh) +YinUtil::absoluteThreshold(const double *yinBuffer, double thresh) { - size_t tau; - size_t minTau = 0; + int tau; + int minTau = 0; double minVal = 1000.; // using Joren Six's "loop construct" from TarsosDSP tau = 2; - while (tau < yinBufferSize) + while (tau < m_yinBufferSize) { if (yinBuffer[tau] < thresh) { - while (tau+1 < yinBufferSize && yinBuffer[tau+1] < yinBuffer[tau]) + while (tau+1 < m_yinBufferSize && yinBuffer[tau+1] < yinBuffer[tau]) { ++tau; } @@ -187,22 +184,22 @@ static float single20[100] = {0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,1.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000}; std::vector<double> -YinUtil::yinProb(const double *yinBuffer, const size_t prior, const size_t yinBufferSize, const size_t minTau0, const size_t maxTau0) +YinUtil::yinProb(const double *yinBuffer, int prior, int minTau0, int maxTau0) { - size_t minTau = 2; - size_t maxTau = yinBufferSize; + int minTau = 2; + int maxTau = m_yinBufferSize; // adapt period range, if necessary if (minTau0 > 0 && minTau0 < maxTau0) minTau = minTau0; - if (maxTau0 > 0 && maxTau0 < yinBufferSize && maxTau0 > minTau) maxTau = maxTau0; + if (maxTau0 > 0 && maxTau0 < m_yinBufferSize && maxTau0 > minTau) maxTau = maxTau0; double minWeight = 0.01; - size_t tau; + int tau; std::vector<float> thresholds; std::vector<float> distribution; - std::vector<double> peakProb = std::vector<double>(yinBufferSize); + std::vector<double> peakProb = std::vector<double>(m_yinBufferSize); - size_t nThreshold = 100; + int nThreshold = 100; int nThresholdInt = nThreshold; for (int i = 0; i < nThresholdInt; ++i) @@ -243,7 +240,7 @@ tau = minTau; // double factor = 1.0 / (0.25 * (nThresholdInt+1) * (nThresholdInt + 1)); // factor to scale down triangular weight - size_t minInd = 0; + int minInd = 0; float minVal = 42.f; // while (currThreshInd != -1 && tau < maxTau) // { @@ -266,7 +263,7 @@ // } // } // double nonPeakProb = 1; - // for (size_t i = minTau; i < maxTau; ++i) + // for (int i = minTau; i < maxTau; ++i) // { // nonPeakProb -= peakProb[i]; // } @@ -288,7 +285,7 @@ minInd = tau; } currThreshInd = nThresholdInt-1; - while (thresholds[currThreshInd] > yinBuffer[tau] && currThreshInd > -1) { + while (currThreshInd > -1 && thresholds[currThreshInd] > yinBuffer[tau]) { // std::cerr << distribution[currThreshInd] << std::endl; peakProb[tau] += distribution[currThreshInd]; currThreshInd--; @@ -303,12 +300,12 @@ if (peakProb[minInd] > 1) { std::cerr << "WARNING: yin has prob > 1 ??? I'm returning all zeros instead." << std::endl; - return(std::vector<double>(yinBufferSize)); + return(std::vector<double>(m_yinBufferSize)); } double nonPeakProb = 1; if (sumProb > 0) { - for (size_t i = minTau; i < maxTau; ++i) + for (int i = minTau; i < maxTau; ++i) { peakProb[i] = peakProb[i] / sumProb * peakProb[minInd]; nonPeakProb -= peakProb[i]; @@ -324,16 +321,16 @@ } double -YinUtil::parabolicInterpolation(const double *yinBuffer, const size_t tau, const size_t yinBufferSize) +YinUtil::parabolicInterpolation(const double *yinBuffer, int tau) { // this is taken almost literally from Joren Six's Java implementation - if (tau == yinBufferSize) // not valid anyway. + if (tau == m_yinBufferSize) // not valid anyway. { return static_cast<double>(tau); } double betterTau = 0.0; - if (tau > 0 && tau < yinBufferSize-1) { + if (tau > 0 && tau < m_yinBufferSize-1) { float s0, s1, s2; s0 = yinBuffer[tau-1]; s1 = yinBuffer[tau]; @@ -352,10 +349,10 @@ } double -YinUtil::sumSquare(const double *in, const size_t start, const size_t end) +YinUtil::sumSquare(const double *in, int start, int end) { double out = 0; - for (size_t i = start; i < end; ++i) + for (int i = start; i < end; ++i) { out += in[i] * in[i]; }
--- a/YinUtil.h Thu Aug 20 16:06:01 2015 +0100 +++ b/YinUtil.h Fri Mar 24 15:08:12 2017 +0000 @@ -14,29 +14,35 @@ #ifndef _YINUTIL_H_ #define _YINUTIL_H_ -#include "vamp-sdk/FFT.h" -#include "MeanFilter.h" - #include <cmath> #include <iostream> #include <vector> #include <exception> +#include "vamp-sdk/FFT.h" + using std::vector; class YinUtil { public: - static double sumSquare(const double *in, const size_t startInd, const size_t endInd); - static void difference(const double *in, double *yinBuffer, const size_t yinBufferSize); - static void fastDifference(const double *in, double *yinBuffer, const size_t yinBufferSize); - static void slowDifference(const double *in, double *yinBuffer, const size_t yinBufferSize); - static void cumulativeDifference(double *yinBuffer, const size_t yinBufferSize); - static int absoluteThreshold(const double *yinBuffer, const size_t yinBufferSize, const double thresh); - static vector<double> yinProb(const double *yinBuffer, const size_t prior, const size_t yinBufferSize, size_t minTau = 0, size_t maxTau = 0); - static double parabolicInterpolation(const double *yinBuffer, const size_t tau, - const size_t yinBufferSize); + YinUtil(int yinBufferSize); + ~YinUtil(); + + double sumSquare(const double *in, int startInd, int endInd); + void difference(const double *in, double *yinBuffer); + void fastDifference(const double *in, double *yinBuffer); + void slowDifference(const double *in, double *yinBuffer); + void cumulativeDifference(double *yinBuffer); + int absoluteThreshold(const double *yinBuffer, double thresh); + vector<double> yinProb(const double *yinBuffer, int prior, + int minTau = 0, int maxTau = 0); + double parabolicInterpolation(const double *yinBuffer, int tau); + +private: + const int m_yinBufferSize; + Vamp::FFTReal m_fft; }; #endif
--- a/YinVamp.cpp Thu Aug 20 16:06:01 2015 +0100 +++ b/YinVamp.cpp Fri Mar 24 15:08:12 2017 +0000 @@ -78,7 +78,7 @@ { // Increment this each time you release a version that behaves // differently from the previous one - return 2; + return 3; } string @@ -192,7 +192,7 @@ } void -YinVamp::selectProgram(string name) +YinVamp::selectProgram(string) { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/expected.csv Fri Mar 24 15:08:12 2017 +0000 @@ -0,0 +1,4703 @@ +1.735691610,252.412 +1.741496599,254.413 +1.747301587,254.643 +1.753106576,253.891 +1.758911565,252.467 +1.764716553,253.517 +1.770521542,255.321 +1.776326531,258.847 +1.782131519,261.6 +1.787936508,263.998 +1.793741497,265.883 +1.799546485,266.994 +1.805351474,268.496 +1.811156463,269.366 +1.816961451,269.456 +1.822766440,268.831 +1.828571429,267.844 +1.834376417,266.514 +1.840181406,265.766 +1.845986395,264.956 +1.851791383,264.37 +1.857596372,264.137 +1.863401361,264.067 +1.869206349,264.323 +1.875011338,264.815 +1.880816327,265.899 +1.886621315,267.214 +1.892426304,268.953 +1.898231293,270.998 +1.904036281,273.541 +1.909841270,276.592 +1.915646259,279.918 +1.921451247,279.824 +1.927256236,278.924 +1.933061224,277.174 +1.938866213,273.883 +1.944671202,273.614 +1.950476190,275.704 +1.956281179,273.461 +1.962086168,276.074 +1.967891156,279.185 +1.973696145,285.13 +1.979501134,294.656 +1.985306122,306.645 +1.991111111,316.506 +1.996916100,326.039 +2.002721088,330.722 +2.008526077,333.649 +2.014331066,333.996 +2.020136054,335.731 +2.025941043,336.094 +2.031746032,336.23 +2.037551020,336.605 +2.043356009,335.974 +2.049160998,335.564 +2.054965986,335.253 +2.060770975,334.882 +2.066575964,334.479 +2.072380952,334.066 +2.078185941,333.512 +2.083990930,332.494 +2.089795918,331.672 +2.095600907,330.832 +2.101405896,329.969 +2.107210884,329.763 +2.113015873,329.382 +2.118820862,329.116 +2.124625850,328.764 +2.130430839,328.211 +2.136235828,327.856 +2.142040816,326.655 +2.147845805,325.664 +2.153650794,325.483 +2.159455782,324.706 +2.165260771,323.721 +2.171065760,322.11 +2.176870748,320.073 +2.182675737,316.313 +2.188480726,309.561 +2.194285714,306.083 +2.200090703,302.779 +2.205895692,299.065 +2.211700680,293.109 +2.217505669,288.801 +2.223310658,285.342 +2.229115646,282.218 +2.234920635,279.632 +2.240725624,273.15 +2.246530612,270.607 +2.252335601,267.999 +2.258140590,267.169 +2.263945578,266.127 +2.269750567,265.006 +2.275555556,264.045 +2.281360544,263.477 +2.287165533,263.399 +2.292970522,264.039 +2.298775510,264.747 +2.304580499,266.112 +2.310385488,267.01 +2.316190476,267.879 +2.321995465,268.449 +2.327800454,268.897 +2.333605442,269.227 +2.339410431,269.819 +2.345215420,270.534 +2.351020408,271.196 +2.356825397,272.272 +2.362630385,273.098 +2.368435374,273.824 +2.374240363,274.034 +2.380045351,273.791 +2.385850340,273.615 +2.391655329,273.698 +2.397460317,274.318 +2.403265306,275.918 +2.409070295,277.01 +2.414875283,278.867 +2.420680272,281.325 +2.426485261,284.908 +2.432290249,288.736 +2.438095238,294.569 +2.443900227,300.31 +2.449705215,308.271 +2.455510204,313.145 +2.461315193,317.372 +2.467120181,319.51 +2.472925170,321.016 +2.478730159,321.798 +2.484535147,322.67 +2.490340136,323.953 +2.496145125,325.347 +2.501950113,327.168 +2.507755102,327.963 +2.513560091,328.192 +2.519365079,328.1 +2.525170068,328.518 +2.530975057,328.809 +2.536780045,328.864 +2.542585034,328.943 +2.548390023,328.999 +2.554195011,328.968 +2.560000000,329.009 +2.565804989,328.974 +2.571609977,328.762 +2.577414966,328.681 +2.583219955,328.638 +2.589024943,329.024 +2.594829932,329.519 +2.600634921,330.155 +2.606439909,330.753 +2.612244898,331.158 +2.618049887,331.53 +2.623854875,331.78 +2.629659864,332.215 +2.635464853,332.58 +2.641269841,332.931 +2.647074830,332.944 +2.652879819,332.511 +2.658684807,331.749 +2.664489796,330.368 +2.670294785,328.701 +2.676099773,327.155 +2.681904762,325.393 +2.687709751,324.184 +2.693514739,324.473 +2.699319728,319.498 +2.705124717,311.588 +2.710929705,308.507 +2.716734694,306.978 +2.722539683,307.059 +2.728344671,312.666 +2.734149660,312.896 +2.739954649,314.627 +2.745759637,317.462 +2.751564626,319.347 +2.757369615,320.583 +2.763174603,323.506 +2.768979592,323.916 +2.774784580,323.069 +2.780589569,321.922 +2.786394558,319.91 +2.792199546,318.262 +2.798004535,317.344 +2.803809524,317.172 +2.809614512,317.983 +2.815419501,321.016 +2.821224490,327.503 +2.827029478,332.737 +2.832834467,335.854 +2.838639456,337.035 +2.844444444,337.862 +2.850249433,338.418 +2.856054422,337.95 +2.861859410,337.362 +2.867664399,336.394 +2.873469388,335.528 +2.879274376,334.456 +2.885079365,332.998 +2.890884354,331.52 +2.896689342,330.019 +2.902494331,329.596 +2.908299320,329.44 +2.914104308,329.863 +2.919909297,330.944 +2.925714286,332.186 +2.931519274,333.656 +2.937324263,335.226 +2.943129252,337.086 +2.948934240,338.915 +2.954739229,340.845 +2.960544218,342.906 +2.966349206,344.962 +2.972154195,347.113 +2.977959184,348.997 +2.983764172,350.634 +2.989569161,352.211 +2.995374150,353.816 +3.001179138,355.631 +3.006984127,357.547 +3.012789116,359.602 +3.018594104,361.518 +3.024399093,363.598 +3.030204082,365.586 +3.036009070,366.756 +3.041814059,367.608 +3.047619048,368.035 +3.053424036,368.299 +3.059229025,368.882 +3.065034014,369.402 +3.070839002,369.876 +3.076643991,370.259 +3.082448980,370.194 +3.088253968,369.853 +3.094058957,369.302 +3.099863946,368.579 +3.105668934,367.936 +3.111473923,367.33 +3.117278912,366.378 +3.123083900,365.526 +3.128888889,365.191 +3.134693878,366.45 +3.140498866,369.807 +3.146303855,377.487 +3.152108844,386.451 +3.157913832,397.468 +3.163718821,402.447 +3.169523810,399.475 +3.175328798,401.39 +5.143219955,202.143 +5.149024943,205.362 +5.154829932,210.774 +5.160634921,215.306 +5.166439909,218.368 +5.172244898,219.412 +5.178049887,218.697 +5.183854875,217.656 +5.189659864,216.04 +5.195464853,214.503 +5.201269841,212.6 +5.207074830,211.436 +5.212879819,210.398 +5.218684807,209.289 +5.224489796,208.006 +5.230294785,206.885 +5.236099773,206.17 +5.241904762,205.84 +5.247709751,205.712 +5.253514739,205.725 +5.259319728,206.428 +5.265124717,207.283 +5.270929705,208.38 +5.276734694,209.693 +5.282539683,211.301 +5.288344671,212.934 +5.294149660,214.319 +5.299954649,215.439 +5.305759637,217.061 +5.311564626,218.937 +5.317369615,222.237 +5.323174603,226.637 +5.328979592,230.071 +5.334784580,231.797 +5.340589569,232.447 +5.346394558,231.522 +5.352199546,230.174 +5.358004535,227.808 +5.363809524,224.731 +5.369614512,221.866 +5.375419501,219.407 +5.381224490,216.981 +5.387029478,214.839 +5.392834467,214.34 +5.398639456,215.229 +5.404444444,214.782 +5.410249433,214.051 +5.416054422,213.675 +5.421859410,213.818 +5.427664399,213.935 +5.433469388,214.431 +5.439274376,215.188 +5.445079365,216.022 +5.450884354,217.593 +5.456689342,219.325 +5.462494331,220.562 +5.468299320,221.697 +5.474104308,222.829 +5.479909297,223.538 +5.485714286,224.115 +5.491519274,224.728 +5.497324263,224.816 +5.503129252,224.773 +5.508934240,224.071 +5.514739229,223.16 +5.520544218,222.296 +5.526349206,221.399 +5.532154195,220.092 +5.537959184,218.97 +5.543764172,217.667 +5.549569161,214.954 +5.694693878,222.566 +5.700498866,223.295 +5.706303855,224.353 +5.712108844,226.091 +5.717913832,228.155 +5.723718821,229.545 +5.729523810,231.235 +5.735328798,233.01 +5.741133787,234.832 +5.746938776,236.291 +5.752743764,237.627 +5.758548753,238.746 +5.764353741,239.764 +5.770158730,240.63 +5.775963719,241.948 +5.781768707,243.459 +5.787573696,245.089 +5.793378685,246.366 +5.799183673,247.748 +5.804988662,248.889 +5.810793651,250.337 +5.816598639,251.867 +5.822403628,253.409 +5.828208617,254.557 +5.834013605,255.193 +5.839818594,255.93 +5.845623583,256.604 +5.851428571,257.607 +5.857233560,258.476 +5.863038549,259.779 +5.868843537,260.82 +5.874648526,262.085 +5.880453515,262.949 +5.886258503,263.863 +5.892063492,264.675 +5.897868481,265.614 +5.903673469,266.902 +5.909478458,267.93 +5.915283447,269.124 +5.921088435,269.714 +5.926893424,270.578 +5.932698413,271.165 +5.938503401,271.799 +5.944308390,272.252 +5.950113379,272.682 +5.955918367,272.911 +5.961723356,273.072 +5.967528345,272.722 +5.973333333,271.489 +5.979138322,269.383 +5.984943311,263.216 +5.990748299,251.7 +5.996553288,243.079 +6.002358277,234.745 +6.008163265,231.227 +6.013968254,229.352 +6.019773243,228.603 +6.025578231,230.117 +6.031383220,237.565 +6.037188209,237.182 +6.124263039,234.826 +6.130068027,234.885 +6.135873016,236.442 +6.141678005,241.44 +6.147482993,244.692 +6.153287982,247.536 +6.159092971,248.844 +6.164897959,249.57 +6.170702948,249.676 +6.176507937,249.736 +6.182312925,249.656 +6.188117914,249.752 +6.193922902,249.799 +6.199727891,249.805 +6.205532880,249.284 +6.211337868,248.866 +6.217142857,248.116 +6.222947846,247.702 +6.228752834,247.113 +6.234557823,246.612 +6.240362812,246.104 +6.246167800,245.326 +6.251972789,244.646 +6.257777778,243.594 +6.263582766,242.971 +6.269387755,242.649 +6.275192744,242.522 +6.280997732,242.644 +6.286802721,242.434 +6.292607710,241.456 +6.298412698,240.913 +6.304217687,239.588 +6.310022676,238.288 +6.315827664,236.98 +6.321632653,235.54 +6.327437642,234.138 +6.333242630,232.196 +6.339047619,229.65 +6.344852608,227 +6.350657596,223.512 +6.356462585,218.03 +6.362267574,211.172 +6.368072562,205.238 +6.373877551,201.304 +6.379682540,198.054 +6.385487528,196.76 +6.391292517,198.036 +6.397097506,200.972 +6.402902494,204.076 +6.408707483,207.163 +6.414512472,209.372 +6.420317460,211.08 +6.426122449,212.414 +6.431927438,213.723 +6.437732426,215.326 +6.443537415,217.995 +6.449342404,220.793 +6.455147392,223.074 +6.460952381,224.639 +6.466757370,225.762 +6.472562358,225.708 +6.478367347,225.028 +6.484172336,223.895 +6.489977324,222.179 +6.495782313,220.644 +6.501587302,219.285 +6.507392290,217.321 +6.513197279,216.002 +6.519002268,214.916 +6.524807256,214.116 +6.530612245,213.061 +6.536417234,212.638 +6.542222222,212.819 +6.548027211,213.363 +6.553832200,214.851 +6.559637188,216.061 +6.565442177,216.835 +6.571247166,217.108 +6.577052154,217.319 +6.582857143,217.771 +6.588662132,219.017 +6.594467120,222.693 +6.600272109,228.017 +6.606077098,232.697 +6.611882086,235.748 +6.617687075,237.614 +6.623492063,238.467 +6.629297052,237.597 +6.635102041,234.525 +6.640907029,231.367 +6.646712018,226.874 +6.652517007,221.2 +6.658321995,216.145 +6.664126984,210.932 +6.669931973,204.813 +6.675736961,200.939 +6.681541950,199.032 +6.687346939,197.011 +6.693151927,195.609 +6.698956916,194.8 +6.704761905,195.354 +6.710566893,198.917 +6.716371882,203.754 +6.722176871,207.771 +6.727981859,211.338 +6.733786848,220.502 +6.739591837,228.854 +6.745396825,237.674 +6.751201814,245.261 +6.757006803,252.686 +6.762811791,251.725 +6.768616780,248.321 +6.774421769,246.093 +6.780226757,242.515 +6.786031746,242.066 +6.791836735,241.562 +7.569705215,250.861 +7.575510204,254.016 +7.581315193,258.191 +7.587120181,261.662 +7.592925170,264.307 +7.598730159,266.468 +7.604535147,267.547 +7.610340136,268.474 +7.616145125,268.854 +7.621950113,269.617 +7.627755102,270.643 +7.633560091,271.303 +7.639365079,271.949 +7.645170068,272.534 +7.650975057,272.62 +7.656780045,272.348 +7.662585034,271.852 +7.668390023,270.978 +7.674195011,270.297 +7.680000000,270.341 +7.685804989,270.518 +7.691609977,271.171 +7.697414966,271.539 +7.703219955,271.501 +7.709024943,271.092 +7.714829932,270.764 +7.720634921,270.518 +7.726439909,270.441 +7.732244898,270.599 +7.738049887,270.857 +7.743854875,271.424 +7.749659864,272.688 +7.755464853,275.037 +7.761269841,278.28 +7.767074830,281.078 +7.772879819,282.272 +7.778684807,283.015 +7.784489796,283.022 +7.790294785,283.089 +7.796099773,284.653 +7.801904762,282.854 +7.807709751,287.781 +7.813514739,296.616 +7.819319728,303.095 +7.825124717,309.875 +7.830929705,317.103 +7.836734694,322.316 +7.842539683,326.311 +7.848344671,328.413 +7.854149660,329.266 +7.859954649,329.872 +7.865759637,330.121 +7.871564626,330.328 +7.877369615,330.591 +7.883174603,330.896 +7.888979592,331.125 +7.894784580,331.482 +7.900589569,331.468 +7.906394558,331.45 +7.912199546,331.547 +7.918004535,332.047 +7.923809524,332.977 +7.929614512,333.724 +7.935419501,334.723 +7.941224490,335.633 +7.947029478,336.756 +7.952834467,338.582 +7.958639456,339.871 +7.964444444,340.723 +7.970249433,340.541 +7.976054422,340.064 +7.981859410,339.208 +7.987664399,337.866 +7.993469388,336.578 +7.999274376,334.602 +8.005079365,332.202 +8.010884354,329.587 +8.016689342,326.897 +8.022494331,324.677 +8.028299320,322.143 +8.034104308,319.595 +8.039909297,316.029 +8.045714286,309.37 +8.051519274,302.282 +8.057324263,296.59 +8.063129252,290.306 +8.068934240,283.999 +8.074739229,279.76 +8.080544218,276.515 +8.086349206,272.788 +8.092154195,271.098 +8.097959184,270.738 +8.103764172,270.544 +8.109569161,270.507 +8.115374150,270.504 +8.121179138,270.583 +8.126984127,270.589 +8.132789116,270.781 +8.138594104,271.018 +8.144399093,271.616 +8.150204082,272.504 +8.156009070,273.5 +8.161814059,274.187 +8.167619048,274.537 +8.173424036,274.435 +8.179229025,274.253 +8.185034014,274.176 +8.190839002,274.353 +8.196643991,275.108 +8.202448980,276.234 +8.208253968,277.9 +8.214058957,279.86 +8.219863946,282.423 +8.225668934,284.334 +8.231473923,285.747 +8.237278912,286.869 +8.243083900,287.279 +8.248888889,286.539 +8.254693878,285.671 +8.260498866,284.914 +8.266303855,285.211 +8.272108844,287.247 +8.277913832,289.24 +8.283718821,291.935 +8.289523810,295.572 +8.295328798,299.241 +8.301133787,303.093 +8.306938776,308.054 +8.312743764,313.279 +8.318548753,317.123 +8.324353741,320.351 +8.330158730,326.33 +8.335963719,329.995 +8.341768707,332.347 +8.347573696,332.869 +8.353378685,332.979 +8.359183673,332.618 +8.364988662,332.159 +8.370793651,331.673 +8.376598639,331.157 +8.382403628,330.66 +8.388208617,329.988 +8.394013605,329.366 +8.399818594,328.828 +8.405623583,328.245 +8.411428571,327.996 +8.417233560,328.018 +8.423038549,328.096 +8.428843537,328.132 +8.434648526,328.294 +8.440453515,328.371 +8.446258503,328.419 +8.452063492,328.766 +8.457868481,329.087 +8.463673469,329.479 +8.469478458,329.75 +8.475283447,329.902 +8.481088435,329.859 +8.486893424,329.643 +8.492698413,329.019 +8.498503401,327.963 +8.504308390,326.356 +8.510113379,324.962 +8.515918367,324.201 +8.521723356,323.334 +8.527528345,323.451 +8.533333333,325.673 +8.539138322,317.944 +8.544943311,312.903 +8.550748299,318.088 +8.556553288,318.482 +8.562358277,318.139 +8.568163265,319.463 +8.573968254,321.886 +8.579773243,325.794 +8.585578231,330.316 +8.591383220,336.202 +8.597188209,340.257 +8.602993197,343.25 +8.608798186,344.985 +8.614603175,346.175 +8.620408163,346.972 +8.626213152,347.497 +8.632018141,347.559 +8.637823129,347.816 +8.643628118,347.576 +8.649433107,347.039 +8.655238095,346.125 +8.661043084,344.55 +8.666848073,342.817 +8.672653061,341.174 +8.678458050,339.401 +8.684263039,337.755 +8.690068027,336.289 +8.695873016,334.476 +8.701678005,332.848 +8.707482993,331.606 +8.713287982,330.77 +8.719092971,330.81 +8.724897959,331.505 +8.730702948,332.896 +8.736507937,334.4 +8.742312925,336.004 +8.748117914,337.629 +8.753922902,339.108 +8.759727891,340.557 +8.765532880,342.076 +8.771337868,343.685 +8.777142857,345.494 +8.782947846,347.207 +8.788752834,349.139 +8.794557823,351.251 +8.800362812,353.188 +8.806167800,355.414 +8.811972789,357.486 +8.817777778,359.524 +8.823582766,361.363 +8.829387755,362.924 +8.835192744,364.538 +8.840997732,365.939 +8.846802721,367.225 +8.852607710,368.424 +8.858412698,369.196 +8.864217687,369.304 +8.870022676,368.813 +8.875827664,367.863 +8.881632653,366.741 +8.887437642,366.193 +8.893242630,365.673 +8.899047619,365.364 +8.904852608,365.468 +8.910657596,365.685 +8.916462585,365.945 +8.922267574,366.384 +8.928072562,366.719 +8.933877551,367.024 +8.939682540,367.517 +8.945487528,368.053 +8.951292517,368.514 +8.957097506,368.904 +8.962902494,369.414 +8.968707483,370.003 +8.974512472,370.52 +8.980317460,371.882 +8.986122449,375.159 +11.969886621,196.411 +11.975691610,201.476 +11.981496599,207.764 +11.987301587,211.601 +11.993106576,221.157 +11.998911565,227.621 +12.004716553,231.139 +12.010521542,236.093 +12.016326531,239.618 +12.022131519,243.172 +12.027936508,246.224 +12.033741497,250.693 +12.039546485,254.743 +12.045351474,257.813 +12.051156463,260.037 +12.056961451,262.646 +12.062766440,264.664 +12.068571429,265.956 +12.074376417,266.182 +12.080181406,265.45 +12.085986395,264.858 +12.091791383,261.142 +12.097596372,257.589 +12.103401361,254.808 +12.109206349,254.232 +12.115011338,253.869 +12.120816327,253.939 +12.126621315,254.987 +12.132426304,256.715 +12.138231293,259.992 +12.144036281,262.717 +12.149841270,265.801 +12.155646259,267.579 +12.161451247,269.907 +12.167256236,271.435 +12.173061224,272.996 +12.178866213,273.951 +12.184671202,274.383 +12.190476190,274.274 +12.196281179,273.75 +12.202086168,272.506 +12.207891156,271.075 +12.213696145,269.501 +12.219501134,268.132 +12.225306122,266.702 +12.231111111,265.043 +12.236916100,263.519 +12.242721088,261.511 +12.248526077,260.019 +12.254331066,257.943 +12.260136054,256.721 +12.265941043,254.259 +12.271746032,252.087 +12.277551020,249.956 +12.283356009,248.329 +12.289160998,246.421 +12.294965986,243.999 +12.300770975,242.183 +12.306575964,241.693 +12.312380952,241.927 +12.318185941,242.228 +12.323990930,242.23 +12.329795918,242.353 +12.335600907,242.329 +12.341405896,242.31 +12.347210884,242.365 +12.353015873,242.069 +12.358820862,241.482 +12.364625850,240.535 +12.370430839,239.205 +12.376235828,237.141 +12.382040816,235.079 +12.387845805,232.978 +12.393650794,229.879 +12.399455782,226.314 +12.405260771,214.97 +12.411065760,202.445 +12.416870748,195.292 +12.422675737,189.787 +12.428480726,184.249 +12.434285714,179.32 +12.440090703,174.054 +12.445895692,168.981 +12.451700680,166.002 +12.457505669,166.395 +12.463310658,170.21 +12.469115646,170.209 +12.474920635,180.358 +12.480725624,190.407 +12.486530612,200.494 +12.492335601,205.165 +12.498140590,207.949 +12.503945578,210.557 +12.509750567,212.927 +12.515555556,215.706 +12.521360544,218.286 +12.527165533,220.398 +12.532970522,222.736 +12.538775510,224.111 +12.544580499,224.668 +12.550385488,224.525 +12.556190476,223.879 +12.561995465,222.914 +12.567800454,221.644 +12.573605442,219.726 +12.579410431,217.847 +12.585215420,216.395 +12.591020408,215.418 +12.596825397,215.148 +12.602630385,215.533 +12.608435374,216.481 +12.614240363,217.766 +12.620045351,218.729 +12.625850340,219.096 +12.631655329,219.235 +12.637460317,219.263 +12.643265306,219.565 +12.649070295,220.14 +12.654875283,221.013 +12.660680272,222.229 +12.666485261,223.708 +12.672290249,224.766 +12.678095238,225.555 +12.683900227,226.014 +12.689705215,225.844 +12.695510204,225.62 +12.701315193,225.143 +12.707120181,224.411 +12.712925170,223.479 +12.718730159,222.085 +12.724535147,220.611 +12.730340136,218.913 +12.736145125,216.956 +12.741950113,214.973 +12.747755102,213.542 +12.753560091,212.614 +12.759365079,211.898 +12.765170068,211.769 +12.770975057,211.71 +12.776780045,211.948 +12.782585034,212.717 +12.788390023,213.719 +12.794195011,215.123 +12.800000000,217.024 +12.805804989,219.267 +12.811609977,221.444 +12.817414966,223.473 +12.823219955,226.532 +12.829024943,230.164 +12.834829932,234.128 +12.840634921,236.565 +12.846439909,238.241 +12.852244898,241.686 +12.858049887,245.456 +12.863854875,251.305 +12.869659864,262.552 +12.875464853,260.546 +12.968344671,233.337 +12.974149660,233.719 +12.979954649,237.725 +12.985759637,239.12 +12.991564626,240.028 +12.997369615,240.521 +13.003174603,240.724 +13.008979592,241.882 +13.014784580,242.997 +13.020589569,244.522 +13.026394558,245.308 +13.032199546,246.034 +13.038004535,246.021 +13.043809524,245.774 +13.049614512,245.08 +13.055419501,244.274 +13.061224490,243.183 +13.067029478,241.842 +13.072834467,239.693 +13.078639456,238.169 +13.084444444,237.219 +13.090249433,236.741 +13.096054422,236.855 +13.101859410,237.125 +13.107664399,237.988 +13.113469388,239.33 +13.119274376,241.211 +13.125079365,242.33 +13.130884354,243.092 +13.136689342,243.8 +13.142494331,244.154 +13.148299320,245.263 +13.154104308,246.245 +13.159909297,247.043 +13.165714286,247.452 +13.171519274,247.284 +13.177324263,246.741 +13.183129252,245.988 +13.188934240,244.904 +13.194739229,244.416 +13.200544218,246.369 +13.206349206,250.097 +13.212154195,249.526 +13.217959184,248.575 +13.223764172,247.593 +13.229569161,246.235 +13.235374150,244.189 +13.241179138,238.178 +13.246984127,232.186 +13.252789116,242.491 +13.258594104,251.249 +13.264399093,249.905 +13.270204082,246.208 +13.276009070,243.11 +13.281814059,240.52 +13.287619048,240.432 +13.293424036,242.667 +13.450158730,241.225 +13.455963719,242.859 +13.461768707,243.284 +13.467573696,243.175 +13.473378685,243.077 +13.479183673,242.212 +13.484988662,241.31 +13.490793651,240.315 +13.496598639,239.675 +13.502403628,239.391 +13.508208617,239.318 +13.514013605,239.687 +13.519818594,240.425 +13.525623583,241.416 +13.531428571,242.663 +13.537233560,244.061 +13.543038549,245.619 +13.548843537,247.223 +13.554648526,248.748 +13.560453515,250.4 +13.566258503,252.231 +13.572063492,254.057 +13.577868481,256.673 +13.583673469,258.823 +13.589478458,261.237 +13.595283447,263.221 +13.601088435,265.579 +13.606893424,267.413 +13.612698413,269.168 +13.618503401,270.622 +13.624308390,272.05 +13.630113379,273.205 +13.635918367,274.3 +13.641723356,275.268 +13.647528345,276.213 +13.653333333,277.209 +13.659138322,278.343 +13.664943311,279.266 +13.670748299,279.869 +13.676553288,279.523 +13.682358277,278.75 +13.688163265,277.885 +13.693968254,276.336 +13.699773243,273.44 +13.705578231,269.69 +13.711383220,271.398 +13.717188209,275.118 +13.722993197,284.376 +13.728798186,291.995 +13.734603175,302.687 +13.740408163,307.035 +13.746213152,316.631 +13.752018141,319.901 +13.757823129,321.695 +13.763628118,322.89 +13.769433107,324.568 +13.775238095,326.529 +13.781043084,328.277 +13.786848073,329.809 +13.792653061,330.957 +13.798458050,331.672 +13.804263039,332.016 +13.810068027,331.657 +13.815873016,331.098 +13.821678005,330.085 +13.827482993,329.11 +13.833287982,328.127 +13.839092971,327.081 +13.844897959,326.007 +13.850702948,324.519 +13.856507937,322.595 +13.862312925,320.425 +13.868117914,318.86 +13.873922902,317.462 +13.879727891,317.306 +13.885532880,316.658 +13.891337868,311.313 +13.897142857,307.251 +13.902947846,300.286 +13.908752834,289.28 +13.914557823,279.113 +13.920362812,269.891 +13.926167800,265.108 +13.931972789,257.329 +13.937777778,253.346 +13.943582766,246.724 +13.949387755,243.275 +13.955192744,240.569 +13.960997732,239.939 +13.966802721,240.126 +13.972607710,241.211 +13.978412698,242.612 +13.984217687,244.86 +13.990022676,246.79 +13.995827664,248.185 +14.001632653,249.239 +14.007437642,249.826 +14.013242630,249.979 +14.019047619,249.967 +14.024852608,249.664 +14.030657596,249.561 +14.036462585,249.917 +14.042267574,250.438 +14.048072562,251.179 +14.053877551,252.033 +14.059682540,253.194 +14.065487528,254.943 +14.071292517,256.383 +14.077097506,258.036 +14.082902494,259.073 +14.088707483,260.243 +14.094512472,260.723 +14.100317460,261.394 +14.106122449,262.268 +14.111927438,263.609 +14.117732426,265.108 +14.123537415,266.393 +14.129342404,267.805 +14.135147392,268.742 +14.140952381,269.842 +14.146757370,270.47 +14.152562358,271.235 +14.158367347,272.311 +14.164172336,273.675 +14.169977324,275.082 +14.175782313,276.161 +14.181587302,276.835 +14.187392290,277.111 +14.193197279,277.58 +14.199002268,277.558 +14.204807256,277.276 +14.210612245,276.697 +14.216417234,276.698 +14.222222222,277.044 +14.228027211,277.277 +14.233832200,277.222 +14.239637188,278.6 +14.245442177,275.327 +14.251247166,273.674 +14.257052154,273.212 +14.262857143,273.197 +14.268662132,273.384 +14.274467120,273.117 +14.280272109,272.75 +14.286077098,271.621 +14.291882086,270.138 +14.297687075,267.159 +14.303492063,263.767 +14.309297052,259.146 +14.315102041,256.448 +14.320907029,252.089 +14.326712018,248.629 +14.332517007,243.788 +14.338321995,239.303 +14.344126984,235.543 +14.349931973,231.974 +14.355736961,228.119 +14.361541950,224.362 +14.367346939,221.104 +14.373151927,217.696 +14.378956916,215.656 +14.384761905,214.218 +14.390566893,212.975 +14.396371882,211.293 +14.402176871,210.139 +14.407981859,209.402 +14.413786848,208.941 +14.419591837,208.57 +14.425396825,208.491 +14.431201814,208.602 +14.437006803,209.011 +14.442811791,209.678 +14.448616780,210.803 +14.454421769,211.654 +14.460226757,212.243 +14.466031746,212.547 +14.471836735,212.73 +14.477641723,214.237 +14.483446712,217.111 +14.489251701,223.308 +14.495056689,225.831 +14.500861678,225.528 +14.506666667,226.504 +14.512471655,226.693 +14.518276644,226.641 +14.524081633,227.069 +14.529886621,227.128 +14.535691610,227.917 +14.541496599,229.054 +14.547301587,230.191 +14.553106576,230.779 +14.558911565,231.039 +14.564716553,230.501 +14.570521542,228.629 +14.576326531,225.763 +14.582131519,223.952 +14.587936508,222.137 +14.593741497,220.583 +14.599546485,219.182 +14.605351474,218.024 +14.611156463,216.485 +14.616961451,214.979 +14.622766440,214.357 +14.628571429,213.388 +14.634376417,212.458 +14.640181406,212.246 +14.645986395,208.59 +14.959455782,202.925 +14.965260771,211.076 +14.971065760,220.319 +14.976870748,229.585 +14.982675737,237.825 +14.988480726,247.362 +14.994285714,255.221 +15.000090703,263.223 +15.005895692,267.966 +15.011700680,270.802 +15.017505669,272.694 +15.023310658,273.602 +15.029115646,274.2 +15.034920635,274.548 +15.040725624,274.91 +15.046530612,274.66 +15.052335601,274.175 +15.058140590,272.819 +15.063945578,271.498 +15.069750567,270.361 +15.075555556,269.915 +15.081360544,269.193 +15.087165533,269.202 +15.092970522,269.367 +15.098775510,269.899 +15.104580499,270.559 +15.110385488,271.533 +15.116190476,272.319 +15.121995465,273.042 +15.127800454,273.344 +15.133605442,273.038 +15.139410431,272.004 +15.145215420,270.536 +15.151020408,268.814 +15.156825397,268.1 +15.162630385,267.799 +15.168435374,268.454 +15.174240363,269.561 +15.180045351,270.695 +15.185850340,271.685 +15.191655329,271.867 +15.197460317,271.656 +15.203265306,270.121 +15.209070295,268.713 +15.214875283,266.915 +15.220680272,265.683 +15.226485261,265.023 +15.232290249,264.992 +15.238095238,266.235 +15.243900227,267.39 +15.249705215,268.087 +15.255510204,268.698 +15.261315193,269.24 +15.267120181,269.329 +15.272925170,269.726 +15.278730159,270.204 +15.284535147,269.832 +15.290340136,269.241 +15.296145125,264.217 +15.307755102,237.723 +15.313560091,234.773 +15.319365079,231.427 +15.325170068,229.846 +15.330975057,229.45 +15.336780045,229.019 +15.342585034,226.918 +15.348390023,226.163 +15.354195011,225.638 +15.360000000,225.456 +15.365804989,224.763 +15.371609977,226.19 +15.377414966,230.329 +15.383219955,235.093 +15.389024943,243.553 +15.394829932,255.951 +15.400634921,262.582 +15.429659864,334.745 +15.435464853,335.576 +15.441269841,336.306 +15.447074830,336.891 +15.452879819,337.115 +15.458684807,336.745 +15.464489796,335.69 +15.470294785,333.946 +15.476099773,332.294 +15.481904762,331.242 +15.487709751,330.352 +15.493514739,329.921 +15.499319728,329.765 +15.505124717,329.42 +15.510929705,329.324 +15.516734694,329.63 +15.522539683,330.409 +15.528344671,331.455 +15.534149660,332.462 +15.539954649,332.974 +15.545759637,332.84 +15.551564626,332.251 +15.557369615,331.096 +15.563174603,329.846 +15.568979592,328.971 +15.574784580,328.607 +15.580589569,329.005 +15.586394558,329.761 +15.592199546,330.559 +15.598004535,331.087 +15.603809524,331.405 +15.609614512,331.403 +15.615419501,331.474 +15.621224490,331.6 +15.627029478,331.902 +15.632834467,332.451 +15.638639456,332.8 +15.644444444,333.074 +15.650249433,333.503 +15.656054422,334.142 +15.661859410,335.15 +15.667664399,336.648 +15.673469388,338.157 +15.679274376,339.665 +15.685079365,340.692 +15.690884354,341.118 +15.696689342,340.965 +15.702494331,340.948 +15.708299320,340.89 +15.714104308,341.04 +15.719909297,341.406 +15.725714286,341.404 +15.731519274,341.101 +15.737324263,340.374 +15.743129252,338.743 +15.748934240,337.001 +15.754739229,333.759 +15.760544218,325.376 +15.917278912,252.975 +15.923083900,255.979 +15.928888889,260.149 +15.934693878,262.085 +15.940498866,263.984 +15.946303855,265.803 +15.952108844,268.322 +15.957913832,270.297 +15.963718821,272.698 +15.969523810,274.195 +15.975328798,275.407 +15.981133787,276.164 +15.986938776,276.524 +15.992743764,276.462 +15.998548753,276.069 +16.004353741,275.366 +16.010158730,274.348 +16.015963719,273.251 +16.021768707,272.08 +16.027573696,271.539 +16.033378685,271.417 +16.039183673,272.354 +16.044988662,273.376 +16.050793651,275.013 +16.056598639,275.883 +16.062403628,276.202 +16.068208617,276.208 +16.074013605,276.077 +16.079818594,275.9 +16.085623583,276.092 +16.091428571,276.363 +16.097233560,276.232 +16.103038549,276.263 +16.108843537,273.766 +16.184308390,324.582 +16.190113379,329.411 +16.195918367,332.724 +16.201723356,333.18 +16.207528345,333.497 +16.213333333,333.788 +16.219138322,333.682 +16.224943311,333.263 +16.230748299,333.892 +16.236553288,336.271 +16.242358277,337.042 +16.248163265,336.306 +16.253968254,334.776 +16.259773243,331.936 +16.265578231,329.565 +16.271383220,328.149 +16.277188209,326.626 +16.282993197,325.589 +16.288798186,324.721 +16.294603175,324.274 +16.300408163,324.278 +16.306213152,324.837 +16.312018141,325.953 +16.317823129,326.956 +16.323628118,327.751 +16.329433107,328.141 +16.335238095,328.529 +16.341043084,329.002 +16.346848073,328.824 +16.352653061,329.149 +16.358458050,329.478 +16.364263039,329.681 +16.370068027,330.246 +16.375873016,330.711 +16.381678005,331.297 +16.387482993,331.978 +16.393287982,332.301 +16.399092971,331.477 +16.404897959,329.778 +16.410702948,328.368 +16.416507937,325.793 +16.422312925,323.049 +16.428117914,326.116 +16.474557823,345.818 +16.480362812,344.102 +16.486167800,341.795 +16.491972789,340.258 +16.497777778,338.802 +16.503582766,337.663 +16.509387755,336.43 +16.515192744,334.724 +16.520997732,333.287 +16.526802721,331.789 +16.532607710,330.131 +16.538412698,328.482 +16.544217687,327.195 +16.550022676,326.163 +16.555827664,325.523 +16.561632653,325.33 +16.567437642,325.375 +16.573242630,325.979 +16.579047619,327 +16.584852608,328.34 +16.590657596,330.243 +16.596462585,332.489 +16.602267574,335.082 +16.608072562,337.569 +16.613877551,340.165 +16.619682540,342.52 +16.625487528,345.218 +16.631292517,348.313 +16.637097506,351.574 +16.642902494,354.845 +16.648707483,357.652 +16.654512472,359.781 +16.660317460,361.393 +16.666122449,362.701 +16.671927438,363.744 +16.677732426,364.594 +16.683537415,365.03 +16.689342404,365.237 +16.695147392,365.194 +16.700952381,365.119 +16.706757370,365.066 +16.712562358,365.434 +16.718367347,365.788 +16.724172336,366.21 +16.729977324,366.696 +16.735782313,366.846 +16.741587302,367.573 +16.747392290,368.325 +16.753197279,370.594 +16.759002268,372.853 +16.764807256,374.458 +16.770612245,376.885 +16.776417234,376.816 +16.782222222,378.934 +19.394467120,81.7962 +19.400272109,81.7749 +19.406077098,82.2093 +19.411882086,82.6523 +19.417687075,83.0027 +19.423492063,82.223 +19.429297052,81.675 +19.435102041,81.4251 +19.440907029,81.759 +19.446712018,82.7227 +19.452517007,82.7592 +19.458321995,82.1042 +19.464126984,81.7673 +19.469931973,81.7316 +19.475736961,81.8553 +19.481541950,82.4663 +19.487346939,82.4558 +19.493151927,82.1734 +19.498956916,82.162 +19.504761905,82.0019 +19.510566893,81.9863 +19.516371882,81.9336 +19.522176871,81.9979 +19.527981859,81.8249 +19.533786848,81.8208 +19.539591837,80.5881 +19.545396825,80.6947 +19.551201814,81.3244 +19.795011338,175.889 +19.800816327,181.724 +19.806621315,186.333 +19.812426304,191.63 +19.818231293,196.636 +19.824036281,200.567 +19.829841270,203.655 +19.835646259,206.606 +19.841451247,209.013 +19.847256236,210.899 +19.853061224,212.412 +19.858866213,213.501 +19.864671202,214.412 +19.870476190,215.502 +19.876281179,216.403 +19.882086168,217.241 +19.887891156,217.844 +19.893696145,218.335 +19.899501134,218.68 +19.905306122,219.114 +19.911111111,219.641 +19.916916100,220.658 +19.922721088,221.386 +19.928526077,221.785 +19.934331066,222.109 +19.940136054,222.132 +19.945941043,222.059 +19.951746032,221.864 +19.957551020,221.225 +19.963356009,220.132 +19.969160998,217.889 +19.974965986,211.719 +20.114285714,211.79 +20.120090703,211.987 +20.125895692,212.486 +20.131700680,213.162 +20.137505669,214.835 +20.143310658,216.577 +20.149115646,218.05 +20.154920635,219.362 +20.160725624,220.896 +20.166530612,221.962 +20.172335601,222.577 +20.178140590,222.406 +20.183945578,221.631 +20.189750567,220.738 +20.195555556,219.751 +20.201360544,218.793 +20.207165533,218.368 +20.212970522,218.088 +20.218775510,218.477 +20.224580499,219.055 +20.230385488,220.244 +20.236190476,222.031 +20.241995465,224.367 +20.247800454,227.487 +20.253605442,230.594 +20.259410431,234.267 +20.265215420,239.137 +20.271020408,249.807 +20.276825397,260.532 +20.282630385,274.172 +20.288435374,286.064 +20.294240363,299.879 +20.300045351,312.259 +20.305850340,322.128 +20.311655329,333.035 +20.317460317,341.132 +20.323265306,346.968 +20.329070295,354.149 +20.334875283,356.925 +20.340680272,359.415 +20.346485261,361.22 +20.352290249,363.437 +20.358095238,365.637 +20.363900227,367.58 +20.369705215,368.194 +20.375510204,368.256 +20.381315193,367.46 +20.387120181,366.163 +20.392925170,365.721 +20.398730159,365.324 +20.404535147,364.918 +20.410340136,364.49 +20.416145125,364.22 +20.421950113,364.04 +20.427755102,364.121 +20.433560091,364.075 +20.439365079,364.303 +20.445170068,364.233 +20.450975057,364.214 +20.456780045,364.201 +20.462585034,363.897 +20.468390023,363.657 +20.474195011,363.399 +20.480000000,363.61 +20.485804989,364.081 +20.491609977,364.989 +20.497414966,366.079 +20.503219955,367.193 +20.509024943,368.117 +20.514829932,368.339 +20.520634921,368.05 +20.526439909,367.72 +20.532244898,367.638 +20.538049887,367.742 +20.543854875,367.953 +20.549659864,368.172 +20.555464853,368.189 +20.561269841,368.119 +20.567074830,367.933 +20.572879819,367.692 +20.578684807,367.499 +20.584489796,367.278 +20.590294785,367.048 +20.596099773,366.573 +20.601904762,365.902 +20.607709751,363.806 +20.613514739,358.16 +20.619319728,348.504 +20.625124717,335.721 +20.630929705,337.896 +20.636734694,345.119 +20.642539683,344.443 +20.648344671,347.687 +20.776054422,386.501 +20.781859410,382.926 +20.787664399,385.267 +20.793469388,382.285 +20.799274376,378.723 +20.805079365,376.669 +20.810884354,374.196 +20.816689342,372.199 +20.822494331,371.684 +20.828299320,372.948 +20.834104308,375.184 +20.839909297,376.308 +20.845714286,376.665 +20.851519274,376.008 +20.857324263,373.225 +20.863129252,370.849 +20.868934240,370.297 +20.874739229,370.51 +20.880544218,370.707 +20.886349206,370.461 +20.892154195,370.177 +20.897959184,369.53 +20.903764172,368.422 +20.909569161,367.416 +20.915374150,366.387 +20.921179138,365.472 +20.926984127,365.368 +20.932789116,365.525 +20.938594104,365.59 +20.944399093,365.543 +20.950204082,365.042 +20.956009070,364.328 +20.961814059,363.849 +20.967619048,363.149 +20.973424036,362.793 +20.979229025,362.518 +20.985034014,362.07 +20.990839002,361.869 +20.996643991,361.264 +21.002448980,360.832 +21.008253968,361.087 +21.014058957,362.131 +21.019863946,363.619 +21.025668934,365.433 +21.031473923,366.76 +21.037278912,367.197 +21.043083900,367.625 +21.048888889,367.806 +21.054693878,368.551 +21.060498866,370.171 +21.066303855,371.03 +21.072108844,371.204 +21.077913832,370.034 +21.083718821,364.906 +21.281088435,282.424 +21.286893424,286.808 +21.292698413,293.033 +21.298503401,295.685 +21.304308390,295.739 +21.310113379,295.262 +21.315918367,294.21 +21.321723356,292.762 +21.327528345,291.952 +21.333333333,291.464 +21.339138322,291.208 +21.344943311,291.34 +21.350748299,291.135 +21.356553288,290.852 +21.362358277,290.479 +21.368163265,289.78 +21.373968254,288.896 +21.379773243,288.037 +21.385578231,287.421 +21.391383220,287.204 +21.397188209,287.496 +21.402993197,288.061 +21.408798186,289.034 +21.414603175,290.296 +21.420408163,291.256 +21.426213152,292.384 +21.432018141,293.047 +21.437823129,293.395 +21.443628118,293.73 +21.449433107,293.876 +21.455238095,294.091 +21.461043084,294.479 +21.466848073,294.885 +21.472653061,295.106 +21.478458050,295.313 +21.484263039,295.381 +21.490068027,295.217 +21.495873016,295.052 +21.501678005,294.358 +21.507482993,293.341 +21.513287982,292.222 +21.519092971,291.326 +21.524897959,290.004 +21.530702948,288.725 +21.536507937,289.641 +21.542312925,283 +21.548117914,277.931 +21.553922902,279.158 +21.559727891,284.425 +21.565532880,291.009 +21.571337868,295.385 +21.577142857,302.913 +21.582947846,316.64 +21.588752834,324.049 +21.594557823,327.304 +21.600362812,330.633 +21.606167800,333.864 +21.611972789,337.15 +21.617777778,339.401 +21.623582766,340.619 +21.629387755,341.251 +21.635192744,341.392 +21.640997732,341.45 +21.646802721,341.72 +21.652607710,341.788 +21.658412698,341.477 +21.664217687,340.681 +21.670022676,339.749 +21.675827664,338.695 +21.681632653,337.826 +21.687437642,336.423 +21.693242630,334.661 +21.699047619,332.101 +21.704852608,327.872 +21.710657596,324.636 +21.716462585,319.413 +21.722267574,314.63 +21.728072562,309.794 +21.733877551,306.119 +21.739682540,302.626 +21.745487528,300.193 +21.751292517,299.887 +21.757097506,300.574 +21.762902494,302.928 +21.768707483,306.149 +21.774512472,308.753 +21.780317460,311.998 +21.786122449,315.349 +21.791927438,319.466 +21.797732426,325.084 +21.803537415,328.685 +21.809342404,331.115 +21.815147392,332.64 +21.820952381,334.454 +21.826757370,336.068 +21.832562358,337.042 +21.838367347,337.709 +21.844172336,338.146 +21.849977324,339.108 +21.855782313,340.322 +21.861587302,342.702 +21.867392290,345.498 +21.873197279,348.562 +21.879002268,351.427 +21.884807256,353.431 +21.890612245,355.362 +21.896417234,356.818 +21.902222222,358.679 +21.908027211,360.373 +21.913832200,362.309 +21.919637188,363.882 +21.925442177,364.673 +21.931247166,365.064 +21.937052154,365.136 +21.942857143,365.367 +21.948662132,366.387 +21.954467120,368.008 +21.960272109,369.755 +21.966077098,370.878 +21.971882086,370.831 +21.977687075,369.441 +21.983492063,366.436 +21.989297052,361.358 +21.995102041,355.12 +22.000907029,349.264 +22.006712018,341.67 +22.012517007,331.527 +22.018321995,323.7 +22.024126984,315.769 +22.029931973,309.563 +22.035736961,304.076 +22.041541950,301.596 +22.047346939,301.492 +22.053151927,302.523 +22.058956916,305.387 +22.064761905,309.655 +22.070566893,315.598 +22.076371882,321.364 +22.082176871,329.027 +22.087981859,337.008 +22.093786848,343.715 +22.099591837,348.799 +22.105396825,352.647 +22.111201814,355.78 +22.117006803,358.234 +22.122811791,360.243 +22.128616780,361.781 +22.134421769,362.959 +22.140226757,363.782 +22.146031746,364.22 +22.151836735,364.386 +22.157641723,364.151 +22.163446712,363.244 +22.169251701,361.567 +22.175056689,359.338 +22.180861678,356.451 +22.186666667,353.458 +22.192471655,350.194 +22.198276644,346.817 +22.204081633,343.493 +22.209886621,340.241 +22.215691610,336.706 +22.221496599,333.117 +22.227301587,329.98 +22.233106576,327.848 +22.238911565,326.421 +22.244716553,325.559 +22.250521542,325.78 +22.256326531,326.233 +22.262131519,326.946 +22.267936508,327.763 +22.273741497,328.771 +22.279546485,330.335 +22.285351474,332.105 +22.291156463,334.147 +22.296961451,335.861 +22.302766440,337.417 +22.308571429,338.669 +22.314376417,339.18 +22.320181406,339.174 +22.325986395,338.525 +22.331791383,337.031 +22.337596372,334.731 +22.343401361,331.888 +22.349206349,329.218 +22.355011338,326.931 +22.360816327,325.447 +22.366621315,324.872 +22.372426304,324.281 +22.378231293,323.595 +22.384036281,322.323 +22.389841270,319.485 +22.395646259,316.384 +22.401451247,314 +22.407256236,310.352 +22.413061224,306.285 +22.418866213,306.173 +22.778775510,232.67 +22.784580499,243.853 +22.790385488,256.849 +22.796190476,267.221 +22.801995465,272.096 +22.807800454,276.426 +22.813605442,280.008 +22.819410431,282.336 +22.825215420,285.052 +22.831020408,286.988 +22.836825397,287.574 +22.842630385,286.904 +22.848435374,285.847 +22.854240363,283.842 +22.860045351,281.315 +22.865850340,278.563 +22.871655329,276.194 +22.877460317,274.736 +22.883265306,273.824 +22.889070295,273.762 +22.894875283,273.803 +22.900680272,274.094 +22.906485261,274.335 +22.912290249,275.104 +22.918095238,275.872 +22.923900227,276.688 +22.929705215,277.356 +22.935510204,277.896 +22.941315193,278.71 +22.947120181,279.197 +22.952925170,279.561 +22.958730159,279.463 +22.964535147,278.837 +22.970340136,277.81 +22.976145125,276.659 +22.981950113,274.53 +22.987755102,271.813 +22.993560091,270.653 +22.999365079,269.23 +23.005170068,268.249 +23.010975057,267.04 +23.016780045,265.905 +23.022585034,264.85 +23.028390023,264.235 +23.034195011,264.137 +23.040000000,264.905 +23.045804989,265.829 +23.051609977,266.533 +23.057414966,266.749 +23.063219955,267.806 +23.069024943,268.89 +23.074829932,269.998 +23.080634921,271.185 +23.086439909,272.32 +23.092244898,272.067 +23.098049887,270.819 +23.103854875,267.8 +23.109659864,264.46 +23.115464853,262.715 +23.121269841,261.098 +23.127074830,255.885 +23.132879819,249.346 +23.138684807,243.572 +23.144489796,236.482 +23.260589569,275.143 +23.266394558,278.761 +23.272199546,288.182 +23.278004535,296.866 +23.283809524,301.338 +23.289614512,303.661 +23.295419501,308.023 +23.301224490,317.787 +23.307029478,328.815 +23.312834467,333.651 +23.318639456,336.699 +23.324444444,339.149 +23.330249433,341.558 +23.336054422,343.332 +23.341859410,344.633 +23.347664399,345.106 +23.353469388,344.751 +23.359274376,343.764 +23.365079365,342.344 +23.370884354,341.429 +23.376689342,340.769 +23.382494331,340.488 +23.388299320,340.12 +23.394104308,339.771 +23.399909297,339.239 +23.405714286,338.725 +23.411519274,338.365 +23.417324263,337.795 +23.423129252,337.165 +23.428934240,336.534 +23.434739229,335.505 +23.440544218,334.643 +23.446349206,333.823 +23.452154195,333.278 +23.457959184,333.368 +23.463764172,333.735 +23.469569161,334.183 +23.475374150,334.778 +23.481179138,334.891 +23.486984127,334.949 +23.492789116,334.692 +23.498594104,334.226 +23.504399093,333.556 +23.510204082,332.405 +23.516009070,331.408 +23.521814059,330.366 +23.527619048,329.957 +23.533424036,329.85 +23.539229025,330.18 +23.545034014,330.365 +23.550839002,330.487 +23.556643991,330.418 +23.562448980,330.098 +23.568253968,329.74 +23.574058957,329.407 +23.579863946,329.306 +23.585668934,329.332 +23.591473923,329.756 +23.597278912,329.862 +23.603083900,330.361 +23.608888889,330.961 +23.614693878,331.381 +23.620498866,332.093 +23.626303855,332.288 +23.632108844,332.055 +23.637913832,331.449 +23.643718821,330.795 +23.649523810,329.804 +23.655328798,329.38 +23.661133787,328.947 +23.666938776,328.57 +23.672743764,328.261 +23.678548753,326.727 +23.684353741,324.722 +23.690158730,322.532 +23.695963719,319.268 +23.701768707,315.793 +23.707573696,315.241 +23.713378685,313.855 +23.719183673,300.88 +23.724988662,287.878 +23.730793651,281.151 +23.736598639,278.967 +23.742403628,276.812 +23.748208617,276.038 +23.754013605,275.002 +23.759818594,274.174 +23.765623583,273.488 +23.771428571,272.75 +23.777233560,272.277 +23.783038549,271.975 +23.788843537,271.7 +23.794648526,271.424 +23.800453515,271.316 +23.806258503,271.204 +23.812063492,271.08 +23.817868481,271.143 +23.823673469,271.162 +23.829478458,271.142 +23.835283447,271.465 +23.841088435,271.781 +23.846893424,271.817 +23.852698413,271.223 +23.858503401,269.163 +23.864308390,266.764 +23.870113379,265.276 +23.875918367,264.214 +23.881723356,263.538 +23.887528345,261.816 +23.893333333,260.357 +24.026848073,305.96 +24.032653061,306.329 +24.038458050,310.138 +24.044263039,313.398 +24.050068027,322.231 +24.055873016,327.069 +24.061678005,327.956 +24.067482993,328.096 +24.073287982,327.602 +24.079092971,325.947 +24.084897959,325.879 +24.090702948,325.825 +24.096507937,325.975 +24.102312925,325.678 +24.108117914,325.375 +24.113922902,325.171 +24.119727891,324.944 +24.125532880,325.238 +24.131337868,325.65 +24.137142857,326.366 +24.142947846,327.512 +24.148752834,328.696 +24.154557823,329.97 +24.160362812,331.25 +24.166167800,332.388 +24.171972789,333.089 +24.177777778,333.557 +24.183582766,333.769 +24.189387755,333.749 +24.195192744,333.618 +24.200997732,333.448 +24.206802721,333.561 +24.212607710,333.499 +24.218412698,333.56 +24.224217687,333.672 +24.230022676,333.237 +24.235827664,332.446 +24.241632653,331.086 +24.247437642,329.56 +24.253242630,328.431 +24.259047619,327.894 +24.264852608,327.765 +24.270657596,327.756 +24.276462585,327.97 +24.282267574,328.486 +24.288072562,328.854 +24.293877551,329.346 +24.299682540,330.002 +24.305487528,330.51 +24.311292517,331.506 +24.317097506,332.242 +24.322902494,333.014 +24.328707483,333.635 +24.334512472,334.36 +24.340317460,334.911 +24.346122449,334.758 +24.351927438,333.657 +24.497052154,335.302 +24.502857143,340.811 +24.508662132,341.814 +24.514467120,341.494 +24.520272109,340.418 +24.526077098,338.63 +24.531882086,336.918 +24.537687075,336.49 +24.543492063,337.545 +24.549297052,339.141 +24.555102041,341.432 +24.560907029,343.433 +24.566712018,344.335 +24.572517007,344.797 +24.578321995,344.318 +24.584126984,343.874 +24.589931973,344.663 +24.595736961,346.187 +24.601541950,348.065 +24.607346939,350.364 +24.613151927,353.298 +24.618956916,355.913 +24.624761905,358.882 +24.630566893,361.445 +24.636371882,364.38 +24.642176871,367.619 +24.647981859,370.623 +24.653786848,373.308 +24.659591837,374.922 +24.665396825,375.376 +24.671201814,374.81 +24.677006803,373.333 +24.682811791,371.891 +24.688616780,371.301 +24.694421769,371.781 +24.700226757,372.466 +24.706031746,373.204 +24.711836735,373.791 +24.717641723,373.804 +24.723446712,373.686 +24.729251701,373.308 +24.735056689,372.889 +24.740861678,372.899 +24.746666667,374.637 +24.752471655,375.712 +24.758276644,376.33 +24.764081633,377.095 +24.769886621,374.279 +24.775691610,373.251 +24.781496599,372.224 +24.787301587,368.601 +28.189024943,194.139 +28.194829932,199.512 +28.200634921,204.62 +28.206439909,207.386 +28.212244898,210.65 +28.218049887,213.713 +28.223854875,218.687 +28.229659864,221.574 +28.235464853,223.454 +28.241269841,224.653 +28.247074830,225.423 +28.252879819,225.492 +28.258684807,225.365 +28.264489796,224.932 +28.270294785,224.176 +28.276099773,223.266 +28.281904762,221.997 +28.287709751,221.026 +28.293514739,220.661 +28.299319728,220.758 +28.305124717,220.969 +28.310929705,221.062 +28.316734694,220.878 +28.322539683,220.325 +28.328344671,219.79 +28.334149660,219.18 +28.339954649,218.666 +28.345759637,217.819 +28.351564626,217.267 +28.357369615,216.861 +28.363174603,216.811 +28.368979592,216.878 +28.374784580,217.131 +28.380589569,217.403 +28.386394558,217.47 +28.392199546,217.582 +28.398004535,217.583 +28.403809524,217.46 +28.409614512,217.439 +28.415419501,217.354 +28.421224490,217.125 +28.427029478,216.476 +28.432834467,208.5 +28.438639456,203.124 +28.444444444,207.906 +28.612789116,174.999 +28.618594104,174.051 +28.624399093,176.939 +28.630204082,181.398 +28.636009070,190.397 +28.641814059,199.082 +28.647619048,205.219 +28.653424036,213.116 +28.659229025,221.496 +28.665034014,230.233 +28.670839002,241.834 +28.676643991,246.701 +28.682448980,248.587 +28.688253968,250.798 +28.694058957,252.771 +28.699863946,255.587 +28.705668934,256.508 +28.711473923,256.876 +28.717278912,256.513 +28.723083900,255.331 +28.728888889,254.54 +28.734693878,253.181 +28.740498866,252.09 +28.746303855,250.575 +28.752108844,249.206 +28.757913832,247.619 +28.763718821,246.559 +28.769523810,245.719 +28.775328798,245.049 +28.781133787,244.492 +28.786938776,243.625 +28.792743764,242.839 +28.798548753,242.222 +28.804353741,242.178 +28.810158730,242.397 +28.815963719,242.756 +28.821768707,242.841 +28.827573696,242.75 +28.833378685,242.409 +28.839183673,241.983 +28.844988662,241.421 +28.850793651,240.968 +28.856598639,240.341 +28.862403628,239.731 +28.868208617,239.403 +28.874013605,239.19 +28.879818594,238.996 +28.885623583,239.172 +28.891428571,239.46 +28.897233560,240.084 +28.903038549,240.919 +28.908843537,241.928 +28.914648526,243.607 +28.920453515,245.659 +28.926258503,247.555 +28.932063492,249.09 +28.937868481,249.792 +28.943673469,249.701 +28.949478458,248.731 +28.955283447,247.393 +28.961088435,246.193 +28.966893424,244.983 +28.972698413,243.401 +28.978503401,241.633 +28.984308390,239.206 +28.990113379,236.392 +28.995918367,233.084 +29.001723356,228.052 +29.152653061,254.589 +29.158458050,261.815 +29.164263039,264.297 +29.170068027,266.726 +29.175873016,267.78 +29.181678005,269.104 +29.187482993,270.497 +29.193287982,271.86 +29.199092971,273.238 +29.204897959,274.123 +29.210702948,273.773 +29.216507937,272.945 +29.222312925,271.13 +29.228117914,270.004 +29.233922902,269.114 +29.239727891,268.824 +29.245532880,268.828 +29.251337868,268.806 +29.257142857,268.666 +29.262947846,268.593 +29.268752834,269.056 +29.274557823,269.538 +29.280362812,270.269 +29.286167800,270.953 +29.291972789,271.195 +29.297777778,271.247 +29.303582766,271.517 +29.309387755,271.54 +29.315192744,271.711 +29.320997732,272.054 +29.326802721,272.23 +29.332607710,272.789 +29.338412698,273.2 +29.344217687,273.341 +29.350022676,273.126 +29.355827664,272.935 +29.361632653,272.397 +29.367437642,272.071 +29.373242630,271.759 +29.379047619,271.556 +29.384852608,272.19 +29.390657596,272.732 +29.396462585,273.645 +29.402267574,274.475 +29.408072562,274.924 +29.413877551,274.945 +29.419682540,274.912 +29.425487528,274.584 +29.431292517,274.323 +29.437097506,274.232 +29.442902494,273.691 +29.448707483,273.756 +29.454512472,273.427 +29.460317460,273.334 +29.466122449,273.537 +29.471927438,273.18 +29.477732426,272.854 +29.483537415,272.124 +29.489342404,271.725 +29.495147392,271.091 +29.500952381,270.82 +29.506757370,270.8 +29.512562358,270.68 +29.518367347,271.176 +29.524172336,271.712 +29.529977324,272.41 +29.535782313,273.188 +29.541587302,273.571 +29.547392290,273.724 +29.553197279,273.986 +29.559002268,274.357 +29.564807256,274.921 +29.570612245,275.622 +29.576417234,276.189 +29.582222222,276.44 +29.588027211,276.126 +29.593832200,275.636 +29.599637188,273.929 +29.605442177,272.258 +29.611247166,269.706 +29.617052154,268.352 +29.622857143,265.674 +29.628662132,262.044 +29.634467120,245.926 +29.640272109,233.335 +29.646077098,230.728 +29.651882086,226.938 +29.657687075,231.293 +29.663492063,233.804 +29.669297052,239.609 +29.675102041,243.35 +29.680907029,243.996 +29.686712018,244.266 +29.692517007,244.441 +29.698321995,244.485 +29.704126984,244.666 +29.709931973,244.808 +29.715736961,245.058 +29.721541950,245.116 +29.727346939,244.924 +29.733151927,244.738 +29.738956916,244.652 +29.744761905,244.691 +29.750566893,244.912 +29.756371882,245.076 +29.762176871,244.926 +29.767981859,244.52 +29.773786848,244.011 +29.779591837,243.418 +29.785396825,242.979 +29.791201814,242.698 +29.797006803,242.481 +29.802811791,242.707 +29.808616780,242.916 +29.814421769,242.992 +29.820226757,243.07 +29.826031746,242.729 +29.831836735,242.292 +29.837641723,241.136 +29.843446712,239.586 +29.849251701,228.968 +29.855056689,216.611 +29.860861678,215.107 +29.866666667,205.945 +29.872471655,201.028 +29.878276644,194.362 +29.884081633,185.038 +29.889886621,181.69 +29.936326531,211.574 +29.942131519,219.196 +29.947936508,222.78 +29.953741497,222.785 +29.959546485,222.41 +29.965351474,221.785 +29.971156463,220.048 +29.976961451,218.941 +29.982766440,218.586 +29.988571429,218.407 +29.994376417,218.137 +30.000181406,218.044 +30.005986395,217.965 +30.011791383,217.983 +30.017596372,217.71 +30.023401361,217.284 +30.029206349,216.767 +30.035011338,216.269 +30.040816327,216.079 +30.046621315,216.289 +30.052426304,216.831 +30.058231293,217.829 +30.064036281,219.136 +30.069841270,219.679 +30.075646259,220.342 +30.081451247,220.906 +30.087256236,221.677 +30.093061224,222.057 +30.098866213,222.321 +30.104671202,222.664 +30.110476190,222.795 +30.116281179,222.409 +30.122086168,221.407 +30.127891156,219.778 +30.133696145,218.568 +30.139501134,217.329 +30.145306122,215.854 +30.151111111,215.012 +30.156916100,214.669 +30.162721088,214.153 +30.168526077,213.547 +30.174331066,212.827 +30.180136054,211.731 +30.185941043,210.946 +30.191746032,210.896 +30.197551020,212.897 +30.203356009,217.789 +30.209160998,223.763 +30.214965986,226.206 +30.220770975,227.756 +30.226575964,228.853 +30.232380952,229.904 +30.238185941,230.836 +30.243990930,231.327 +30.249795918,231.756 +30.255600907,231.971 +30.261405896,232.512 +30.267210884,232.718 +30.273015873,232.796 +30.278820862,231.963 +30.284625850,229.827 +30.296235828,208.886 +30.302040816,208.446 +30.307845805,203.83 +30.313650794,206.89 +30.319455782,205.164 +30.325260771,203.286 +30.331065760,199.942 +30.336870748,195.572 +30.342675737,191.326 +30.621315193,207.787 +30.627120181,217.056 +30.632925170,227.393 +30.638730159,238.688 +30.644535147,245.051 +30.650340136,249.167 +30.656145125,254.557 +30.661950113,262.199 +30.667755102,266.88 +30.673560091,269.674 +30.679365079,271.606 +30.685170068,272.821 +30.690975057,273.816 +30.696780045,274.766 +30.702585034,275.427 +30.708390023,275.61 +30.714195011,275.603 +30.720000000,274.816 +30.725804989,274.121 +30.731609977,273.223 +30.737414966,272.488 +30.743219955,272.208 +30.749024943,272.416 +30.754829932,272.929 +30.760634921,273.935 +30.766439909,275.338 +30.772244898,276.505 +30.778049887,277.842 +30.783854875,278.271 +30.789659864,278.614 +30.795464853,277.945 +30.801269841,277.096 +30.807074830,275.847 +30.812879819,274.237 +30.818684807,272.167 +30.824489796,270.093 +30.830294785,268.758 +30.836099773,267.841 +30.841904762,267.503 +30.847709751,267.387 +30.853514739,267.547 +30.859319728,267.388 +30.865124717,267.709 +30.870929705,268.445 +30.876734694,269.442 +30.882539683,270.176 +30.888344671,270.985 +30.894149660,272.034 +30.899954649,273.223 +30.905759637,274.466 +30.911564626,275.788 +30.917369615,276.231 +30.923174603,276.37 +30.928979592,276.282 +30.934784580,275.752 +30.940589569,274.433 +30.946394558,271.557 +30.952199546,268.495 +30.958004535,265.571 +30.963809524,261.599 +30.969614512,247.933 +30.975419501,241.67 +30.981224490,234.355 +31.108934240,285.607 +31.114739229,289.077 +31.120544218,294.435 +31.126349206,300.824 +31.132154195,306.84 +31.137959184,311.593 +31.143764172,315.147 +31.149569161,318.785 +31.155374150,322.57 +31.161179138,326.368 +31.166984127,329.67 +31.172789116,332.109 +31.178594104,333.91 +31.184399093,335.106 +31.190204082,335.491 +31.196009070,335.299 +31.201814059,334.474 +31.207619048,333.155 +31.213424036,331.724 +31.219229025,330.665 +31.225034014,329.915 +31.230839002,329.762 +31.236643991,330.163 +31.242448980,330.474 +31.248253968,331.514 +31.254058957,332.292 +31.259863946,333 +31.265668934,333.611 +31.271473923,333.709 +31.277278912,333.428 +31.283083900,332.655 +31.288888889,331.667 +31.294693878,330.588 +31.300498866,329.687 +31.306303855,328.88 +31.312108844,328.23 +31.317913832,327.58 +31.323718821,326.923 +31.329523810,326.388 +31.335328798,326.084 +31.341133787,326.225 +31.346938776,326.872 +31.352743764,327.67 +31.358548753,328.437 +31.364353741,329.014 +31.370158730,329.245 +31.375963719,329.427 +31.381768707,329.651 +31.387573696,329.747 +31.393378685,329.767 +31.399183673,329.879 +31.404988662,329.819 +31.410793651,329.774 +31.416598639,329.519 +31.422403628,328.914 +31.428208617,328.405 +31.434013605,327.757 +31.439818594,327.596 +31.445623583,327.96 +31.451428571,328.865 +31.457233560,330.021 +31.463038549,331.307 +31.468843537,332.501 +31.474648526,333.428 +31.480453515,334.229 +31.486258503,334.687 +31.492063492,335.191 +31.497868481,335.603 +31.503673469,335.973 +31.509478458,336.06 +31.515283447,335.967 +31.521088435,335.413 +31.526893424,333.956 +31.532698413,332.133 +31.538503401,329.739 +31.544308390,326.741 +31.550113379,323.854 +31.555918367,321.407 +31.561723356,319.839 +31.567528345,320.234 +31.573333333,321.326 +31.579138322,320.963 +31.584943311,316.826 +31.590748299,306.082 +31.596553288,303.14 +31.602358277,299.431 +31.608163265,295.266 +31.613968254,290.293 +31.619773243,286.809 +31.625578231,284.518 +31.631383220,282.141 +31.637188209,280.669 +31.642993197,279.616 +31.648798186,279.696 +31.654603175,279.781 +31.660408163,279.714 +31.666213152,279.364 +31.672018141,278.536 +31.677823129,277.568 +31.683628118,276.595 +31.689433107,275.885 +31.695238095,275.193 +31.701043084,274.21 +31.706848073,273.529 +31.712653061,270.498 +31.718458050,261.813 +31.910022676,277.592 +31.915827664,283.08 +31.921632653,289.024 +31.927437642,293.826 +31.933242630,297.571 +31.939047619,301.58 +31.944852608,307.15 +31.950657596,313.86 +31.956462585,320.425 +31.962267574,325.498 +31.968072562,329.343 +31.973877551,332.309 +31.979682540,334.352 +31.985487528,335.921 +31.991292517,336.878 +31.997097506,336.98 +32.002902494,336.414 +32.008707483,335.263 +32.014512472,334.038 +32.020317460,332.645 +32.026122449,331.769 +32.031927438,331.184 +32.037732426,330.451 +32.043537415,329.961 +32.049342404,329.296 +32.055147392,329.213 +32.060952381,329.249 +32.066757370,329.541 +32.072562358,329.948 +32.078367347,330.421 +32.084172336,330.838 +32.089977324,331.458 +32.095782313,332.094 +32.101587302,332.167 +32.107392290,332.514 +32.113197279,332.641 +32.119002268,332.714 +32.124807256,333.478 +32.130612245,334.027 +32.136417234,334.517 +32.142222222,334.831 +32.148027211,334.495 +32.153832200,333.86 +32.159637188,333.079 +32.165442177,332.024 +32.171247166,331.148 +32.177052154,330.187 +32.182857143,329.626 +32.188662132,329.45 +32.194467120,329.199 +32.200272109,329.14 +32.206077098,328.51 +32.211882086,327.876 +32.217687075,327.797 +32.223492063,327.484 +32.229297052,327.745 +32.235102041,328.115 +32.240907029,326.59 +32.246712018,325.576 +32.252517007,323.817 +32.258321995,322.849 +32.264126984,323.55 +32.269931973,323.984 +32.275736961,325.328 +32.281541950,326.284 +32.287346939,327.192 +32.293151927,328.737 +32.298956916,330.114 +32.304761905,331.393 +32.310566893,332.932 +32.316371882,333.954 +32.322176871,334.405 +32.327981859,334.277 +32.333786848,333.627 +32.339591837,333.058 +32.345396825,332.622 +32.351201814,333.337 +32.357006803,334.022 +32.362811791,334.724 +32.368616780,335.42 +32.374421769,335.485 +32.380226757,335.626 +32.386031746,335.528 +32.391836735,335.561 +32.397641723,335.791 +32.403446712,335.884 +32.409251701,335.647 +32.415056689,335.134 +32.420861678,334.241 +32.426666667,333.233 +32.432471655,332.365 +32.438276644,332.109 +32.444081633,332.803 +32.449886621,333.895 +32.455691610,335.239 +32.461496599,336.702 +32.467301587,338.322 +32.473106576,340.084 +32.478911565,342.286 +32.484716553,344.69 +32.490521542,347.452 +32.496326531,350.363 +32.502131519,353.285 +32.507936508,355.934 +32.513741497,358.206 +32.519546485,360.061 +32.525351474,361.529 +32.531156463,362.759 +32.536961451,363.911 +32.542766440,365.197 +32.548571429,366.562 +32.554376417,367.726 +32.560181406,368.987 +32.565986395,369.674 +32.571791383,370.274 +32.577596372,370.103 +32.583401361,369.648 +32.589206349,368.82 +32.595011338,367.737 +32.600816327,366.83 +32.606621315,365.563 +32.612426304,364.998 +32.618231293,364.817 +32.624036281,364.922 +32.629841270,365.239 +32.635646259,365.022 +32.641451247,364.391 +32.647256236,364.118 +32.653061224,364.036 +32.658866213,364.35 +32.664671202,365.101 +32.670476190,365.174 +32.676281179,364.462 +32.682086168,363.74 +32.687891156,362.837 +32.693696145,361.77 +32.699501134,361.283 +32.705306122,360.66 +32.711111111,360.044 +32.716916100,359.394 +32.722721088,359.174 +32.728526077,359.014 +32.734331066,359.598 +32.740136054,360.543 +32.745941043,361.648 +32.751746032,362.336 +32.757551020,362.543 +32.763356009,362.714 +32.769160998,362.63 +32.774965986,362.791 +32.780770975,362.905 +32.786575964,363.186 +32.792380952,363.585 +32.798185941,364.105 +32.803990930,365.209 +32.809795918,366.703 +32.815600907,367.952 +32.821405896,369.06 +32.827210884,369.317 +32.833015873,368.605 +32.838820862,367.214 +32.844625850,364.39 +32.850430839,364.967 +32.856235828,370.084 +32.862040816,371.276 +32.867845805,373.233 +32.873650794,376.245 +32.879455782,378.4 +32.885260771,382.408 +32.891065760,385.605 +32.896870748,382.019 +32.902675737,379.946 +32.908480726,372.46 +32.914285714,366.681 +32.920090703,362.08 +32.925895692,358.474 +32.931700680,361.644 +32.937505669,358.746 +32.943310658,357.92 +32.949115646,358.519 +32.954920635,351.794 +32.960725624,338.406 +32.966530612,336.864 +32.972335601,329.17 +33.262585034,239.473 +33.268390023,240.884 +33.274195011,240.153 +33.280000000,239.057 +33.285804989,236.239 +33.291609977,232.634 +33.297414966,225.037 +33.303219955,217.578 +33.309024943,214.428 +33.314829932,212.598 +33.320634921,210.952 +33.326439909,209.303 +33.332244898,208.213 +33.338049887,208.222 +33.343854875,208.877 +33.349659864,210.436 +33.355464853,212.333 +33.361269841,213.458 +33.367074830,214.728 +33.372879819,215.949 +33.378684807,217.711 +33.384489796,219.43 +33.390294785,220.458 +33.396099773,221.237 +33.401904762,221.624 +33.407709751,221.191 +33.413514739,220.664 +33.419319728,219.86 +33.425124717,218.973 +33.430929705,218.454 +33.436734694,217.902 +33.442539683,217.116 +33.448344671,217.003 +33.454149660,217.188 +33.459954649,217.546 +33.465759637,218.686 +33.471564626,219.509 +33.477369615,220.111 +33.483174603,220.236 +33.488979592,220.451 +33.494784580,220.523 +33.500589569,220.166 +33.506394558,219.577 +33.512199546,218.372 +33.518004535,217.117 +33.523809524,216.577 +33.529614512,215.691 +33.535419501,215.162 +33.541224490,215.404 +33.547029478,214.352 +33.552834467,215.334 +33.558639456,217.769 +33.564444444,219.82 +33.570249433,223.964 +33.576054422,228.108 +33.581859410,230.932 +33.587664399,232.462 +33.593469388,233.75 +33.599274376,235.514 +33.605079365,237.24 +33.610884354,237.976 +33.616689342,237.907 +33.622494331,237.644 +33.628299320,235.46 +33.634104308,234.071 +33.639909297,231.831 +33.645714286,228.802 +33.651519274,226.947 +33.657324263,222.491 +33.663129252,219.281 +33.668934240,216.188 +33.674739229,213.176 +33.680544218,210.804 +33.686349206,210.205 +33.692154195,210.656 +35.863219955,204.864 +35.869024943,212.295 +35.874829932,217.853 +35.880634921,222.936 +35.886439909,226.771 +35.892244898,229.422 +35.898049887,231.727 +35.903854875,233.789 +35.909659864,235.561 +35.915464853,237.39 +35.921269841,239.126 +35.927074830,240.514 +35.932879819,241.632 +35.938684807,242.558 +35.944489796,243.109 +35.950294785,243.255 +35.956099773,242.818 +35.961904762,242.235 +35.967709751,241.548 +35.973514739,240.607 +35.979319728,239.231 +35.985124717,237.2 +35.990929705,234.783 +35.996734694,232.697 +36.002539683,231.483 +36.008344671,229.694 +36.014149660,226.308 +36.141859410,335.058 +36.147664399,353.591 +36.153469388,365.658 +36.159274376,366.25 +36.165079365,366.292 +36.170884354,365.046 +36.176689342,364.335 +36.182494331,364.921 +36.188299320,366.552 +36.194104308,367.687 +36.199909297,368.716 +36.205714286,370.189 +36.211519274,370.059 +36.217324263,369.644 +36.223129252,369.229 +36.228934240,367.942 +36.234739229,366.857 +36.240544218,366.096 +36.246349206,365.882 +36.252154195,365.377 +36.257959184,365.804 +36.263764172,366.119 +36.269569161,366.008 +36.275374150,366.19 +36.281179138,365.33 +36.286984127,364.211 +36.292789116,363.227 +36.298594104,362.959 +36.304399093,363.062 +36.310204082,363.32 +36.316009070,363.924 +36.321814059,364.39 +36.327619048,364.574 +36.333424036,364.985 +36.339229025,364.535 +36.345034014,363.301 +36.350839002,361.48 +36.356643991,359.708 +36.362448980,357.947 +36.368253968,354.625 +36.374058957,351.434 +36.530793651,347.25 +36.536598639,348.693 +36.542403628,363.036 +36.548208617,370.631 +36.554013605,373.77 +36.559818594,375.332 +36.565623583,376.664 +36.571428571,377.857 +36.577233560,377.893 +36.583038549,377.068 +36.588843537,376.163 +36.594648526,374.026 +36.600453515,371.576 +36.606258503,369.849 +36.612063492,368.451 +36.617868481,367.601 +36.623673469,366.826 +36.629478458,365.905 +36.635283447,364.973 +36.641088435,364.045 +36.646893424,363.367 +36.652698413,362.918 +36.658503401,363.345 +36.664308390,364.014 +36.670113379,364.852 +36.675918367,365.765 +36.681723356,365.84 +36.687528345,365.25 +36.693333333,364.5 +36.699138322,363.616 +36.704943311,362.707 +36.710748299,362.49 +36.716553288,362.597 +36.722358277,363.24 +36.728163265,364.224 +36.733968254,365.235 +36.739773243,366.093 +36.745578231,366.796 +36.751383220,367.54 +36.757188209,368.136 +36.762993197,368.574 +36.768798186,369.1 +36.774603175,369.642 +36.780408163,370.309 +36.786213152,370.879 +36.792018141,371.356 +36.797823129,371.651 +36.803628118,371.737 +36.809433107,371.821 +36.815238095,371.732 +36.821043084,371.6 +36.826848073,371.606 +36.832653061,371.59 +36.838458050,371.205 +36.844263039,370.873 +36.850068027,369.45 +36.855873016,366.935 +36.861678005,364.712 +36.867482993,362.147 +36.873287982,359.575 +36.879092971,357.524 +36.884897959,357.712 +36.890702948,352.446 +36.896507937,348.325 +36.902312925,348.853 +36.908117914,352.504 +36.913922902,349.872 +36.919727891,346.829 +36.925532880,341.431 +36.931337868,330.99 +36.937142857,324.188 +36.942947846,315.571 +36.948752834,309.48 +36.954557823,300.847 +36.960362812,293.057 +36.966167800,281.494 +36.971972789,278.274 +36.977777778,273.127 +36.983582766,267.688 +36.989387755,267.699 +36.995192744,275.722 +37.000997732,284.697 +37.006802721,288.282 +37.012607710,297.072 +37.018412698,306.361 +37.024217687,312.212 +37.030022676,311.765 +37.035827664,320.585 +37.041632653,325.996 +37.047437642,330.706 +37.053242630,334.568 +37.059047619,338.213 +37.064852608,338.816 +37.070657596,338.936 +37.076462585,339.141 +37.082267574,338.457 +37.088072562,337.922 +37.093877551,337.664 +37.099682540,337.299 +37.105487528,337.386 +37.111292517,338.08 +37.117097506,338.857 +37.122902494,339.744 +37.128707483,340.865 +37.134512472,341.994 +37.140317460,343.444 +37.146122449,344.708 +37.151927438,345.913 +37.157732426,347.328 +37.163537415,349.296 +37.169342404,351.262 +37.175147392,353.476 +37.180952381,355.273 +37.186757370,357.064 +37.192562358,359.398 +37.198367347,360.889 +37.204172336,363.338 +37.209977324,364.472 +37.215782313,365.611 +37.221587302,366.595 +37.227392290,366.486 +37.233197279,366.263 +37.239002268,365.819 +37.244807256,365 +37.250612245,364.427 +37.256417234,364.43 +37.262222222,363.704 +37.268027211,363.426 +37.273832200,363.183 +37.279637188,363.066 +37.285442177,362.399 +37.291247166,363.183 +37.297052154,363.338 +37.302857143,362.755 +37.308662132,363.69 +37.314467120,362.443 +37.320272109,362.165 +37.326077098,362.629 +37.331882086,362.543 +37.337687075,363.535 +37.343492063,364.052 +37.349297052,364.317 +37.355102041,364.611 +37.360907029,364.93 +37.366712018,364.891 +37.372517007,364.876 +37.378321995,365.193 +37.384126984,365.332 +37.389931973,365.452 +37.395736961,365.826 +37.401541950,365.848 +37.407346939,365.583 +37.413151927,365.594 +37.418956916,365.561 +37.424761905,364.956 +37.430566893,364.36 +37.436371882,363.88 +37.442176871,363.212 +37.447981859,363.505 +37.453786848,362.675 +37.459591837,360.372 +37.465396825,358.72 +37.471201814,356.343 +37.477006803,352.138 +37.482811791,351.273 +37.488616780,351.415 +37.494421769,345.419 +37.500226757,360.741 +37.506031746,362.804 +37.511836735,363.742 +37.517641723,366.731 +37.523446712,368.464 +37.529251701,370.494 +37.535056689,371.414 +37.540861678,371.216 +37.546666667,371.224 +37.552471655,370.51 +37.558276644,370.031 +37.564081633,369.22 +37.569886621,368.416 +37.575691610,368.109 +37.581496599,367.64 +37.587301587,367.651 +37.593106576,367.29 +37.598911565,367.296 +37.604716553,367.126 +37.610521542,367.279 +37.616326531,367.746 +37.622131519,368.351 +37.627936508,369.403 +37.633741497,370.585 +37.639546485,371.546 +37.645351474,372.225 +37.651156463,372.963 +37.656961451,372.191 +37.662766440,371.435 +37.668571429,370.57 +37.790476190,334.679 +37.796281179,331.407 +37.802086168,333.024 +37.807891156,335.958 +37.813696145,337.132 +37.819501134,338.266 +37.825306122,339.929 +37.831111111,340.275 +37.836916100,339.636 +37.842721088,338.994 +37.848526077,337.513 +37.854331066,336.068 +37.860136054,335.311 +37.865941043,334.256 +37.871746032,333.135 +37.877551020,331.462 +37.883356009,329.846 +37.889160998,328.671 +37.894965986,328.254 +37.900770975,328.424 +37.906575964,328.487 +37.912380952,328.547 +37.918185941,328.384 +37.923990930,327.977 +37.929795918,327.415 +37.935600907,326.957 +37.941405896,326.646 +37.947210884,326.392 +37.953015873,326.579 +37.958820862,326.777 +37.964625850,327.287 +37.970430839,327.516 +37.976235828,327.472 +37.982040816,327.354 +37.987845805,326.673 +37.993650794,325.684 +37.999455782,324.188 +38.005260771,321.965 +38.011065760,319.255 +38.016870748,315.759 +38.022675737,311.686 +38.028480726,306.802 +38.034285714,302.193 +38.040090703,298.125 +38.045895692,294.534 +38.051700680,290.899 +38.057505669,288.102 +38.063310658,286.728 +38.069115646,286.265 +38.074920635,286.818 +38.080725624,287.685 +38.086530612,288.722 +38.092335601,290.179 +38.098140590,291.594 +38.103945578,293.067 +38.109750567,294.431 +38.115555556,295.245 +38.121360544,295.478 +38.127165533,295.01 +38.132970522,294.161 +38.138775510,293.049 +38.144580499,291.759 +38.150385488,290.336 +38.156190476,288.919 +38.161995465,287.155 +38.167800454,284.971 +38.173605442,282.379 +38.179410431,279.896 +38.185215420,277.181 +38.191020408,274.12 +38.196825397,270.82 +38.202630385,267.576 +38.208435374,265.557 +38.214240363,264.543 +38.220045351,264.672 +38.225850340,265.384 +38.231655329,266.798 +38.237460317,268.631 +38.243265306,271.1 +38.249070295,273.56 +38.254875283,276.643 +38.260680272,279.216 +38.266485261,281.421 +38.272290249,283.697 +38.278095238,285.521 +38.283900227,286.624 +38.289705215,287.072 +38.295510204,286.708 +38.301315193,285.855 +38.307120181,284.513 +38.312925170,282.951 +38.318730159,281.695 +38.324535147,280.506 +38.330340136,279.212 +38.336145125,277.852 +38.341950113,276.426 +38.347755102,274.897 +38.353560091,273.56 +38.359365079,272.46 +38.365170068,271.56 +38.370975057,271.12 +38.376780045,270.854 +38.382585034,271.116 +38.388390023,271.733 +38.394195011,272.755 +38.400000000,273.922 +38.405804989,275.046 +38.411609977,276.313 +38.417414966,278.106 +38.423219955,280.208 +38.429024943,282.718 +38.434829932,284.888 +38.440634921,286.945 +38.446439909,289.57 +38.452244898,292.037 +38.458049887,295.065 +38.463854875,297.565 +38.469659864,299.123 +38.475464853,299.691 +38.481269841,299.235 +38.487074830,297.897 +38.492879819,295.805 +38.498684807,293.051 +38.504489796,289.533 +38.510294785,286.018 +38.516099773,281.925 +38.521904762,278.331 +38.527709751,275.356 +38.533514739,272.393 +38.539319728,269.692 +38.545124717,267.592 +38.550929705,266.054 +38.556734694,267.542 +38.562539683,277.866 +38.568344671,284.336 +38.574149660,288.436 +38.579954649,291.68 +38.585759637,294.671 +38.591564626,298.232 +38.597369615,303.301 +38.603174603,305.246 +38.608979592,307.402 +38.614784580,309.02 +38.620589569,307.056 +38.626394558,310.761 +39.293968254,246.706 +39.299773243,250.272 +39.305578231,255.972 +39.311383220,261.864 +39.317188209,269.864 +39.322993197,273.127 +39.328798186,276.165 +39.334603175,279.04 +39.340408163,281.091 +39.346213152,282.512 +39.352018141,283.504 +39.357823129,283.859 +39.363628118,283.875 +39.369433107,283.324 +39.375238095,282.522 +39.381043084,281.505 +39.386848073,280.639 +39.392653061,280.29 +39.398458050,280.574 +39.404263039,281.221 +39.410068027,282.312 +39.415873016,283.676 +39.421678005,285.144 +39.427482993,285.866 +39.433287982,285.889 +39.439092971,285.644 +39.444897959,284.856 +39.450702948,284.091 +39.456507937,282.668 +39.462312925,280.95 +39.468117914,279.256 +39.473922902,276.682 +39.479727891,272.967 +39.485532880,268.555 +39.491337868,263.757 +39.497142857,261.745 +39.502947846,253.334 +39.508752834,249.443 +39.636462585,261.007 +39.642267574,271.145 +39.648072562,278.525 +39.653877551,286.428 +39.659682540,290.512 +39.665487528,292.142 +39.671292517,293.039 +39.677097506,293.725 +39.682902494,294.245 +39.688707483,294.631 +39.694512472,295.138 +39.700317460,295.529 +39.706122449,295.762 +39.711927438,295.542 +39.717732426,295.303 +39.723537415,295.118 +39.729342404,295.008 +39.735147392,295.141 +39.740952381,295.355 +39.746757370,295.593 +39.752562358,295.711 +39.758367347,295.695 +39.764172336,295.616 +39.769977324,295.489 +39.775782313,294.987 +39.781587302,294.171 +39.787392290,293.082 +39.793197279,291.026 +39.799002268,290.874 +39.949931973,370.596 +39.955736961,369.981 +39.961541950,358.121 +39.967346939,351.502 +39.973151927,346.528 +39.978956916,341.425 +39.984761905,339.071 +39.990566893,338.495 +39.996371882,336.714 +40.002176871,334.5 +40.007981859,332.514 +40.013786848,330.627 +40.019591837,329.29 +40.025396825,328.492 +40.031201814,328.026 +40.037006803,327.893 +40.042811791,327.991 +40.048616780,328.037 +40.054421769,328.049 +40.060226757,328.276 +40.066031746,328.322 +40.071836735,328.649 +40.077641723,328.88 +40.083446712,329.326 +40.089251701,329.739 +40.095056689,330.013 +40.100861678,330.635 +40.106666667,330.791 +40.112471655,331.094 +40.118276644,331.306 +40.124081633,331.484 +40.129886621,331.658 +40.135691610,331.196 +40.141496599,330.636 +40.147301587,329.99 +40.153106576,329.21 +40.158911565,328.366 +40.164716553,327.107 +40.170521542,325.085 +40.176326531,323.154 +40.182131519,320.981 +40.187936508,318.633 +40.193741497,317.878 +40.199546485,315.914 +40.205351474,309.501 +40.211156463,313.448 +40.216961451,309.536 +40.222766440,302.709 +40.228571429,296.287 +40.234376417,289.229 +40.240181406,280.464 +40.245986395,271.935 +40.251791383,265.028 +40.257596372,255.717 +40.263401361,250.674 +40.269206349,247.728 +40.275011338,247.574 +40.280816327,249.822 +40.286621315,257.449 +40.292426304,269.126 +40.298231293,273.526 +40.304036281,276.704 +40.309841270,277.803 +40.315646259,278.632 +40.321451247,278.99 +40.327256236,279.212 +40.333061224,278.993 +40.338866213,278.209 +40.344671202,277.465 +40.350476190,276.455 +40.356281179,275.636 +40.362086168,274.74 +40.367891156,273.988 +40.373696145,273.311 +40.379501134,272.873 +40.385306122,272.638 +40.391111111,272.921 +40.396916100,273.252 +40.402721088,273.667 +40.408526077,274.032 +40.414331066,274.154 +40.420136054,274.226 +40.425941043,274.513 +40.431746032,274.821 +40.437551020,275.201 +40.443356009,276.722 +40.449160998,276.747 +40.454965986,273.951 +40.460770975,271.042 +40.466575964,270.355 +40.472380952,269.59 +40.478185941,269.578 +40.483990930,269.344 +40.617505669,298.571 +40.623310658,299.062 +40.629115646,302.695 +40.634920635,303.477 +40.640725624,303.594 +40.646530612,303.578 +40.652335601,303.297 +40.658140590,302.738 +40.663945578,302.253 +40.669750567,301.834 +40.675555556,301.185 +40.681360544,300.93 +40.687165533,300.861 +40.692970522,300.465 +40.698775510,299.898 +40.704580499,298.772 +40.710385488,297.399 +40.716190476,296.378 +40.721995465,296.261 +40.727800454,296.304 +40.733605442,296.286 +40.739410431,296.226 +40.745215420,296.109 +40.751020408,291.244 +40.756825397,290.183 +40.762630385,288.72 +40.872925170,342.967 +40.878730159,339.689 +40.884535147,341.545 +40.890340136,340.997 +40.896145125,340.072 +40.901950113,338.302 +40.907755102,338.497 +40.913560091,338.479 +40.919365079,338.494 +40.925170068,338.938 +40.930975057,339.268 +40.936780045,339.374 +40.942585034,339.27 +40.948390023,338.48 +40.954195011,336.865 +40.960000000,336.477 +40.965804989,336.216 +40.971609977,335.027 +40.977414966,334.042 +40.983219955,332.697 +40.989024943,331.7 +40.994829932,330.812 +41.000634921,329.943 +41.006439909,329.19 +41.012244898,328.389 +41.018049887,327.675 +41.023854875,327.198 +41.029659864,326.737 +41.035464853,326.315 +41.041269841,325.988 +41.047074830,325.788 +41.052879819,325.873 +41.058684807,326.18 +41.064489796,326.668 +41.070294785,327.227 +41.076099773,327.687 +41.081904762,327.794 +41.087709751,327.741 +41.093514739,327.338 +41.099319728,327.037 +41.105124717,326.732 +41.110929705,326.957 +41.116734694,327.835 +41.122539683,329.557 +41.128344671,332.585 +41.134149660,334.119 +41.139954649,335.019 +41.145759637,334.32 +41.151564626,332.784 +41.157369615,333.825 +41.163174603,335.339 +41.168979592,334.277 +41.174784580,335.722 +41.180589569,319.464 +41.186394558,306.993 +41.192199546,293.89 +41.198004535,282.805 +41.203809524,270.833 +41.209614512,265.958 +41.215419501,257.563 +41.221224490,252.047 +41.227029478,248.666 +41.232834467,245.583 +41.238639456,246.461 +41.244444444,251.249 +41.250249433,259.448 +41.256054422,267.915 +41.261859410,276.343 +41.267664399,275.209 +41.273469388,279.023 +41.279274376,278.868 +41.285079365,278.625 +41.290884354,278.082 +41.296689342,277.583 +41.302494331,277.178 +41.308299320,276.722 +41.314104308,276.439 +41.319909297,276.106 +41.325714286,275.678 +41.331519274,275.324 +41.337324263,274.705 +41.343129252,274.012 +41.348934240,273.126 +41.354739229,272.246 +41.360544218,271.969 +41.366349206,272.043 +41.372154195,274.393 +41.377959184,275.932 +41.383764172,277.09 +41.389569161,278.157 +41.395374150,272.788 +41.401179138,273.441 +41.406984127,273.722 +41.412789116,274.171 +41.418594104,273.692 +41.424399093,272.598 +41.430204082,271.865 +41.436009070,270.47 +41.441814059,269.6 +41.447619048,268.408 +41.453424036,268.781 +41.604353741,278.464 +41.610158730,285.68 +41.615963719,289.842 +41.621768707,295.589 +41.627573696,298.86 +41.633378685,299.546 +41.639183673,299.71 +41.644988662,299.694 +41.650793651,298.89 +41.656598639,298.199 +41.662403628,297.721 +41.668208617,297.328 +41.674013605,297.003 +41.679818594,296.933 +41.685623583,296.968 +41.691428571,297.022 +41.697233560,297.526 +41.703038549,297.805 +41.708843537,297.849 +41.714648526,298.143 +41.720453515,298.131 +41.726258503,298.023 +41.732063492,297.858 +41.737868481,293.379 +41.894603175,358.182 +41.900408163,346.297 +41.906213152,342.125 +41.912018141,340.154 +41.917823129,340.858 +41.923628118,341.91 +41.929433107,343.261 +41.935238095,344.697 +41.941043084,344.562 +41.946848073,344.13 +41.952653061,343.462 +41.958458050,342.42 +41.964263039,341.296 +41.970068027,340.201 +41.975873016,339.029 +41.981678005,337.831 +41.987482993,336.943 +41.993287982,335.94 +41.999092971,334.941 +42.004897959,334.099 +42.010702948,333.33 +42.016507937,332.724 +42.022312925,332.243 +42.028117914,331.877 +42.033922902,331.116 +42.039727891,330.584 +42.045532880,329.993 +42.051337868,329.397 +42.057142857,329.289 +42.062947846,329.204 +42.068752834,329.542 +42.074557823,329.96 +42.080362812,330.457 +42.086167800,330.651 +42.091972789,330.782 +42.097777778,330.691 +42.103582766,330.177 +42.109387755,329.365 +42.115192744,328.179 +42.120997732,326.729 +42.126802721,325.202 +42.132607710,323.809 +42.138412698,322.524 +42.144217687,321.511 +42.150022676,321.137 +42.155827664,321.151 +42.161632653,308.751 +42.167437642,308.916 +42.173242630,307.612 +42.179047619,303.727 +42.184852608,295.465 +42.190657596,285.801 +42.196462585,277.116 +42.202267574,268.935 +42.208072562,262.404 +42.213877551,257.567 +42.219682540,255.185 +42.225487528,254.912 +42.231292517,257.252 +42.237097506,258.484 +42.242902494,264.654 +42.248707483,271.526 +42.254512472,278.573 +42.260317460,283.575 +42.266122449,286.319 +42.271927438,286.799 +42.277732426,286.531 +42.283537415,286.239 +42.289342404,285.602 +42.295147392,284.685 +42.300952381,283.58 +42.306757370,282.456 +42.312562358,281.473 +42.318367347,280.597 +42.324172336,280.093 +42.329977324,279.719 +42.335782313,279.901 +42.341587302,280.145 +42.347392290,280.251 +42.353197279,280.299 +42.359002268,279.659 +42.364807256,279.073 +42.370612245,278.573 +42.376417234,278.172 +42.382222222,278.144 +42.388027211,278.264 +42.393832200,278.46 +42.399637188,278.599 +42.405442177,278.141 +42.411247166,276.684 +42.417052154,274.076 +42.422857143,275.342 +42.585396825,291.307 +42.591201814,290.886 +42.597006803,293.244 +42.602811791,294.992 +42.608616780,296.016 +42.614421769,296.707 +42.620226757,297.031 +42.626031746,297.192 +42.631836735,297.053 +42.637641723,296.838 +42.643446712,296.498 +42.649251701,295.903 +42.655056689,295.564 +42.660861678,295.153 +42.666666667,294.791 +42.672471655,294.667 +42.678276644,294.701 +42.684081633,295.185 +42.689886621,296.063 +42.695691610,296.868 +42.701496599,297.299 +42.707301587,297.528 +42.713106576,297.456 +42.718911565,297.143 +42.724716553,296.267 +42.730521542,290.107 +42.736326531,283.859 +42.742131519,279.393 +42.893061224,339.545 +42.898866213,333.813 +42.904671202,334.37 +42.910476190,335.4 +42.916281179,337.218 +42.922086168,338.436 +42.927891156,340.078 +42.933696145,342.15 +42.939501134,343.799 +42.945306122,343.767 +42.951111111,343.563 +42.956916100,341.93 +42.962721088,340.113 +42.968526077,338.171 +42.974331066,336.711 +42.980136054,335.48 +42.985941043,334.358 +42.991746032,333.397 +42.997551020,332.338 +43.003356009,331.354 +43.009160998,330.534 +43.014965986,329.605 +43.020770975,328.943 +43.026575964,328.626 +43.032380952,328.275 +43.038185941,328.18 +43.043990930,328.145 +43.049795918,328.021 +43.055600907,328.001 +43.061405896,328.073 +43.067210884,328.178 +43.073015873,328.162 +43.078820862,328.242 +43.084625850,327.983 +43.090430839,327.593 +43.096235828,326.953 +43.102040816,325.922 +43.107845805,324.799 +43.113650794,322.945 +43.119455782,321.161 +43.125260771,319.697 +43.131065760,318.105 +43.136870748,317.017 +43.142675737,317.538 +43.148480726,309.089 +43.154285714,308.188 +43.160090703,307.781 +43.165895692,301.44 +43.171700680,294.528 +43.177505669,284.47 +43.183310658,275.401 +43.189115646,267.85 +43.194920635,259.142 +43.200725624,250.744 +43.206530612,244.563 +43.212335601,243.465 +43.218140590,245.678 +43.223945578,254.179 +43.229750567,262.092 +43.235555556,271.794 +43.241360544,280.063 +43.247165533,278.799 +43.252970522,290.375 +43.258775510,296.685 +43.264580499,298.728 +43.270385488,300.833 +43.276190476,303.31 +43.281995465,303.822 +43.287800454,303.727 +43.293605442,303.71 +43.299410431,302.785 +43.305215420,302.092 +43.311020408,301.883 +43.316825397,301.436 +43.322630385,301.09 +43.328435374,300.223 +43.334240363,299.209 +43.340045351,298.47 +43.345850340,297.41 +43.351655329,296.745 +43.357460317,296.53 +43.363265306,296.459 +43.369070295,296.463 +43.374875283,296.597 +43.380680272,296.62 +43.386485261,296.708 +43.392290249,297.18 +43.398095238,297.368 +43.403900227,297.575 +43.409705215,297.986 +43.415510204,297.879 +43.421315193,297.522 +43.427120181,296.252 +43.432925170,294.851 +43.438730159,292.493 +43.444535147,288.465 +43.554829932,273.42 +43.560634921,276.664 +43.566439909,279.242 +43.572244898,282.632 +43.578049887,284.299 +43.583854875,284.561 +43.589659864,284.669 +43.595464853,284.208 +43.601269841,283.081 +43.607074830,282.321 +43.612879819,281.596 +43.618684807,280.674 +43.624489796,279.806 +43.630294785,278.564 +43.636099773,277.725 +43.641904762,277.263 +43.647709751,276.939 +43.653514739,277.163 +43.659319728,277.508 +43.665124717,277.788 +43.670929705,278.237 +43.676734694,278.569 +43.682539683,278.87 +43.688344671,279.247 +43.694149660,279.702 +43.699954649,279.99 +43.705759637,280.239 +43.711564626,280.363 +43.717369615,279.99 +43.723174603,279.12 +43.728979592,278.118 +43.734784580,277.172 +43.740589569,276.495 +43.746394558,275.38 +43.752199546,276.238 +43.758004535,276.878 +43.763809524,276.049 +43.769614512,275.398 +43.775419501,274.931 +43.781224490,273.499 +43.787029478,272.092 +43.792834467,269.538 +43.798639456,266.424 +43.804444444,261.749 +43.810249433,255.731 +43.816054422,247.569 +43.821859410,236.071 +43.949569161,246.517 +43.955374150,248.918 +43.961179138,252.569 +43.966984127,254.442 +43.972789116,256.187 +43.978594104,258.083 +43.984399093,260.133 +43.990204082,261.906 +43.996009070,263.298 +44.001814059,264.204 +44.007619048,264.892 +44.013424036,265.398 +44.019229025,265.684 +44.025034014,266.033 +44.030839002,266.726 +44.036643991,267.431 +44.042448980,268.558 +44.048253968,269.667 +44.054058957,270.917 +44.059863946,272.286 +44.065668934,273.395 +44.071473923,274.77 +44.077278912,275.907 +44.083083900,276.969 +44.088888889,277.717 +44.094693878,278.732 +44.100498866,279.465 +44.106303855,280.251 +44.112108844,281.181 +44.117913832,282.396 +44.123718821,283.703 +44.129523810,284.723 +44.135328798,285.174 +44.141133787,285.353 +44.146938776,285.243 +44.152743764,285.133 +44.158548753,285.347 +44.164353741,285.226 +44.170158730,285.576 +44.175963719,286.01 +44.181768707,286.239 +44.187573696,286.698 +44.193378685,287.608 +44.199183673,288.642 +44.204988662,290.53 +44.210793651,292.396 +44.216598639,293.455 +44.222403628,294.224 +44.228208617,294.759 +44.234013605,294.936 +44.239818594,296.005 +44.245623583,296.608 +44.251428571,297.008 +44.257233560,298.02 +44.263038549,298.88 +44.268843537,299.889 +44.274648526,300.736 +44.280453515,301.214 +44.286258503,301.126 +44.292063492,300.478 +44.297868481,299.568 +44.303673469,298.193 +44.309478458,296.372 +44.315283447,294.188 +44.321088435,292.15 +44.326893424,290.102 +44.332698413,288.158 +44.338503401,286.431 +44.344308390,285.373 +44.350113379,284.719 +44.355918367,284.481 +44.361723356,284.856 +44.367528345,285.525 +44.373333333,286.467 +44.379138322,288.043 +44.384943311,290.235 +44.390748299,292.507 +44.396553288,294.476 +44.402358277,296.282 +44.408163265,297.696 +44.413968254,299.361 +44.419773243,301.377 +44.425578231,303.907 +44.431383220,306.409 +44.437188209,308.478 +44.442993197,309.93 +44.448798186,310.801 +44.454603175,310.323 +44.460408163,309.295 +44.466213152,308.067 +44.472018141,306.505 +44.477823129,304.109 +44.483628118,301.346 +44.489433107,298.621 +44.495238095,295.772 +44.501043084,293.008 +44.506848073,290.024 +44.512653061,288.262 +44.518458050,287.207 +44.524263039,286.252 +44.530068027,285.164 +44.535873016,284.455 +44.541678005,283.978 +44.547482993,284.622 +44.553287982,285.976 +44.559092971,287.297 +44.564897959,289.158 +44.570702948,291.43 +44.576507937,294.722 +44.582312925,296.947 +44.588117914,302.097 +44.593922902,308.925 +44.599727891,315.915 +44.605532880,322.34 +44.611337868,327.794 +44.617142857,330.333 +44.622947846,330.356 +44.628752834,328.633 +44.634557823,325.365 +44.640362812,318.938 +44.646167800,312.451 +44.651972789,306.971 +44.657777778,299.31 +44.663582766,289.746 +44.669387755,279.086 +44.675192744,268.806 +44.680997732,261.351 +44.686802721,255.338 +44.692607710,251.438 +44.698412698,248.201 +44.704217687,246.589 +44.710022676,244.982 +44.715827664,244.931 +44.721632653,247.849 +44.727437642,254.119 +44.733242630,267.227 +44.739047619,284.728 +44.744852608,293.389 +44.750657596,304.336 +44.756462585,314.418 +44.762267574,323.104 +44.768072562,332.173 +44.773877551,338.299 +44.779682540,343.776 +44.785487528,349.208 +44.791292517,357.886 +44.797097506,362.781 +44.802902494,365.519 +44.808707483,365.972 +44.814512472,362.395 +44.820317460,358.669 +44.826122449,351.23 +44.831927438,340.716 +44.837732426,325.053 +44.843537415,310.629 +44.849342404,298.493 +44.855147392,284.935 +44.860952381,272.062 +44.866757370,262.428 +44.872562358,259.395 +44.878367347,254.375 +47.159727891,272.422 +47.165532880,276.3 +47.171337868,277.93 +47.177142857,279.042 +47.182947846,279.289 +47.188752834,279.174 +47.194557823,278.932 +47.200362812,278.364 +47.206167800,277.849 +47.211972789,277.336 +47.217777778,277.249 +47.223582766,277.314 +47.229387755,277.384 +47.235192744,277.526 +47.240997732,277.339 +47.246802721,277.007 +47.252607710,276.45 +47.258412698,275.756 +47.264217687,274.638 +47.270022676,273.581 +47.275827664,272.405 +47.281632653,271.651 +47.287437642,271.165 +47.293242630,270.756 +47.299047619,270.641 +47.304852608,270.348 +47.310657596,269.415 +47.316462585,267.377 +47.322267574,264.043 +47.328072562,261.866 +47.496417234,304.278 +47.502222222,313.701 +47.508027211,317.956 +47.513832200,320.93 +47.519637188,323.421 +47.525442177,326.274 +47.531247166,329.751 +47.537052154,333.153 +47.542857143,336.772 +47.548662132,341.159 +47.554467120,345.682 +47.560272109,348.831 +47.566077098,351.393 +47.571882086,353.824 +47.577687075,356.017 +47.583492063,357.614 +47.589297052,358.808 +47.595102041,359.83 +47.600907029,360.694 +47.606712018,361.308 +47.612517007,361.894 +47.618321995,362.297 +47.624126984,362.454 +47.629931973,362.27 +47.635736961,361.373 +47.641541950,358.813 +47.647346939,353.054 +47.653151927,347.481 +47.658956916,340.658 +47.664761905,338.645 +47.780861678,385.828 +47.786666667,379.505 +47.792471655,371.336 +47.798276644,365.424 +47.804081633,361.721 +47.809886621,358.273 +47.815691610,358.34 +47.821496599,359.136 +47.827301587,360.482 +47.833106576,361.178 +47.838911565,361.557 +47.844716553,361.673 +47.850521542,361.118 +47.856326531,360.522 +47.862131519,359.426 +47.867936508,358.343 +47.873741497,357.498 +47.879546485,356.63 +47.885351474,355.823 +47.891156463,354.736 +47.896961451,353.396 +47.902766440,351.559 +47.908571429,349.325 +47.914376417,346.812 +47.920181406,343.963 +47.925986395,341.42 +47.931791383,338.946 +47.937596372,336.868 +47.943401361,335.03 +47.949206349,333.186 +47.955011338,331.435 +47.960816327,329.849 +47.966621315,328.428 +47.972426304,327.395 +47.978231293,326.73 +47.984036281,326.165 +47.989841270,326.126 +47.995646259,326.412 +48.001451247,326.858 +48.007256236,327.329 +48.013061224,327.602 +48.018866213,327.73 +48.024671202,327.682 +48.030476190,327.698 +48.036281179,327.782 +48.042086168,328.06 +48.047891156,328.51 +48.053696145,329.085 +48.059501134,329.463 +48.065306122,329.787 +48.071111111,329.562 +48.076916100,328.552 +48.082721088,326.987 +48.088526077,324.603 +48.094331066,322.464 +48.100136054,320.143 +48.105941043,316.873 +48.111746032,314.756 +48.117551020,312.935 +48.123356009,315.068 +48.129160998,311.09 +48.140770975,280.871 +48.146575964,272.353 +48.152380952,264.945 +48.158185941,265.543 +48.163990930,267.315 +48.169795918,268.419 +48.175600907,268.247 +48.181405896,267.881 +48.187210884,267.526 +48.193015873,267.133 +48.198820862,267.34 +48.204625850,267.527 +48.210430839,267.626 +48.216235828,267.763 +48.222040816,267.645 +48.227845805,267.473 +48.233650794,267.312 +48.239455782,267.08 +48.245260771,266.748 +48.251065760,266.699 +48.256870748,266.676 +48.262675737,267.096 +48.268480726,267.977 +48.274285714,269.446 +48.280090703,271.092 +48.285895692,272.401 +48.291700680,273.059 +48.297505669,273.849 +48.303310658,274.421 +48.309115646,275.467 +48.314920635,276.596 +48.320725624,276.894 +48.326530612,276.293 +48.332335601,274.149 +48.338140590,269.706 +48.343945578,267.449 +48.349750567,257.226 +48.355555556,249.63 +48.361360544,249.299 +48.367165533,249.598 +48.372970522,248.995 +48.494875283,306.078 +48.500680272,311.574 +48.506485261,317.141 +48.512290249,320.766 +48.518095238,323.314 +48.523900227,325.358 +48.529705215,327.468 +48.535510204,329.468 +48.541315193,331.451 +48.547120181,333.561 +48.552925170,335.901 +48.558730159,338.878 +48.564535147,342.574 +48.570340136,346.411 +48.576145125,350.193 +48.581950113,353.311 +48.587755102,356.31 +48.593560091,359.5 +48.599365079,361.931 +48.605170068,363.791 +48.610975057,365.334 +48.616780045,366.836 +48.622585034,369.41 +48.628390023,370.119 +48.634195011,367.533 +48.640000000,360.627 +48.645804989,357.682 +48.651609977,356.204 +48.657414966,354.968 +48.750294785,393.039 +48.756099773,386.223 +48.761904762,387.843 +48.767709751,386.736 +48.773514739,382.851 +48.779319728,379.491 +48.785124717,375.106 +48.790929705,372.083 +48.796734694,369.981 +48.802539683,366.381 +48.808344671,362.147 +48.814149660,359.308 +48.819954649,356.486 +48.825759637,353.456 +48.831564626,349.942 +48.837369615,345.971 +48.843174603,342.227 +48.848979592,339.349 +48.854784580,336.818 +48.860589569,334.833 +48.866394558,333.406 +48.872199546,332.492 +48.878004535,331.804 +48.883809524,331.284 +48.889614512,330.873 +48.895419501,330.446 +48.901224490,330.407 +48.907029478,330.357 +48.912834467,330.309 +48.918639456,330.107 +48.924444444,329.71 +48.930249433,329.101 +48.936054422,328.554 +48.941859410,328.384 +48.947664399,328.139 +48.953469388,328.062 +48.959274376,327.944 +48.965079365,327.767 +48.970884354,327.659 +48.976689342,327.488 +48.982494331,327.464 +48.988299320,327.797 +48.994104308,328.411 +48.999909297,329.221 +49.005714286,330.073 +49.011519274,330.413 +49.017324263,330.707 +49.023129252,330.907 +49.028934240,330.366 +49.034739229,329.597 +49.040544218,327.845 +49.046349206,325.14 +49.052154195,322.602 +49.057959184,319.789 +49.063764172,316.425 +49.069569161,313.793 +49.075374150,311.577 +49.081179138,306.186 +49.086984127,304.386 +49.092789116,297.139 +49.098594104,287.993 +49.104399093,277.522 +49.110204082,268.494 +49.116009070,266.759 +49.121814059,267.033 +49.127619048,273.672 +49.133424036,276.234 +49.139229025,277.037 +49.145034014,277.192 +49.150839002,277.541 +49.156643991,277.457 +49.162448980,277.144 +49.168253968,276.818 +49.174058957,276.262 +49.179863946,275.514 +49.185668934,274.587 +49.191473923,273.757 +49.197278912,273.356 +49.203083900,273.35 +49.208888889,273.14 +49.214693878,272.917 +49.220498866,272.561 +49.226303855,272.212 +49.232108844,272.009 +49.237913832,272.01 +49.243718821,272.194 +49.249523810,272.732 +49.255328798,273.637 +49.261133787,274.357 +49.266938776,275.064 +49.272743764,275.022 +49.278548753,274.517 +49.284353741,274.089 +49.290158730,273.917 +49.295963719,273.867 +49.301768707,273.874 +49.307573696,273.069 +49.446893424,291.435 +49.452698413,302.651 +49.458503401,313.149 +49.464308390,316.08 +49.470113379,318.62 +49.475918367,320.466 +49.481723356,323.992 +49.487528345,330.484 +49.493333333,338.168 +49.499138322,342.332 +49.504943311,346.281 +49.510748299,349.676 +49.516553288,352.826 +49.522358277,355.738 +49.528163265,358.902 +49.533968254,361.809 +49.539773243,363.9 +49.545578231,365.44 +49.551383220,366.581 +49.557188209,368.848 +49.562993197,373.138 +49.568798186,374.142 +49.574603175,375.781 +49.713922902,431.185 +49.719727891,447.442 +49.725532880,440.759 +49.731337868,434.282 +49.737142857,435.465 +49.742947846,419.335 +49.748752834,406.579 +49.754557823,391.456 +49.760362812,374.798 +49.766167800,368.593 +49.771972789,365.696 +49.777777778,362.469 +49.783582766,358.415 +49.789387755,355.072 +49.795192744,351.944 +49.800997732,348.32 +49.806802721,344.55 +49.812607710,341.708 +49.818412698,339.563 +49.824217687,337.821 +49.830022676,336.671 +49.835827664,335.652 +49.841632653,334.966 +49.847437642,334.457 +49.853242630,333.969 +49.859047619,333.656 +49.864852608,333.504 +49.870657596,333.255 +49.876462585,333.085 +49.882267574,332.782 +49.888072562,332.395 +49.893877551,332.166 +49.899682540,331.946 +49.905487528,332.013 +49.911292517,332.032 +49.917097506,331.731 +49.922902494,331.233 +49.928707483,330.438 +49.934512472,329.43 +49.940317460,328.654 +49.946122449,327.802 +49.951927438,327.101 +49.957732426,326.714 +49.963537415,326.524 +49.969342404,326.565 +49.975147392,327.138 +49.980952381,327.951 +49.986757370,328.616 +49.992562358,329.299 +49.998367347,329.358 +50.004172336,328.801 +50.009977324,327.434 +50.015782313,325.211 +50.021587302,322.203 +50.027392290,319.357 +50.033197279,316.259 +50.039002268,312.891 +50.044807256,312.532 +50.050612245,299.907 +50.056417234,285.34 +50.062222222,275.281 +50.068027211,270.409 +50.073832200,263.621 +50.079637188,260.299 +50.085442177,259.766 +50.091247166,266.637 +50.097052154,270.294 +50.102857143,273.407 +50.108662132,274.26 +50.114467120,275.467 +50.120272109,275.596 +50.126077098,275.7 +50.131882086,275.33 +50.137687075,274.731 +50.143492063,274.14 +50.149297052,273.853 +50.155102041,273.695 +50.160907029,273.46 +50.166712018,273.369 +50.172517007,272.823 +50.178321995,272.589 +50.184126984,272.44 +50.189931973,272.564 +50.195736961,272.795 +50.201541950,272.351 +50.207346939,271.867 +50.213151927,270.889 +50.218956916,270.306 +50.224761905,269.484 +50.230566893,268.36 +50.236371882,264.96 +50.242176871,268.702 +50.398911565,289.472 +50.404716553,300.911 +50.410521542,309.851 +50.416326531,314.214 +50.422131519,317.27 +50.427936508,320.06 +50.433741497,324.458 +50.439546485,329.741 +50.445351474,335.456 +50.451156463,341.546 +50.456961451,347.293 +50.462766440,351.479 +50.468571429,355.155 +50.474376417,358.178 +50.480181406,360.797 +50.485986395,363.242 +50.491791383,365.138 +50.497596372,366.566 +50.503401361,368.149 +50.665941043,364.541 +50.671746032,373.96 +50.677551020,385.592 +50.683356009,376.771 +50.689160998,384.038 +50.694965986,379.491 +50.700770975,370.895 +50.706575964,363.977 +50.712380952,348.839 +50.718185941,336.562 +50.723990930,332.908 +50.729795918,333.883 +50.735600907,336.045 +50.741405896,337.397 +50.747210884,337.877 +50.753015873,338.053 +50.758820862,338.882 +50.764625850,339.22 +50.770430839,339.555 +50.776235828,339.338 +50.782040816,338.799 +50.787845805,338.159 +50.793650794,337.493 +50.799455782,337.061 +50.805260771,336.685 +50.811065760,336.44 +50.816870748,336.317 +50.822675737,336.155 +50.828480726,336.031 +50.834285714,335.831 +50.840090703,335.417 +50.845895692,334.996 +50.851700680,334.788 +50.857505669,334.63 +50.863310658,334.627 +50.869115646,334.449 +50.874920635,334.074 +50.880725624,333.79 +50.886530612,333.509 +50.892335601,333.296 +50.898140590,333.132 +50.903945578,333.091 +50.909750567,333.054 +50.915555556,333.133 +50.921360544,333.285 +50.927165533,332.854 +50.932970522,332.062 +50.938775510,330.625 +50.944580499,328.89 +50.950385488,326.751 +50.956190476,324.106 +50.961995465,321.509 +50.967800454,318.564 +50.973605442,315.709 +50.979410431,313.164 +50.985215420,312.954 +50.991020408,305.614 +50.996825397,305.575 +51.002630385,295.031 +51.008435374,276.214 +51.014240363,264.193 +51.020045351,257.721 +51.025850340,250.839 +51.031655329,246.007 +51.037460317,244.31 +51.043265306,244.836 +51.049070295,251.546 +51.054875283,260.762 +51.066485261,285.914 +51.072290249,291.233 +51.078095238,294.448 +51.083900227,296.651 +51.089705215,296.973 +51.095510204,296.479 +51.101315193,295.652 +51.107120181,294 +51.112925170,293.404 +51.118730159,293.895 +51.124535147,294.39 +51.130340136,294.59 +51.136145125,294.261 +51.141950113,293.488 +51.147755102,292.697 +51.153560091,291.971 +51.159365079,291.386 +51.165170068,290.974 +51.170975057,290.757 +51.176780045,290.494 +51.182585034,290.655 +51.188390023,291.415 +51.194195011,292.005 +51.200000000,292.543 +51.205804989,292.904 +51.211609977,292.664 +51.217414966,292.387 +51.223219955,291.722 +51.229024943,290.677 +51.234829932,289.804 +51.240634921,286.994 +51.246439909,279.367 +51.252244898,271.824 +51.258049887,274.273 +51.263854875,274.795 +51.339319728,267.066 +51.345124717,274.085 +51.350929705,278.798 +51.356734694,282.554 +51.362539683,283.282 +51.368344671,282.579 +51.374149660,281.547 +51.379954649,279.964 +51.385759637,277.979 +51.391564626,276.832 +51.397369615,276.351 +51.403174603,276.073 +51.408979592,275.929 +51.414784580,275.776 +51.420589569,275.546 +51.426394558,275.216 +51.432199546,274.935 +51.438004535,274.792 +51.443809524,274.949 +51.449614512,275.22 +51.455419501,275.464 +51.461224490,275.239 +51.467029478,274.851 +51.472834467,274.309 +51.478639456,273.797 +51.484444444,274.058 +51.490249433,274.47 +51.496054422,275.131 +51.501859410,275.858 +51.507664399,276.395 +51.513469388,276.448 +51.519274376,276.226 +51.525079365,275.279 +51.530884354,274.269 +51.536689342,273.388 +51.542494331,272.178 +51.548299320,271.168 +51.554104308,271.573 +51.559909297,272.332 +51.565714286,271.342 +51.571519274,269.909 +51.577324263,267.035 +51.583129252,263.606 +51.588934240,258.066 +51.594739229,251.243 +51.600544218,240.987 +51.606349206,230.087 +51.612154195,219.227 +51.722448980,254.606 +51.728253968,261.562 +51.734058957,266.406 +51.739863946,274.787 +51.745668934,283.182 +51.751473923,292.892 +51.757278912,299.683 +51.768888889,326.132 +51.774693878,332.467 +51.780498866,338.024 +51.786303855,342.104 +51.792108844,345.871 +51.797913832,348.726 +51.803718821,350.389 +51.809523810,351.077 +51.815328798,350.762 +51.821133787,350.003 +51.826938776,348.678 +51.832743764,346.923 +51.838548753,344.8 +51.844353741,342.008 +51.850158730,338.465 +51.855963719,334.709 +51.861768707,330.545 +51.867573696,325.356 +51.873378685,319.513 +51.879183673,314.245 +51.884988662,310.568 +51.890793651,307.162 +51.896598639,303.485 +51.902403628,299.68 +51.908208617,297.141 +51.914013605,295.817 +51.919818594,294.884 +51.925623583,294.622 +51.931428571,294.222 +51.937233560,294.128 +51.943038549,294.658 +51.948843537,295.067 +51.954648526,295.583 +51.960453515,295.768 +51.966258503,295.494 +51.972063492,295.696 +51.977868481,296.242 +51.983673469,299.48 +51.989478458,301.884 +51.995283447,301.727 +52.001088435,301.562 +52.006893424,301.499 +52.012698413,301.423 +52.018503401,302.897 +52.024308390,304.158 +52.030113379,304.468 +52.035918367,305.743 +52.041723356,306.213 +52.047528345,305.687 +52.053333333,304.559 +52.059138322,301.837 +52.064943311,298.091 +52.070748299,295.481 +52.076553288,294.257 +52.082358277,293.297 +52.088163265,292.724 +52.093968254,292.068 +52.099773243,291.213 +52.105578231,290.31 +52.111383220,289.323 +52.117188209,288.128 +52.122993197,287.095 +52.128798186,286.565 +52.134603175,286.608 +52.140408163,287.08 +52.146213152,287.986 +52.152018141,289.106 +52.157823129,290.493 +52.163628118,291.797 +52.169433107,293.233 +52.175238095,294.931 +52.181043084,296.745 +52.186848073,298.783 +52.192653061,301.114 +52.198458050,302.924 +52.204263039,304.183 +52.210068027,304.981 +52.215873016,305.515 +52.221678005,305.522 +52.227482993,304.915 +52.233287982,303.562 +52.239092971,301.533 +52.244897959,298.327 +52.250702948,295.398 +52.256507937,292.524 +52.262312925,289.001 +52.268117914,285.968 +52.273922902,283.323 +52.279727891,281.605 +52.285532880,280.107 +52.291337868,279.149 +52.297142857,278.149 +52.302947846,277.477 +52.308752834,276.975 +52.314557823,275.902 +52.320362812,276.263 +52.326167800,279.877 +52.331972789,296.487 +52.337777778,315.074 +52.343582766,317.621 +52.349387755,330.156 +52.355192744,332.566 +52.360997732,337.272 +52.366802721,340.664 +52.372607710,342.718 +52.378412698,347.329 +52.384217687,351.214 +52.390022676,351.945 +52.395827664,351.37 +52.401632653,348.464 +52.407437642,343.052 +52.413242630,339.706 +52.419047619,332.662 +52.424852608,326.277 +52.430657596,318.547 +52.436462585,307.521 +52.442267574,296.418 +52.448072562,281.764 +52.453877551,268.577 +52.459682540,257.201 +52.465487528,249.244 +52.471292517,244.162 +52.477097506,242.498 +52.482902494,244.676 +52.488707483,249.856 +52.494512472,256.994
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/regression.sh Fri Mar 24 15:08:12 2017 +0000 @@ -0,0 +1,29 @@ +#!/bin/bash + +set -eu + +testdir=$(dirname "$0") + +if ! sonic-annotator -v >/dev/null ; then + echo "No sonic-annotator available in PATH, skipping regression test" + exit 0 +fi + +echo "Running regression test..." + +( time ( VAMP_PATH="$testdir/.." sonic-annotator \ + -d vamp:pyin:pyin:smoothedpitchtrack \ + -w csv --csv-stdout --csv-omit-filename \ + "$testdir/../testdata/bob_02.wav" \ + > "$testdir/obtained.csv" \ + 2> "$testdir/log.txt" ) ) 2>&1 | \ + grep -i real | \ + sed 's/^real/Elapsed time/' + +if ! cmp -s "$testdir/expected.csv" "$testdir/obtained.csv" ; then + echo "*** FAILED, diff follows:" + sdiff -w78 "$testdir/expected.csv" "$testdir/obtained.csv" +else + echo "Succeeded" +fi +
--- a/win32-build/pyin.pro Thu Aug 20 16:06:01 2015 +0100 +++ b/win32-build/pyin.pro Fri Mar 24 15:08:12 2017 +0000 @@ -13,7 +13,6 @@ ../Yin.cpp \ ../SparseHMM.cpp \ ../MonoPitchHMM.cpp \ - ../MonoPitch.cpp \ ../MonoNoteParameters.cpp \ ../MonoNoteHMM.cpp \ ../MonoNote.cpp \ @@ -27,7 +26,6 @@ ../Yin.h \ ../SparseHMM.h \ ../MonoPitchHMM.h \ - ../MonoPitch.h \ ../MonoNoteParameters.h \ ../MonoNoteHMM.h \ ../MonoNote.h \