visualizer: add filled wave visualizer
This commit is contained in:
committed by
Andrzej Rybczak
parent
9bab03e4b2
commit
1f2daaa08c
@@ -39,4 +39,6 @@ enum class Design { Classic, Alternative };
|
||||
std::ostream &operator<<(std::ostream &os, Design ui);
|
||||
std::istream &operator>>(std::istream &is, Design &ui);
|
||||
|
||||
enum class VisualizerType { Wave, WaveFilled, Spectrum };
|
||||
|
||||
#endif // NCMPCPP_ENUMS_H
|
||||
|
||||
@@ -231,13 +231,8 @@ bool Configuration::read(const std::string &config_path)
|
||||
return boost::posix_time::seconds(v);
|
||||
}));
|
||||
p.add("visualizer_type", option_parser::worker([this](std::string &&v) {
|
||||
if (v == "wave")
|
||||
visualizer_use_wave = true;
|
||||
else if (v == "spectrum")
|
||||
visualizer_use_wave = false;
|
||||
else
|
||||
throw std::runtime_error("invalid argument: " + v);
|
||||
}, defaults_to(visualizer_use_wave, true)
|
||||
visualizer_type = stringToVisualizerType( v );
|
||||
}, defaults_to(visualizer_type, VisualizerType::Wave)
|
||||
));
|
||||
p.add("visualizer_look", assign_default<std::string>(
|
||||
visualizer_chars, "●▮", [](std::string &&s) {
|
||||
@@ -649,3 +644,5 @@ bool Configuration::read(const std::string &config_path)
|
||||
std::ifstream f(config_path);
|
||||
return p.run(f);
|
||||
}
|
||||
|
||||
/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab : */
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
struct Column
|
||||
{
|
||||
Column() : stretch_limit(-1), right_alignment(0), display_empty_tag(1) { }
|
||||
|
||||
|
||||
std::wstring name;
|
||||
std::string type;
|
||||
int width;
|
||||
@@ -50,12 +50,12 @@ struct Configuration
|
||||
Configuration()
|
||||
: playlist_disable_highlight_delay(0), visualizer_sync_interval(0)
|
||||
{ }
|
||||
|
||||
|
||||
bool read(const std::string &config_path);
|
||||
|
||||
|
||||
std::string ncmpcpp_directory;
|
||||
std::string lyrics_directory;
|
||||
|
||||
|
||||
std::string mpd_music_dir;
|
||||
std::string visualizer_fifo_path;
|
||||
std::string visualizer_output_name;
|
||||
@@ -78,7 +78,7 @@ struct Configuration
|
||||
std::string lastfm_preferred_language;
|
||||
std::wstring progressbar;
|
||||
std::wstring visualizer_chars;
|
||||
|
||||
|
||||
std::string pattern;
|
||||
|
||||
std::vector<Column> columns;
|
||||
@@ -94,7 +94,7 @@ struct Configuration
|
||||
NC::Buffer now_playing_prefix;
|
||||
NC::Buffer now_playing_suffix;
|
||||
NC::Buffer modified_item_prefix;
|
||||
|
||||
|
||||
NC::Color color1;
|
||||
NC::Color color2;
|
||||
NC::Color empty_tags_color;
|
||||
@@ -109,17 +109,19 @@ struct Configuration
|
||||
NC::Color statusbar_color;
|
||||
NC::Color alternative_ui_separator_color;
|
||||
NC::Color active_column_color;
|
||||
|
||||
std::vector<NC::Color> visualizer_colors;
|
||||
|
||||
VisualizerType visualizer_type;
|
||||
|
||||
NC::Border window_border;
|
||||
NC::Border active_window_border;
|
||||
|
||||
|
||||
Design design;
|
||||
|
||||
SpaceAddMode space_add_mode;
|
||||
|
||||
mpd_tag_type media_lib_primary_tag;
|
||||
|
||||
|
||||
bool colors_enabled;
|
||||
bool playlist_show_remaining_time;
|
||||
bool playlist_shorten_total_times;
|
||||
@@ -151,7 +153,6 @@ struct Configuration
|
||||
bool ask_before_clearing_playlists;
|
||||
bool mouse_support;
|
||||
bool mouse_list_scroll_whole_page;
|
||||
bool visualizer_use_wave;
|
||||
bool visualizer_in_stereo;
|
||||
bool data_fetching_delay;
|
||||
bool media_library_sort_by_mtime;
|
||||
@@ -162,7 +163,7 @@ struct Configuration
|
||||
bool ask_for_locked_screen_width_part;
|
||||
bool allow_for_physical_item_deletion;
|
||||
bool progressbar_boldness;
|
||||
|
||||
|
||||
unsigned mpd_connection_timeout;
|
||||
unsigned crossfade_time;
|
||||
unsigned seek_time;
|
||||
@@ -173,21 +174,21 @@ struct Configuration
|
||||
unsigned search_engine_default_search_mode;
|
||||
|
||||
boost::regex::flag_type regex_type;
|
||||
|
||||
|
||||
boost::posix_time::seconds playlist_disable_highlight_delay;
|
||||
boost::posix_time::seconds visualizer_sync_interval;
|
||||
|
||||
|
||||
double visualizer_sample_multiplier;
|
||||
double locked_screen_width_part;
|
||||
|
||||
|
||||
size_t selected_item_prefix_length;
|
||||
size_t selected_item_suffix_length;
|
||||
size_t now_playing_prefix_length;
|
||||
size_t now_playing_suffix_length;
|
||||
|
||||
|
||||
ScreenType startup_screen_type;
|
||||
std::list<ScreenType> screen_sequence;
|
||||
|
||||
|
||||
SortMode browser_sort_mode;
|
||||
};
|
||||
|
||||
|
||||
@@ -43,6 +43,18 @@ NC::Color stringToColor(const std::string &color)
|
||||
return result;
|
||||
}
|
||||
|
||||
VisualizerType stringToVisualizerType(const std::string &visualizerType)
|
||||
{
|
||||
VisualizerType result = VisualizerType::Wave;
|
||||
if (visualizerType == "wave")
|
||||
result = VisualizerType::Wave;
|
||||
else if (visualizerType == "spectrum")
|
||||
result = VisualizerType::Spectrum;
|
||||
else if (visualizerType == "wave_filled")
|
||||
result = VisualizerType::WaveFilled;
|
||||
return result;
|
||||
}
|
||||
|
||||
NC::Border stringToBorder(const std::string &border)
|
||||
{
|
||||
NC::Border result = NC::Border::None;
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
#include "mpdpp.h"
|
||||
#include "mutable_song.h"
|
||||
#include "window.h"
|
||||
#include "enums.h"
|
||||
|
||||
NC::Color stringToColor(const std::string &color);
|
||||
VisualizerType stringToVisualizerType(const std::string &visualizerType);
|
||||
NC::Border stringToBorder(const std::string &border);
|
||||
|
||||
std::string tagTypeToString(mpd_tag_type tag);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "title.h"
|
||||
#include "screen_switcher.h"
|
||||
#include "status.h"
|
||||
#include "enums.h"
|
||||
|
||||
using Global::MainStartY;
|
||||
using Global::MainHeight;
|
||||
@@ -92,13 +93,13 @@ void Visualizer::update()
|
||||
{
|
||||
if (m_fifo < 0)
|
||||
return;
|
||||
|
||||
|
||||
// PCM in format 44100:16:1 (for mono visualization) and 44100:16:2 (for stereo visualization) is supported
|
||||
int16_t buf[m_samples];
|
||||
ssize_t data = read(m_fifo, buf, sizeof(buf));
|
||||
if (data < 0) // no data available in fifo
|
||||
return;
|
||||
|
||||
|
||||
if (m_output_id != -1 && Global::Timer - m_timer > Config.visualizer_sync_interval)
|
||||
{
|
||||
Mpd.DisableOutput(m_output_id);
|
||||
@@ -106,13 +107,16 @@ void Visualizer::update()
|
||||
Mpd.EnableOutput(m_output_id);
|
||||
m_timer = Global::Timer;
|
||||
}
|
||||
|
||||
|
||||
void (Visualizer::*draw)(int16_t *, ssize_t, size_t, size_t);
|
||||
# ifdef HAVE_FFTW3_H
|
||||
if (!Config.visualizer_use_wave)
|
||||
if (Config.visualizer_type == VisualizerType::Spectrum)
|
||||
draw = &Visualizer::DrawFrequencySpectrum;
|
||||
else
|
||||
# endif // HAVE_FFTW3_H
|
||||
if (Config.visualizer_type == VisualizerType::WaveFilled)
|
||||
draw = &Visualizer::DrawSoundWaveFill;
|
||||
else
|
||||
draw = &Visualizer::DrawSoundWave;
|
||||
|
||||
const ssize_t samples_read = data/sizeof(int16_t);
|
||||
@@ -137,7 +141,7 @@ void Visualizer::update()
|
||||
}
|
||||
size_t half_height = MainHeight/2;
|
||||
(this->*draw)(buf_left, samples_read/2, 0, half_height);
|
||||
(this->*draw)(buf_right, samples_read/2, half_height+(draw == &Visualizer::DrawSoundWave ? 1 : 0), half_height+(draw != &Visualizer::DrawSoundWave ? 1 : 0));
|
||||
(this->*draw)(buf_right, samples_read/2, half_height+(draw == &Visualizer::DrawFrequencySpectrum ? 0 : 1), half_height+(draw != &Visualizer::DrawFrequencySpectrum ? 0 : 1));
|
||||
}
|
||||
else
|
||||
(this->*draw)(buf, samples_read, 0, MainHeight);
|
||||
@@ -154,12 +158,63 @@ int Visualizer::windowTimeout()
|
||||
|
||||
void Visualizer::spacePressed()
|
||||
{
|
||||
std::string visualizerName;
|
||||
if (Config.visualizer_type == VisualizerType::Wave)
|
||||
{
|
||||
Config.visualizer_type = VisualizerType::WaveFilled;
|
||||
visualizerName = "sound wave filled";
|
||||
}
|
||||
# ifdef HAVE_FFTW3_H
|
||||
Config.visualizer_use_wave = !Config.visualizer_use_wave;
|
||||
Statusbar::printf("Visualization type: %1%",
|
||||
Config.visualizer_use_wave ? "sound wave" : "frequency spectrum"
|
||||
);
|
||||
else if (Config.visualizer_type == VisualizerType::WaveFilled)
|
||||
{
|
||||
Config.visualizer_type = VisualizerType::Spectrum;
|
||||
visualizerName = "frequency spectrum";
|
||||
}
|
||||
# endif // HAVE_FFTW3_H
|
||||
else
|
||||
{
|
||||
Config.visualizer_type = VisualizerType::Wave;
|
||||
visualizerName = "sound wave";
|
||||
}
|
||||
|
||||
Statusbar::printf("Visualization type: %1%", visualizerName.c_str());
|
||||
}
|
||||
|
||||
NC::Color Visualizer::toColor( int number, int max )
|
||||
{
|
||||
const int colorMapSize = Config.visualizer_colors.size();
|
||||
const int normalizedNumber = ( ( number * colorMapSize ) / max ) % colorMapSize;
|
||||
return Config.visualizer_colors[normalizedNumber];
|
||||
}
|
||||
|
||||
void Visualizer::DrawSoundWaveFill(int16_t *buf, ssize_t samples, size_t y_offset, size_t height)
|
||||
{
|
||||
const int samples_per_col = samples/w.getWidth();
|
||||
const int half_height = height/2;
|
||||
double prev_point_pos = 0;
|
||||
const size_t win_width = w.getWidth();
|
||||
const bool left = y_offset > 0;
|
||||
int x = 0;
|
||||
for (size_t i = 0; i < win_width; ++i)
|
||||
{
|
||||
double point_pos = 0;
|
||||
for (int j = 0; j < samples_per_col; ++j)
|
||||
point_pos += buf[i*samples_per_col+j];
|
||||
point_pos /= samples_per_col;
|
||||
point_pos /= std::numeric_limits<int16_t>::max();
|
||||
point_pos *= half_height;
|
||||
for (int k = 0; k < point_pos * 2; k += 1)
|
||||
{
|
||||
x = left ? height + k : height - k;
|
||||
if ( x > 0 && x < w.getHeight() && (i-(k < half_height + point_pos)) > 0 && (i-(k < half_height + point_pos)) < w.getWidth() )
|
||||
{
|
||||
w << toColor( k, height )
|
||||
<< NC::XY(i-(k < half_height + point_pos), x)
|
||||
<< Config.visualizer_chars[1]
|
||||
<< NC::Color::End;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Visualizer::DrawSoundWave(int16_t *buf, ssize_t samples, size_t y_offset, size_t height)
|
||||
@@ -183,7 +238,7 @@ void Visualizer::DrawSoundWave(int16_t *buf, ssize_t samples, size_t y_offset, s
|
||||
Config.visualizer_colors.size()), Config.visualizer_colors.size() - 1)]
|
||||
<< Config.visualizer_chars[0]
|
||||
<< NC::Color::End;
|
||||
|
||||
|
||||
if (i && abs(prev_point_pos-point_pos) > 2)
|
||||
{
|
||||
// if gap is too big. intermediate values are needed
|
||||
@@ -211,13 +266,13 @@ void Visualizer::DrawFrequencySpectrum(int16_t *buf, ssize_t samples, size_t y_o
|
||||
else
|
||||
m_fftw_input[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
fftw_execute(m_fftw_plan);
|
||||
|
||||
|
||||
// count magnitude of each frequency and scale it to fit the screen
|
||||
for (unsigned i = 0; i < m_fftw_results; ++i)
|
||||
m_freq_magnitudes[i] = sqrt(m_fftw_output[i][0]*m_fftw_output[i][0] + m_fftw_output[i][1]*m_fftw_output[i][1])/2e4*height;
|
||||
|
||||
|
||||
const size_t win_width = w.getWidth();
|
||||
// cut bandwidth a little to achieve better look
|
||||
const int freqs_per_col = m_fftw_results/win_width * 7/10;
|
||||
@@ -282,3 +337,4 @@ void Visualizer::FindOutputID()
|
||||
|
||||
#endif // ENABLE_VISUALIZER
|
||||
|
||||
/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab : */
|
||||
|
||||
@@ -37,41 +37,43 @@
|
||||
struct Visualizer: Screen<NC::Window>, Tabbable
|
||||
{
|
||||
Visualizer();
|
||||
|
||||
|
||||
virtual void switchTo() OVERRIDE;
|
||||
virtual void resize() OVERRIDE;
|
||||
|
||||
|
||||
virtual std::wstring title() OVERRIDE;
|
||||
virtual ScreenType type() OVERRIDE { return ScreenType::Visualizer; }
|
||||
|
||||
|
||||
virtual void update() OVERRIDE;
|
||||
virtual void scroll(NC::Scroll) OVERRIDE { }
|
||||
|
||||
virtual int windowTimeout() OVERRIDE;
|
||||
|
||||
|
||||
virtual void enterPressed() OVERRIDE { }
|
||||
virtual void spacePressed() OVERRIDE;
|
||||
virtual void mouseButtonPressed(MEVENT) OVERRIDE { }
|
||||
|
||||
|
||||
virtual bool isMergable() OVERRIDE { return true; }
|
||||
|
||||
|
||||
// private members
|
||||
void SetFD();
|
||||
void ResetFD();
|
||||
void FindOutputID();
|
||||
|
||||
|
||||
protected:
|
||||
virtual bool isLockable() OVERRIDE { return true; }
|
||||
|
||||
|
||||
private:
|
||||
NC::Color toColor(int, int);
|
||||
void DrawSoundWave(int16_t *, ssize_t, size_t, size_t);
|
||||
void DrawSoundWaveFill(int16_t *, ssize_t, size_t, size_t);
|
||||
# ifdef HAVE_FFTW3_H
|
||||
void DrawFrequencySpectrum(int16_t *, ssize_t, size_t, size_t);
|
||||
# endif // HAVE_FFTW3_H
|
||||
|
||||
|
||||
int m_output_id;
|
||||
boost::posix_time::ptime m_timer;
|
||||
|
||||
|
||||
int m_fifo;
|
||||
unsigned m_samples;
|
||||
# ifdef HAVE_FFTW3_H
|
||||
@@ -89,3 +91,4 @@ extern Visualizer *myVisualizer;
|
||||
|
||||
#endif // NCMPCPP_VISUALIZER_H
|
||||
|
||||
/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab : */
|
||||
|
||||
Reference in New Issue
Block a user