Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | crop window implemented |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk | origin/sfml |
Files: | files | file ages | folders |
SHA3-256: |
57f725266642d08f9518e741fb49f321 |
User & Date: | jesse.mcclure@umassmed.edu 2016-02-15 19:42:29 |
Context
2016-02-15
| ||
23:13 | initial eraser implementation check-in: c385cdab1c user: jesse.mcclure@umassmed.edu tags: trunk, origin/sfml | |
19:42 | crop window implemented check-in: 57f7252666 user: jesse.mcclure@umassmed.edu tags: trunk, origin/sfml | |
2016-02-12
| ||
17:12 | begining python ui check-in: 324d1ee857 user: jesse.mcclure@umassmed.edu tags: trunk, origin/sfml | |
Changes
Changes to TODO.
1 2 3 4 5 6 |
- Add eraser function to spectrogram module - Add crop option - Add log transformation to frequency? - Implement config file reading |
> < > | > > > > |
1 2 3 4 5 6 7 8 9 10 11 |
- change function names to camelCase in spectrogram - Add eraser function to spectrogram module - Add log transformation to frequency? - Add cursorFG to config.cpp and python code x Implement config file reading * offloaded to pyfex * fex only uses command line parameters * this makes porting across platforms easier * at least for me: I have no idea where a Win user would keep config files. |
Changes to src/config.hpp.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
sf::Color winBG = sf::Color(0x60,0x64,0x68); 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 pointFG = 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, char *const *); ~Config(); }; |
> |
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
sf::Color winBG = sf::Color(0x60,0x64,0x68);
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 pointFG = sf::Color(0x33,0x99,0xFF);
sf::Color pointBG = sf::Color(0x33,0x99,0xFF,0x48);
sf::Color linesFG = sf::Color(0xE8,0x68,0x50);
sf::Color cursorFG = sf::Color(0xFF,0x00,0x00,0xAA);
} conf;
struct {
bool cursor = false;
bool hud = true;
bool overlay = true;
} show;
char *fname = NULL, *name = NULL;
public:
Config(int, char *const *);
~Config();
};
|
Changes to src/fex.cpp.
1 2 3 4 5 6 7 8 9 10 |
#include "spectrogram.hpp" int main(int argc, char *const *argv) { printf("ONE\n"); Spectrogram spec(argc, argv); spec.main_loop(); printf("TWO\n"); return EXIT_SUCCESS; } |
< < |
1 2 3 4 5 6 7 8 |
#include "spectrogram.hpp" int main(int argc, char *const *argv) { Spectrogram spec(argc, argv); spec.main_loop(); return EXIT_SUCCESS; } |
Changes to src/fft.cpp.
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 ... 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 ... 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
amp = new_amp; /* normalize, log transform and scale to dB */ double max = 0.0; for (t = 0; t < ntime; ++t) for (f = 0; f < nfreq; ++f) if (amp[nfreq * t + f] > max) max = amp[nfreq * t + f]; for (t = 0; t < ntime; ++t) for (f = 0; f < nfreq; ++f) amp[nfreq * t + f] = 10.0 * log10(amp[nfreq * t + f] / max); /* prepare point and line overlays */ lines.setPrimitiveType(sf::LinesStrip); lines.resize(ntime); points.setPrimitiveType(sf::Quads); points.resize(ntime * 4); for (t = 0; t < ntime; ++t) { lines[t].color = conf.linesFG; 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); } makeSpectrogram(); makeThreshold(); makeOverlay(); } void Fft::makeSpectrogram() { int t, f; sf::Image img; ................................................................................ } void Fft::makeOverlay() { // * Change function name to "recalculate"? int t, f, fmax, n;; double max, pt, pf; pathLength = timeLength = 0.0; 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; if (n) { /* increment lengths for fex calculation for all but first point */ pathLength += hypot(freq[fmax]-pf,time[t]-pt); ................................................................................ } } void Fft::makeThreshold() { int t, f; sf::Image img; img.create(ntime, nfreq); for (f = 0; f < nfreq; ++f) for (t = 0; t < ntime; ++t) img.setPixel(t, f, sf::Color(255, 255, 255, (amp[nfreq * t + f] > - conf.threshold ? 255 : 0))); texThresh.loadFromImage(img); texThresh.setSmooth(true); thresh = sf::Sprite(texThresh); thresh.setScale(1.0,-1.0); } |
| > > > > > > > > > > > > > > > > > > > > | | | |
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 125 126 127 128 ... 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 ... 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
amp = new_amp; /* normalize, log transform and scale to dB */ double max = 0.0; for (t = 0; t < ntime; ++t) for (f = 0; f < nfreq; ++f) if (amp[nfreq * t + f] > max) max = amp[nfreq * t + f]; for (t = 0; t < ntime; ++t) for (f = 0; f < nfreq; ++f) amp[nfreq * t + f] = 10.0 * log10(amp[nfreq * t + f] / max); /* prepare point and line overlays */ lines.setPrimitiveType(sf::LinesStrip); lines.resize(ntime); points.setPrimitiveType(sf::Quads); points.resize(ntime * 4); for (t = 0; t < ntime; ++t) { lines[t].color = conf.linesFG; 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); } t1 = f1 = 0; t2 = ntime; f2 = nfreq; /* prepare sprites */ makeSpectrogram(); makeThreshold(); makeOverlay(); } void Fft::setCrop(sf::Vector2f a, sf::Vector2f b) { if (a.x == -1) { /* reset */ t1 = f1 = 0; t2 = ntime; f2 = nfreq; } else { a.y *= -1; b.y *= -1; t1 = (a.x < b.x ? a.x : b.x); t2 = (a.x < b.x ? b.x : a.x); f1 = (a.y < b.y ? a.y : b.y); f2 = (a.y < b.y ? b.y : a.y); } makeThreshold(); makeOverlay(); } void Fft::makeSpectrogram() { int t, f; sf::Image img; ................................................................................ } void Fft::makeOverlay() { // * Change function name to "recalculate"? int t, f, fmax, n;; double max, pt, pf; pathLength = timeLength = 0.0; for (t = t1, n = 0; t < t2; ++t) { fmax = -1; max = std::numeric_limits<double>::lowest(); // TODO: is this negative? Should it be? for (f = f1; f < f2; ++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; if (n) { /* increment lengths for fex calculation for all but first point */ pathLength += hypot(freq[fmax]-pf,time[t]-pt); ................................................................................ } } void Fft::makeThreshold() { int t, f; sf::Image img; img.create(ntime, nfreq); for (f = f1; f < f2; ++f) for (t = t1; t < t2; ++t) img.setPixel(t, f, sf::Color(255, 255, 255, (amp[nfreq * t + f] > - conf.threshold ? 255 : 0))); texThresh.loadFromImage(img); texThresh.setSmooth(true); thresh = sf::Sprite(texThresh); thresh.setScale(1.0,-1.0); } |
Changes to src/fft.hpp.
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 |
#include <SFML/Audio.hpp> class Fft : public Config { private: 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; double pathLength, timeLength; void makeSpectrogram(); void makeThreshold(); void makeOverlay(); sf::VertexArray const &getPoints() const { return points; }; sf::VertexArray const &getLines() const { return lines; }; void eraseShift(); void erasePoint(int, int); void eraseUndo(); public: Fft(int, char *const *); ~Fft(); }; |
> > > |
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 |
#include <SFML/Audio.hpp> class Fft : public Config { private: sf::Texture texSpec, texThresh; double *freq = NULL, *time = NULL, *amp = NULL; unsigned short int *erase = NULL; int t1, t2, f1, f2; sf::VertexArray points, lines; protected: sf::Sprite spec, thresh; sf::SoundBuffer song; int ntime, nfreq; double pathLength, timeLength; void makeSpectrogram(); void makeThreshold(); void makeOverlay(); void setCrop(sf::Vector2f, sf::Vector2f); sf::FloatRect getCrop() { return sf::FloatRect(t1, f1, t2 - t1, f2 - f1); } sf::VertexArray const &getPoints() const { return points; }; sf::VertexArray const &getLines() const { return lines; }; void eraseShift(); void erasePoint(int, int); void eraseUndo(); public: Fft(int, char *const *); ~Fft(); }; |
Changes to src/spectrogram.cpp.
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 .. 46 47 48 49 50 51 52 53 54 55 56 57 58 59 .. 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 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 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 185 186 187 188 189 190 |
dot.setFillColor(conf.pointBG); dot.setOutlineColor(conf.pointFG); 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 ................................................................................ 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; } } ................................................................................ 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) { } void Spectrogram::ev_keypress(sf::Event ev) { if (ev.key.control) { if (ev.key.code == sf::Keyboard::Q) win.close(); else if (ev.key.code == sf::Keyboard::Right) { conf.floor -= 0.25; makeSpectrogram(); } else if (ev.key.code == sf::Keyboard::Left) { conf.floor += 0.25; makeSpectrogram(); } else if (ev.key.code == sf::Keyboard::Up) { conf.threshold -= 0.25; /* redraw overlay */ } else if (ev.key.code == sf::Keyboard::Down) { conf.threshold += 0.25; /* redraw overlay */ } } else if (ev.key.alt) { if (ev.key.code == sf::Keyboard::C) win.setMouseCursorVisible(!(show.cursor=!show.cursor)); if (ev.key.code == sf::Keyboard::H) show.hud = !show.hud; if (ev.key.code == sf::Keyboard::O) show.overlay = !show.overlay; if (ev.key.code == sf::Keyboard::Num1) listen(1.0); if (ev.key.code == sf::Keyboard::Num2) listen(0.5); if (ev.key.code == sf::Keyboard::Num3) listen(0.333); if (ev.key.code == sf::Keyboard::Num4) listen(0.25); if (ev.key.code == sf::Keyboard::Num5) listen(0.2); } } void Spectrogram::ev_resize(sf::Event ev) { aspect = (ntime * win.getSize().y * conf.hop) / (float) (nfreq * win.getSize().x * conf.winlen); } void Spectrogram::ev_mousemove(sf::Event ev) { sf::Vector2f prev = mouse; mouse = win.mapPixelToCoords(sf::Vector2i(ev.mouseMove.x,ev.mouseMove.y)); if (mode == MOVE_RESIZE) { if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) { view.setSize(view.getSize().x + prev.x - mouse.x, view.getSize().y + prev.y - mouse.y); view.move((prev.x - mouse.x)/2.0, (prev.y - mouse.y)/2.0); } if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) { view.move(prev.x - mouse.x, prev.y - mouse.y); } win.setView(view); mouse = win.mapPixelToCoords(sf::Vector2i(ev.mouseMove.x,ev.mouseMove.y)); } if (mouse.x < 0) mouse.x = 0.0; else if (mouse.x > ntime) mouse.x = ntime; if (mouse.y > 0) mouse.y = 0.0; else if (mouse.y < - nfreq) mouse.y = - nfreq; } void Spectrogram::ev_button(sf::Event ev) { switch (ev.mouseButton.button) { case sf::Mouse::Button::Middle: view.reset(sf::FloatRect(0, -nfreq * (1 + aspect)/2.0, ntime, nfreq * aspect)); break; } } void Spectrogram::ev_wheel(sf::Event ev) { if (ev.mouseWheelScroll.wheel == 0) { /* vertical */ // TODO, make 0.0075 step size customizable? float vx = view.getSize().x / ntime, vy = view.getSize().y / nfreq; float dx = ev.mouseWheelScroll.delta; if (dx < 0 && vx > 1.20 && vy > 1.20) return; if (dx > 0 && vx < 0.01 && vy > 0.01) return; 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); } */ |
> > | > > > > | > | | | | < < > > < > > > > > < > | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | > > > > > > > > > > > > > > > > > | < < < < < < < < < < < < < < < < < < < < < < < < < |
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 .. 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 .. 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 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 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 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
dot.setFillColor(conf.pointBG); dot.setOutlineColor(conf.pointFG); dot.setOutlineThickness(-8); render_ball.draw(dot); ball = render_ball.getTexture(); back.setSize(sf::Vector2f(ntime,-nfreq)); back.setFillColor(conf.specBG); mouse.x = ntime / 2; mouse.y = - nfreq / 2; crop1 = sf::Vector2f(-1, -1); } 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) { if (crop1.x > 0) draw_cursor(crop1.x, crop1.y); draw_cursor(mouse.x, mouse.y); } 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 ................................................................................ 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::KeyReleased: ev_keyrelease(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; } } ................................................................................ if (show.overlay) { win.draw(thresh); win.draw(getPoints(), &ball); win.draw(getLines()); } } void Spectrogram::draw_cursor(float x, float y) { // TODO get config cursor color sf::RectangleShape lineV(sf::Vector2f(1, nfreq)); lineV.setFillColor(conf.cursorFG); lineV.setPosition(view.getViewport().left + x, -nfreq); win.draw(lineV); sf::RectangleShape lineH(sf::Vector2f(ntime, 1)); lineH.setFillColor(conf.cursorFG); lineH.setPosition(0,view.getViewport().top + 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(ntime * (snd.getPlayingOffset() / song.getDuration()), -nfreq); draw_main(); win.draw(line); win.display(); } } void Spectrogram::ev_close(sf::Event ev) { } void Spectrogram::ev_keypress(sf::Event ev) { if (ev.key.code == sf::Keyboard::LShift) show.cursor = true; if (ev.key.code == sf::Keyboard::RShift) show.cursor = true; if (ev.key.control) { if (ev.key.code == sf::Keyboard::Q) win.close(); else if (ev.key.code == sf::Keyboard::Right) { conf.floor -= 0.25; makeSpectrogram(); } else if (ev.key.code == sf::Keyboard::Left) { conf.floor += 0.25; makeSpectrogram(); } else if (ev.key.code == sf::Keyboard::Up) { conf.threshold -= 0.25; /* redraw overlay */ } else if (ev.key.code == sf::Keyboard::Down) { conf.threshold += 0.25; /* redraw overlay */ } } else if (ev.key.alt) { if (ev.key.code == sf::Keyboard::H) show.hud = !show.hud; if (ev.key.code == sf::Keyboard::O) show.overlay = !show.overlay; if (ev.key.code == sf::Keyboard::Num1) listen(1.0); if (ev.key.code == sf::Keyboard::Num2) listen(0.5); if (ev.key.code == sf::Keyboard::Num3) listen(0.333); if (ev.key.code == sf::Keyboard::Num4) listen(0.25); if (ev.key.code == sf::Keyboard::Num5) listen(0.2); } } void Spectrogram::ev_keyrelease(sf::Event ev) { if (ev.key.code == sf::Keyboard::LShift) show.cursor = false; if (ev.key.code == sf::Keyboard::RShift) show.cursor = false; } void Spectrogram::ev_resize(sf::Event ev) { aspect = (ntime * win.getSize().y * conf.hop) / (float) (nfreq * win.getSize().x * conf.winlen); } void Spectrogram::ev_mousemove(sf::Event ev) { sf::Vector2f prev = mouse; mouse = win.mapPixelToCoords(sf::Vector2i(ev.mouseMove.x,ev.mouseMove.y)); if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) { view.setSize(view.getSize().x + prev.x - mouse.x, view.getSize().y + prev.y - mouse.y); view.move((prev.x - mouse.x)/2.0, (prev.y - mouse.y)/2.0); } if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) { view.move(prev.x - mouse.x, prev.y - mouse.y); } win.setView(view); mouse = win.mapPixelToCoords(sf::Vector2i(ev.mouseMove.x,ev.mouseMove.y)); if (mouse.x < 0) mouse.x = 0.0; else if (mouse.x > ntime) mouse.x = ntime; if (mouse.y > 0) mouse.y = 0.0; else if (mouse.y < - nfreq) mouse.y = - nfreq; } void Spectrogram::checkModKeys() { mod_ctrl = mod_shift = mod_alt = false; if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl)) mod_ctrl = true; if (sf::Keyboard::isKeyPressed(sf::Keyboard::RControl)) mod_ctrl = true; if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)) mod_shift = true; if (sf::Keyboard::isKeyPressed(sf::Keyboard::RShift)) mod_shift = true; if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt)) mod_alt = true; if (sf::Keyboard::isKeyPressed(sf::Keyboard::RAlt)) mod_alt = true; } void Spectrogram::ev_button(sf::Event ev) { checkModKeys(); sf::FloatRect rect; /* Control + button combinations are for working with the threshold: */ if (mod_ctrl) switch (ev.mouseButton.button) { } /* Shift + button combinations are for working with the crop area: */ else if (mod_shift) switch (ev.mouseButton.button) { /* set a crop window: requires 2 presses */ case sf::Mouse::Button::Left: if (crop1.x < 0) crop1 = mouse; else { setCrop(crop1, mouse); crop1.x = -1; } break; /* zoom to fit crop area to window */ case sf::Mouse::Button::Middle: rect = getCrop(); rect.top -= rect.height * (1 + aspect) / 2.0; rect.height *= aspect; view.reset(rect); win.setView(view); break; /* reset crop to full song */ case sf::Mouse::Button::Right: crop1.x = -1; setCrop(crop1, mouse); break; } /* Alt + button combinations are for working with the eraser: */ else if (mod_alt) switch (ev.mouseButton.button) { } else switch (ev.mouseButton.button) { /* NOTE: left and right are handled in ev_mousemove */ /* zoom to fit song to window */ case sf::Mouse::Button::Middle: view.reset(sf::FloatRect(0, -nfreq * (1 + aspect)/2.0, ntime, nfreq * aspect)); win.setView(view); break; } } void Spectrogram::ev_wheel(sf::Event ev) { checkModKeys(); bool vert = (ev.mouseWheelScroll.wheel == 0); /* Control + wheel combinations are for working with the threshold: */ if (mod_ctrl && vert) { // TODO: threshold up/down } /* Shift + wheel combinations are for working with the crop area: */ else if (mod_shift) { // TODO: anything here? Probably not. } /* Alt + wheel combinations are for working with the eraser: */ else if (mod_alt && vert) { // TODO: size up/down } else if (mod_alt) { // TODO: shape left/right } /* No modifier wheel movements are for zooming: */ else if (vert) { // TODO: make 0.0075 step size customizable? float vx = view.getSize().x / ntime, vy = view.getSize().y / nfreq; float dx = ev.mouseWheelScroll.delta; if (dx < 0 && vx > 1.20 && vy > 1.20) return; if (dx > 0 && vx < 0.01 && vy > 0.01) return; view.zoom(1.0 - 0.0075 * ev.mouseWheelScroll.delta); win.setView(view); } } |
Changes to src/spectrogram.hpp.
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 |
#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); void ev_resize(sf::Event); void ev_button(sf::Event); void ev_wheel(sf::Event); protected: void listen(float=1.0); public: int main_loop(); Spectrogram(int, char *const *); ~Spectrogram(); }; |
< < | > | > > |
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 |
#include "fft.hpp" #include <SFML/Audio.hpp> #include <SFML/Graphics.hpp> #include <SFML/Window.hpp> class Spectrogram : public Fft { private: sf::RenderWindow win; sf::View view; sf::Vector2f mouse, crop1; sf::RectangleShape back; sf::Texture ball; bool mod_ctrl, mod_shift, mod_alt; float aspect; void draw_main(); void draw_cursor(float, float); void draw_hud(); void checkModKeys(); void ev_handler(sf::Event); void ev_close(sf::Event); void ev_keypress(sf::Event); void ev_keyrelease(sf::Event); void ev_mousemove(sf::Event); void ev_resize(sf::Event); void ev_button(sf::Event); void ev_wheel(sf::Event); protected: void listen(float=1.0); public: int main_loop(); Spectrogram(int, char *const *); ~Spectrogram(); }; |