Fex

Check-in [e7099aefda]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:cleaning up overlap drawing
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | origin/sfml
Files: files | file ages | folders
SHA3-256: e7099aefda0fbba15570a6f95435cda5672199f747642aaf2c0ccf65ea4526f9
User & Date: jesse.mcclure@umassmed.edu 2016-02-10 18:35:31
Context
2016-02-12
17:12
begining python ui check-in: 324d1ee857 user: jesse.mcclure@umassmed.edu tags: trunk, origin/sfml
2016-02-10
18:35
cleaning up overlap drawing check-in: e7099aefda user: jesse.mcclure@umassmed.edu tags: trunk, origin/sfml
2016-01-26
16:24
attempting a win32 build check-in: e0fd3c30ad user: jesse.mcclure@umassmed.edu tags: trunk, origin/sfml
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PROG        =  fex
VER         =  3.0pre
PREFIX     ?=  /usr
CC          =  g++
CONFFILE   ?=  ${PREFIX}/share/${PROG}/${PROG}rc
DEFS        =  -DPROGRAM_NAME=${PROG} -DPROGRAM_VER=${VER} -DDEFAULT_CONFIG=${CONFFILE}
CPPFLAGS   ?=  -D_FORTIFY_SOURCE=2
CXXFLAGS   ?=  -march=native -O2 -pipe -fstack-protector-strong --param=ssp-buffer-size=4
LDFLAGS    ?=  -Wl,-O1,--sort-common,--as-needed,-z,relro
CXXFLAGS   +=  $(shell pkg-config --cflags sfml-all fftw3) -std=c++11 ${DEFS}
LDLIBS     +=  $(shell pkg-config --libs sfml-all fftw3)
MODULES     =  config fex fft spectrogram
MANPAGES    =  ${PROG}.1 ${PROG}rc.5
VPATH       =  src








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PROG        =  fex
VER         =  3.0pre
PREFIX     ?=  /usr
CC          =  g++
CONFFILE   ?=  ${PREFIX}/share/${PROG}/${PROG}rc
DEFS        =  -DPROGRAM_NAME=${PROG} -DPROGRAM_VER=${VER} -DDEFAULT_CONFIG=${CONFFILE}
CPPFLAGS   ?=  -D_FORTIFY_SOURCE=2
CXXFLAGS   ?=  -march=native -O2 -pipe -fstack-protector-strong -Wstack-protector
LDFLAGS    ?=  -Wl,-O1,--sort-common,--as-needed,-z,relro
CXXFLAGS   +=  $(shell pkg-config --cflags sfml-all fftw3) -std=c++11 ${DEFS}
LDLIBS     +=  $(shell pkg-config --libs sfml-all fftw3)
MODULES     =  config fex fft spectrogram
MANPAGES    =  ${PROG}.1 ${PROG}rc.5
VPATH       =  src

Changes to src/config.cpp.

1
2
3
4
5
6
7



8






#include "config.hpp"

Config::Config(int argc, const char **argv) {
	// TODO read config file to override defaults
	if (argc != 2) exit(1);
	fname = argv[1];



}











|
>
>
>

>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#include "config.hpp"

Config::Config(int argc, const char **argv) {
	// TODO read config file to override defaults
	if (argc != 2) exit(1);
	fname = strdup(argv[1]);
	char *dup = strdup(argv[1]);
	name = strdup(basename(dup));
	free(dup);
}

Config::~Config() {
	if (name) free(name);
	if (fname) free(fname);
}

Changes to src/config.hpp.

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

#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>



class Config {
	protected:
		struct {
			int winlen           = 256;
			int hop              = 64;
			double lopass        = 01.25;
			double hipass        = 10.00;
			double threshold     = 20.00;
			double floor         = 24.00;
			sf::Color specFG     = sf::Color::Black;
			sf::Color specBG     = sf::Color::White;
			sf::Color winBG      = sf::Color(200,200,210);
			sf::Color threshFG   = sf::Color(0,128,255,64);



		} conf;
		struct {
			bool cursor       = false;
			bool hud          = true;
			bool overlay      = true;
		} show;
		sf::String fname;

	public:
		Config(int, const char **);

};




>
>








|

|
|
|
|
>
>
>






|



>


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

#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <string.h>
#include <libgen.h>

