File: LoopPointExtractor.hxx

package info (click to toggle)
clam 1.4.0-6
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 17,836 kB
  • ctags: 20,981
  • sloc: cpp: 92,504; python: 9,721; ansic: 1,602; xml: 444; sh: 239; makefile: 153; perl: 54; asm: 15
file content (124 lines) | stat: -rw-r--r-- 3,917 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

#include <CLAM/XMLStorage.hxx>
#include <CLAM/SMSSynthesis.hxx>
#include <CLAM/SMSSynthesisConfig.hxx>
#include <CLAM/Audio.hxx>
#include <CLAM/List.hxx>
#include "Processing.hxx"
#include "SDIFInConfig.hxx"
#include "SDIFFileReader.hxx"
#include "MonoAudioFileWriter.hxx"
#include "MonoAudioFileWriterConfig.hxx"
#include "Spectrum.hxx"
#include "AudioManager.hxx"
#include "AudioIO.hxx"
#include "AudioOut.hxx"
#include "TopLevelProcessing.hxx"
#include "DataTypes.hxx"
#include <math.h>
#include "emd.hxx"
#include <algorithm>
#include <float.h>

/**
*  This class extracts the best loop points from a collection of 
*  analysis frames using the earth movers distance. This algorithm
*  calculates the distances between two sets of spectral peak arrays
*  by calculating the cost of tranforming one into the other. The
*  actual code for calculating this distance comes from one of
*  the original authors of the algorithm, Y. Rubner.
*
*  \see http://ai.stanford.edu/~rubner/emd/default.htm  
*
*  \author Greg Kellum [gkellum@iua.upf.edu] 7/1/2007
*  \since  CLAM v1.1
*/

namespace CLAM
{

// this ensures that the loop is at least a second long because with a 
// hopzise of 256 samples, ceil(44100 / 256) = 173 frames
#define DEFAULT_MINIMUM_FRAME_SEPARATION 173
// it's computationally too expensive to compare every frame for files larger
// than a few seconds. so, use this parameter to set how many frames you would
// like to hop over between each emd evaluation.
#define DEFAULT_FRAME_HOPSIZE 10

class DistanceMeasure
{
public:
	bool operator<(const DistanceMeasure& argDistanceMeasure) const
	{
		return getDistance() < argDistanceMeasure.getDistance();
	}
	bool operator>(const DistanceMeasure& argDistanceMeasure) const
	{
		return getDistance() > argDistanceMeasure.getDistance();
	}
	bool operator==(const DistanceMeasure& argDistanceMeasure) const
	{
		return getDistance() == argDistanceMeasure.getDistance();
	}
	int getPositionA() const { return positionA; }
	void setPositionA(int argPosition) { positionA = argPosition; }
	int getPositionB() const { return positionB; }
	void setPositionB(int argPosition) { positionB = argPosition; }
	float getDistance() const { return distance; }
	void setDistance(float argDistance) { distance = argDistance; }
private:
	int positionA;
	int positionB;
	float distance;
};

class LoopPointExtractor
{
public:
	LoopPointExtractor();
	
	void extractOptimalLoopPoints(CLAM::List<CLAM::Frame>& framesArray,
									std::map<int,int>& loopPoints,
									int startFrame=0, int endFrame=-1);

private:

	int millisecondsToFrames(double milliseconds)
	{
		return milliseconds / 1000. * 44100 / 256.;
	}
	
	int framesToMilliseconds(int frames)
	{
		return frames * 256. / 44100. * 1000.;
	}


	void scaleWeights(TData* weights1Ptr, TData* scaledWeights1Ptr, int arraySize);

	void generateEqualWeights(TData* scaledWeights1Ptr, int arraySize);

	signature_t generateSignatureWithMagnitudes(SpectralPeakArray& spectralPeakArray);
	
	signature_t generateSignatureWithFrequenciesScaledByMagnitudes(SpectralPeakArray& spectralPeakArray);
	
	void calculateEarthMoverDistances(CLAM::List<CLAM::Frame>& framesArray, std::vector<CLAM::DistanceMeasure>& emdVector, int startFrame=0, int endFrame=-1);

	bool areStartAndEndFramesCloseTogether(int startFrameNumber, int endFrameNumber);

	bool areStartAndEndFramesCloseTogether(DistanceMeasure& pDistanceMeasure);
	
	bool isCloseToFrameAlreadyReported(DistanceMeasure& currentDistanceMeasure, std::vector<CLAM::DistanceMeasure>& reportedDistanceVector);
	
	void selectBestLoopPoints(std::vector<CLAM::DistanceMeasure>& emdVector, std::vector<CLAM::DistanceMeasure>& bestLoopsVector);

	void convertToMap(std::vector<CLAM::DistanceMeasure>& bestLoopsVector, std::map<int,int>& loopPoints);

	std::vector<CLAM::DistanceMeasure> emdVector;
	int minimumStartAndEndFrameSeparation;
	int frameHopSize;

};

} //namespace CLAM