class Config {
	protected:
		struct {
			int winlen           = 256;
			int hop              = 64;
			double lopass        = 01.25;
			double hipass        = 10.00;
			double threshold     = 14.00;
			double floor         = 24.00;
			sf::Color winBG      = sf::Color(0xFE,0xEF,0xE0);
			sf::Color specBG     = sf::Color(0xFF,0xFF,0xFF);
			sf::Color specFG     = sf::Color(0x00,0x00,0x00);
			sf::Color threshFG   = sf::Color(0x58,0x74,0x98,0x48);
			sf::Color pointFB    = sf::Color(0x33,0x99,0xFF);
			sf::Color pointBG    = sf::Color(0x33,0x99,0xFF,0x48);
			sf::Color linesFG    = sf::Color(0xE8,0x68,0x50);
		} conf;
		struct {
			bool cursor       = false;
			bool hud          = true;
			bool overlay      = true;
		} show;
		char *fname = NULL, *name = NULL;

	public:
		Config(int, const char **);
		~Config();
};

Changes to src/fft.cpp.

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134


135
136
137
138








139
140
141
142
143
144
145
	spec = sf::Sprite(texSpec);
	spec.setScale(1.0,-1.0);
}

void Fft::makeOverlay() {
// TODO add fex calculation here?
//   * Change function name to "recalculate"?
	int t, f, fmax;
	double max;
	for (t = 0; t < ntime; ++t) {
		fmax = -1;
		max = std::numeric_limits<double>::lowest();
		for (f = 0; f < nfreq; ++f) {
			if (erase[nfreq * t + f]) continue;
			if (amp[nfreq * t + f] < max) continue;
			max = amp[nfreq * t + (fmax=f)];
		}
// TODO need to interpolate "blanks" for lines
		lines[t].position = sf::Vector2f(t + 0.5, - fmax - 0.5);
		lines[t].color = sf::Color::Red;
		points[4*t].position = sf::Vector2f(t, - fmax);
		points[4*t+1].position = sf::Vector2f(t + 1, - fmax);
		points[4*t+2].position = sf::Vector2f(t + 1, - fmax - 1);
		points[4*t+3].position = sf::Vector2f(t, - fmax - 1);


		points[4*t].texCoords = sf::Vector2f(0,0);
		points[4*t+1].texCoords = sf::Vector2f(64,0);
		points[4*t+2].texCoords = sf::Vector2f(64,64);
		points[4*t+3].texCoords = sf::Vector2f(0,64);








	}
}

void Fft::makeThreshold() {
	int t, f;
	sf::Image img;
	img.create(ntime, nfreq);







|

|

|





|
|
<
|
|
|
|
>
>
|
|
|
|
>
>
>
>
>
>
>
>







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
	spec = sf::Sprite(texSpec);
	spec.setScale(1.0,-1.0);
}

void Fft::makeOverlay() {
// TODO add fex calculation here?
//   * Change function name to "recalculate"?
	int t, f, fmax, n;;
	double max;
	for (t = 0, n = 0; t < ntime; ++t) {
		fmax = -1;
		max = std::numeric_limits<double>::lowest(); // TODO: is this negative?  Should it be?
		for (f = 0; f < nfreq; ++f) {
			if (erase[nfreq * t + f]) continue;
			if (amp[nfreq * t + f] < max) continue;
			max = amp[nfreq * t + (fmax=f)];
		}
		if (max < -1.0 * conf.threshold) continue;
		lines[n].position = sf::Vector2f(t + 0.5, - fmax - 0.5);

		points[4*n].position = sf::Vector2f(t, - fmax);
		points[4*n+1].position = sf::Vector2f(t + 1, - fmax);
		points[4*n+2].position = sf::Vector2f(t + 1, - fmax - 1);
		points[4*n+3].position = sf::Vector2f(t, - fmax - 1);
// TODO: These next lines should only need to be done once ... move to constructor?
		lines[n].color = conf.linesFG;
		points[4*n].texCoords = sf::Vector2f(0,0);
		points[4*n+1].texCoords = sf::Vector2f(64,0);
		points[4*n+2].texCoords = sf::Vector2f(64,64);
		points[4*n+3].texCoords = sf::Vector2f(0,64);
		++n;
	}
	for (; n < ntime; ++n) {
		lines[n].position = lines[n-1].position;
		points[4*n].position = sf::Vector2f(-2,0);
		points[4*n+1].position = sf::Vector2f(-2,0);
		points[4*n+2].position = sf::Vector2f(-2,0);
		points[4*n+3].position = sf::Vector2f(-2,0);
	}
}

void Fft::makeThreshold() {
	int t, f;
	sf::Image img;
	img.create(ntime, nfreq);

Changes to src/fft.hpp.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
		sf::Texture texSpec, texThresh;
		double *freq = NULL, *time = NULL, *amp = NULL;
		unsigned short int *erase = NULL;
		sf::VertexArray points, lines;

	protected:
		sf::Sprite spec, thresh;
		sf::String name;
		sf::SoundBuffer song;
		int ntime, nfreq;

		void makeSpectrogram();
		void makeThreshold();
		void makeOverlay();
		sf::VertexArray const &getPoints() const { return points; };







<







9
10
11
12
13
14
15

16
17
18
19
20
21
22
		sf::Texture texSpec, texThresh;
		double *freq = NULL, *time = NULL, *amp = NULL;
		unsigned short int *erase = NULL;
		sf::VertexArray points, lines;

	protected:
		sf::Sprite spec, thresh;

		sf::SoundBuffer song;
		int ntime, nfreq;

		void makeSpectrogram();
		void makeThreshold();
		void makeOverlay();
		sf::VertexArray const &getPoints() const { return points; };

Changes to src/spectrogram.cpp.

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

#include "spectrogram.hpp"

Spectrogram::Spectrogram(int argc, const char **argv) : Fft(argc, argv) {
//	if (getenv("NON_REPARENTING"))
		win.create(sf::VideoMode::getDesktopMode(), "Fex", sf::Style::Fullscreen);
//	else
//		win.create(sf::VideoMode::getDesktopMode(), "Fex");
	float aspect = (ntime * win.getSize().y * conf.hop) / (float) (nfreq * win.getSize().x * conf.winlen);
	view.reset(sf::FloatRect(0, -nfreq * (1 + aspect)/2.0, ntime, nfreq * aspect));
	win.setView(view);












}

Spectrogram::~Spectrogram() {
	// TODO destory win, tex, spec.?


















}

void Spectrogram::ev_handler(sf::Event ev) {
	switch (ev.type) {
		case sf::Event::Closed: ev_close(ev); break;
		case sf::Event::KeyPressed: ev_keypress(ev); break;
		case sf::Event::MouseMoved: ev_mousemove(ev); break;
		case sf::Event::MouseButtonPressed: ev_button(ev); break;
		case sf::Event::MouseWheelScrolled: ev_wheel(ev); break;
		case sf::Event::Resized: ev_resize(ev); break;
	}
}

int Spectrogram::main_loop() {
	if (!font.loadFromFile("/usr/share/fonts/TTF/DroidSans.ttf")) return 0;
sf::RectangleShape rect(view.getSize());
sf::RenderTexture pts;
pts.setSmooth(true);
pts.create(64,64);
sf::CircleShape dot(32);
dot.setFillColor(sf::Color(0,0,0,128));
dot.setOutlineColor(sf::Color::Green);
dot.setOutlineThickness(-8);
pts.draw(dot);
aspect = (ntime * win.getSize().y * conf.hop) / (float) (nfreq * win.getSize().x * conf.winlen);
	sf::Event ev;
	while (win.isOpen() && win.waitEvent(ev)) {
		ev_handler(ev);
		while (win.pollEvent(ev)) ev_handler(ev);
		win.clear(conf.winBG);
		spec.setColor(conf.specFG);
rect.setFillColor(conf.specBG);
rect.setSize(sf::Vector2f(ntime,-nfreq));
win.draw(rect);
		win.draw(spec);
		thresh.setColor(conf.threshFG);
		if (show.overlay) {
			win.draw(thresh);
			win.draw(getPoints(), &pts.getTexture());
			win.draw(getLines());
		}
		if (show.cursor) draw_cursor();
		if (show.hud) draw_hud();
		win.display();
	}
	return 0;
}

void Spectrogram::draw_hud() {
	float w = view.getSize().x, h = view.getSize().y;
	float x = view.getCenter().x - w / 2.0, y = view.getCenter().y - h / 2.0;
	sf::RectangleShape shape(sf::Vector2f(w, h * 0.036));
	shape.setPosition(x, y);
	shape.setFillColor(sf::Color(0, 0, 128,100));
	win.draw(shape);
	char out[256];
	sf::Text text;
	text.setFont(font); text.setCharacterSize(28); text.setColor(sf::Color(255,255,255,200)); text.setScale(w/1000,h/1000);
	snprintf(out,255,"FE: %0.3f", 123.456789);
	text.setString(out);
	text.setPosition(x+4, y);
	win.draw(text);
	snprintf(out,255,"(%0.3fs, %0.3fKHz)",
		song.getDuration().asSeconds() * mouse.x / ntime,
		conf.lopass - (conf.hipass - conf.lopass) * mouse.y / nfreq
	);
	text.setString(out);
	text.setPosition(x + w - text.getGlobalBounds().width - 8, y);
	win.draw(text);
}

void Spectrogram::draw_cursor() {
	sf::RectangleShape lineV(sf::Vector2f(1.5, nfreq));
	lineV.setFillColor(sf::Color(255,0,0,120));
	lineV.setPosition(view.getViewport().left + mouse.x, -nfreq);
	win.draw(lineV);
	sf::RectangleShape lineH(sf::Vector2f(ntime, 0.15));
	lineH.setFillColor(sf::Color(255,0,0,120));
	lineH.setPosition(0,view.getViewport().top + mouse.y);
	win.draw(lineH);
}

void Spectrogram::listen(float speed) {
	sf::Sound snd(song);
	snd.play();
	snd.setPitch(speed);
	while(snd.getStatus() == 2) {
		sf::RectangleShape line(sf::Vector2f((float) view.getSize().x / (100.0 * song.getDuration().asSeconds()), nfreq));
		line.setFillColor(sf::Color(0,255,0,120));
		line.setPosition((float) view.getSize().x * snd.getPlayingOffset().asSeconds() / song.getDuration().asSeconds(), -nfreq);
		win.clear();
		win.draw(spec);
		win.draw(line);
		if (show.hud) draw_hud();
		win.display();
	}
}

void Spectrogram::ev_close(sf::Event ev) {
}





|


|
|


>
>
>
>
>
>
>
>
>
>
>
>


|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
|
|
|
|
|
|
|
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|



|










|

|
|
|

|







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

#include "spectrogram.hpp"

Spectrogram::Spectrogram(int argc, const char **argv) : Fft(argc, argv) {
//	if (getenv("FEX_FULLSCREEN"))
		win.create(sf::VideoMode::getDesktopMode(), "Fex", sf::Style::Fullscreen);
//	else
//		win.create(sf::VideoMode(640,480), "Fex");
	aspect = (ntime * win.getSize().y * conf.hop) / (float) (nfreq * win.getSize().x * conf.winlen);
	view.reset(sf::FloatRect(0, -nfreq * (1 + aspect)/2.0, ntime, nfreq * aspect));
	win.setView(view);
	spec.setColor(conf.specFG);
	sf::RenderTexture render_ball;
	render_ball.setSmooth(true);
	render_ball.create(64,64);
	sf::CircleShape dot(32);
	dot.setFillColor(conf.pointBG);
	dot.setOutlineColor(conf.pointFB);
	dot.setOutlineThickness(-8);
	render_ball.draw(dot);
	ball = render_ball.getTexture();
	back.setSize(sf::Vector2f(ntime,-nfreq));
	back.setFillColor(conf.specBG);
}

Spectrogram::~Spectrogram() { }

int Spectrogram::main_loop() {
	sf::Event ev;
	while (win.isOpen() && win.waitEvent(ev)) {
		ev_handler(ev);
		while (win.pollEvent(ev)) ev_handler(ev);
		draw_main();
		if (show.cursor) draw_cursor();
		win.display();
	char out[256];
	snprintf(out,255,"%s - (%0.3fs, %0.3fKHz) FE: %lf ",
		name,
		song.getDuration().asSeconds() * mouse.x / ntime,
		conf.lopass - (conf.hipass - conf.lopass) * mouse.y / nfreq,
		1234.5
	);
	win.setTitle(sf::String(out));
	}
	return 0;
}

void Spectrogram::ev_handler(sf::Event ev) {
	switch (ev.type) {
		case sf::Event::Closed: ev_close(ev); break;
		case sf::Event::KeyPressed: ev_keypress(ev); break;
		case sf::Event::MouseMoved: ev_mousemove(ev); break;
		case sf::Event::MouseButtonPressed: ev_button(ev); break;
		case sf::Event::MouseWheelScrolled: ev_wheel(ev); break;
		case sf::Event::Resized: ev_resize(ev); break;
	}
}

void Spectrogram::draw_main() {















	win.clear(conf.winBG);



	win.draw(back);
	win.draw(spec);
	thresh.setColor(conf.threshFG);
	if (show.overlay) {
		win.draw(thresh);
		win.draw(getPoints(), &ball);
		win.draw(getLines());
	}



}


























void Spectrogram::draw_cursor() {
	sf::RectangleShape lineV(sf::Vector2f(1, nfreq));
	lineV.setFillColor(sf::Color(255,0,0,120));
	lineV.setPosition(view.getViewport().left + mouse.x, -nfreq);
	win.draw(lineV);
	sf::RectangleShape lineH(sf::Vector2f(ntime, 1));
	lineH.setFillColor(sf::Color(255,0,0,120));
	lineH.setPosition(0,view.getViewport().top + mouse.y);
	win.draw(lineH);
}

void Spectrogram::listen(float speed) {
	sf::Sound snd(song);
	snd.play();
	snd.setPitch(speed);
	while(snd.getStatus() == 2) {
		sf::RectangleShape line(sf::Vector2f(10, nfreq));
		line.setFillColor(sf::Color(0,255,0,120));
		//line.setPosition((float) view.getSize().x * snd.getPlayingOffset().asSeconds() / song.getDuration().asSeconds(), -nfreq);
		line.setPosition(ntime * (snd.getPlayingOffset() / song.getDuration()), -nfreq);
		draw_main();
		win.draw(line);
	//	if (show.hud) draw_hud();
		win.display();
	}
}

void Spectrogram::ev_close(sf::Event ev) {
}

168
169
170
171
172
173
174



























void Spectrogram::ev_wheel(sf::Event ev) {
	if (ev.mouseWheelScroll.wheel == 0) { /* vertical */
		view.zoom(1.0 - 0.0075 * ev.mouseWheelScroll.delta);
		win.setView(view);
	}
}

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

void Spectrogram::ev_wheel(sf::Event ev) {
	if (ev.mouseWheelScroll.wheel == 0) { /* vertical */
		view.zoom(1.0 - 0.0075 * ev.mouseWheelScroll.delta);
		win.setView(view);
	}
}

/*
void Spectrogram::draw_hud() {
	float w = view.getSize().x, h = view.getSize().y;
	float x = view.getCenter().x - w / 2.0, y = view.getCenter().y - h / 2.0;
	sf::RectangleShape shape(sf::Vector2f(w, h * 0.036));
	shape.setPosition(x, y);
	shape.setFillColor(sf::Color(0, 0, 128,100));
	win.draw(shape);
	char out[256];
	sf::Text text;
	text.setFont(font); text.setCharacterSize(28); text.setColor(sf::Color(255,255,255,200)); text.setScale(w/1000,h/1000);
	snprintf(out,255," FE: %0.3f", 123.456789);
	text.setString(out);
	text.setPosition(x, y);
	win.draw(text);
	snprintf(out,255,"(%0.3fs, %0.3fKHz) ",
		song.getDuration().asSeconds() * mouse.x / ntime,
		conf.lopass - (conf.hipass - conf.lopass) * mouse.y / nfreq
	);
	text.setString(out);
	text.setPosition(x + w - text.getGlobalBounds().width, y);
	win.draw(text);
}
*/

Changes to src/spectrogram.hpp.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16

17
18
19
20
21
22
23

#include "fft.hpp"
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>

class Spectrogram : public Fft {
	private:
		enum Mode { MOVE_RESIZE };
		Mode mode = MOVE_RESIZE;
		sf::RenderWindow win;
		sf::View view;
		sf::Vector2f mouse;

		sf::Font font;
		float aspect;


		void draw_cursor();
		void draw_hud();

		void ev_handler(sf::Event);
		void ev_close(sf::Event);
		void ev_keypress(sf::Event);
		void ev_mousemove(sf::Event);













>
|


>







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

#include "fft.hpp"
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>

class Spectrogram : public Fft {
	private:
		enum Mode { MOVE_RESIZE };
		Mode mode = MOVE_RESIZE;
		sf::RenderWindow win;
		sf::View view;
		sf::Vector2f mouse;
		sf::RectangleShape back;
		sf::Texture ball;
		float aspect;

		void draw_main();
		void draw_cursor();
		void draw_hud();

		void ev_handler(sf::Event);
		void ev_close(sf::Event);
		void ev_keypress(sf::Event);
		void ev_mousemove(sf::Event);