19 #include <QCoreApplication>
20 #include <QApplication>
46 : m_xscreensaverenable(screensaverenable)
66 p->fillRect(0, 0, size.width(), size.height(),
back);
70 QFont font = QApplication::font();
74 int logicalDpiY = 100;
75 HDC hdc = GetDC(
nullptr);
78 logicalDpiY = GetDeviceCaps(hdc, LOGPIXELSY);
79 ReleaseDC(
nullptr, hdc);
86 float floatSize = (16 * 100.0F) / logicalDpiY;
91 floatSize = floatSize * hmult;
93 font.setPointSize(lroundf(floatSize));
94 font.setWeight(QFont::Bold);
95 font.setPointSizeF(fontSize * (size.width() / 800.0));
98 p->drawText(0, 0, size.width(), size.height(), Qt::AlignVCenter | Qt::AlignHCenter | Qt::TextWordWrap, warning);
106 setMax(maxscale, maxrange);
116 if (maxscale == 0 || maxrange == 0)
124 auto domain = (
long double) maxscale;
125 auto range = (
long double) maxrange;
127 long double dx = 1.0;
128 long double e4 = 1.0E-8;
131 for (
int i = 0; i < maxrange; i++)
135 for (
uint i=0; i<10000 && (std::abs(dx) > e4); i++)
138 double y = (x *
t) -
range;
139 double yy =
t - (domain / (x + domain));
145 for (
int i = 1; i < (int) domain; i++)
147 int scaled = (int) floor(0.5 + (alpha *
log((
double(i) + alpha) / alpha)));
187 for (
int i = 0; i <
m_size.width(); i++)
189 auto indexTo = (
unsigned long)(index + step);
190 if (indexTo == (
unsigned long)(index))
191 indexTo = (
unsigned long)(index + 1);
224 for (
auto s = (
unsigned long)index; s < indexTo && s < node->
m_length; s++)
226 double adjHeight =
static_cast<double>(
m_size.height()) / 4.0;
227 double tmpL = ( ( node->
m_left ?
static_cast<double>(node->
m_left[s]) : 0.) *
228 adjHeight ) / 32768.0;
229 double tmpR = ( ( node->
m_right ?
static_cast<double>(node->
m_right[s]) : 0.) *
230 adjHeight ) / 32768.0;
232 valL = (tmpL > valL) ? tmpL : valL;
234 valL = (tmpL < valL) ? tmpL : valL;
236 valR = (tmpR > valR) ? tmpR : valR;
238 valR = (tmpR < valR) ? tmpR : valR;
241 if (valL != 0. || valR != 0.)
247 index = index + step;
253 for (
int i = 0; i <
m_size.width(); i++)
279 if (valL != 0. || valR != 0.)
289 for (
int i = 0; (unsigned) i <
m_magnitudes.size(); i++ )
299 for (
int i = 1; i <
m_size.width(); i++ )
306 (
static_cast<double>(
m_size.height()) / 4.0 );
336 p->setPen( QColor(
int(r), int(g), int(b) ) );
340 double adjHeight =
static_cast<double>(
m_size.height()) / 4.0;
379 p->setPen( QColor(
int(r), int(g), int(b) ) );
383 adjHeight =
static_cast<double>(
m_size.height()) * 3.0 / 4.0;
404 for (
int i = 0; i <
m_size.width(); i++)
406 auto indexTo = (
unsigned long)(index + step);
407 if (indexTo == (
unsigned long)index)
408 indexTo = (
unsigned long)(index + 1);
433 for (
auto s = (
unsigned long)index; s < indexTo && s < node->
m_length; s++)
435 double tmp = (
static_cast<double>(node->
m_left[s]) +
437 (
static_cast<double>(
m_size.height()) / 2.0 ) ) / 65536.0;
440 val = (
tmp > val) ?
tmp : val;
444 val = (
tmp < val) ?
tmp : val;
453 index = index + step;
459 for (
int i = 0; i <
m_size.width(); i++) {
479 for (
int i = 0; i <
m_size.width(); i++ )
489 for (
int i = 1; i <
m_size.width(); i++ ) {
494 double(
m_size.height() / 4 );
524 p->setPen(QColor(
int(r), int(g), int(b)));
528 double adjHeight =
static_cast<double>(
m_size.height()) / 2.0;
544 const QString &
name(
void)
const override
546 static QString s_name = QCoreApplication::translate(
"Visualizers",
570 const QString &
name(
void)
const override
572 static QString s_name = QCoreApplication::translate(
"Visualizers",
597 LOG(VB_GENERAL, LOG_INFO, QString(
"Spectrum : Being Initialised"));
601 m_lin = (myth_fftw_float*) av_malloc(
sizeof(myth_fftw_float)*
FFTW_N);
602 m_rin = (myth_fftw_float*) av_malloc(
sizeof(myth_fftw_float)*
FFTW_N);
603 m_lout = (myth_fftw_complex*) av_malloc(
sizeof(myth_fftw_complex)*(
FFTW_N/2+1));
604 m_rout = (myth_fftw_complex*) av_malloc(
sizeof(myth_fftw_complex)*(
FFTW_N/2+1));
606 m_lplan = fftw_plan_dft_r2c_1d(
FFTW_N, m_lin, (myth_fftw_complex_cast*)m_lout, FFTW_MEASURE);
607 m_rplan = fftw_plan_dft_r2c_1d(
FFTW_N, m_rin, (myth_fftw_complex_cast*)m_rout, FFTW_MEASURE);
610 Spectrum::~Spectrum()
621 fftw_destroy_plan(m_lplan);
622 fftw_destroy_plan(m_rplan);
625 void Spectrum::resize(
const QSize &newsize)
635 m_analyzerBarWidth = m_size.width() / 64;
637 if (m_analyzerBarWidth < 6)
638 m_analyzerBarWidth = 6;
640 m_scale.setMax(192, m_size.width() / m_analyzerBarWidth);
642 m_rects.resize( m_scale.range() );
645 for (
uint i = 0; i < (
uint)m_rects.size(); i++, w += m_analyzerBarWidth)
647 m_rects[i].setRect(w, m_size.height() / 2, m_analyzerBarWidth - 1, 1);
650 m_magnitudes.resize( m_scale.range() * 2 );
652 for (
uint os = m_magnitudes.size(); os < (
uint)m_magnitudes.size(); os++)
654 m_magnitudes[os] = 0.0;
657 m_scaleFactor = (
static_cast<double>(m_size.height()) / 2.0 ) /
661 template<
typename T> T
sq(T a) {
return a*a; };
672 QRect *rectsp = m_rects.data();
673 double *magnitudesp = m_magnitudes.data();
680 fast_real_set_from_short(m_lin, node->
m_left, i);
682 fast_real_set_from_short(m_rin, node->
m_right, i);
685 fast_reals_set(m_lin + i, m_rin + i, 0,
FFTW_N - i);
687 fftw_execute(m_lplan);
688 fftw_execute(m_rplan);
692 for (i = 0; (int)i < m_rects.size(); i++, w += m_analyzerBarWidth)
697 double tmp = 2 *
sq(real(m_lout[index]));
698 double magL = (
tmp > 1.) ? (
log(
tmp) - 22.0) * m_scaleFactor : 0.;
700 tmp = 2 *
sq(real(m_rout[index]));
701 double magR = (
tmp > 1.) ? (
log(
tmp) - 22.0) * m_scaleFactor : 0.;
704 double adjHeight =
static_cast<double>(m_size.height()) / 2.0;
705 if (magL > adjHeight)
709 if (magL < magnitudesp[i])
711 tmp = magnitudesp[i] - m_falloff;
723 if (magR > adjHeight)
727 if (magR < magnitudesp[i + m_scale.range()])
729 tmp = magnitudesp[i + m_scale.range()] - m_falloff;
741 if (magR != 1 || magL != 1)
746 magnitudesp[i] = magL;
747 magnitudesp[i + m_scale.range()] = magR;
748 rectsp[i].setTop( m_size.height() / 2 - int( magL ) );
749 rectsp[i].setBottom( m_size.height() / 2 + int( magR ) );
767 bool Spectrum::draw(QPainter *
p,
const QColor &
back)
775 QRect *rectsp = m_rects.data();
777 p->fillRect(0, 0, m_size.width(), m_size.height(),
back);
778 for (
uint i = 0; i < (
uint)m_rects.size(); i++)
780 double per = double( rectsp[i].height() - 2 ) / double( m_size.height() );
782 per =
clamp(per, 1.0, 0.0);
784 double r = m_startColor.red() +
785 (m_targetColor.red() - m_startColor.red()) * (per * per);
786 double g = m_startColor.green() +
787 (m_targetColor.green() - m_startColor.green()) * (per * per);
788 double b = m_startColor.blue() +
789 (m_targetColor.blue() - m_startColor.blue()) * (per * per);
791 r =
clamp(r, 255.0, 0.0);
792 g =
clamp(g, 255.0, 0.0);
793 b =
clamp(b, 255.0, 0.0);
795 if(rectsp[i].height() > 4)
796 p->fillRect(rectsp[i], QColor(
int(r),
int(g),
int(b)));
802 static class SpectrumFactory :
public VisFactory
805 const QString &
name(
void)
const override
807 static QString s_name = QCoreApplication::translate(
"Visualizers",
820 return new Spectrum();
831 m_fakeHeight = m_numberOfSquares * m_analyzerBarWidth;
834 void Squares::resize (
const QSize &newsize) {
836 Spectrum::resize (QSize (m_fakeHeight, m_fakeHeight));
838 m_actualSize = newsize;
841 void Squares::drawRect(QPainter *
p, QRect *rect,
int i,
int c,
int w,
int h)
844 int correction = (m_actualSize.width() % m_rects.size ()) / 2;
845 int x = ((i / 2) * w) + correction;
851 per = double(m_fakeHeight - rect->top()) / double(m_fakeHeight);
856 per = double(rect->bottom()) / double(m_fakeHeight);
859 per =
clamp(per, 1.0, 0.0);
861 double r = m_startColor.red() +
862 (m_targetColor.red() - m_startColor.red()) * (per * per);
863 double g = m_startColor.green() +
864 (m_targetColor.green() - m_startColor.green()) * (per * per);
865 double b = m_startColor.blue() +
866 (m_targetColor.blue() - m_startColor.blue()) * (per * per);
868 r =
clamp(r, 255.0, 0.0);
869 g =
clamp(g, 255.0, 0.0);
870 b =
clamp(b, 255.0, 0.0);
872 p->fillRect (x, y, w, h, QColor (
int(r),
int(g),
int(b)));
875 bool Squares::draw(QPainter *
p,
const QColor &
back)
877 p->fillRect (0, 0, m_actualSize.width(), m_actualSize.height(),
back);
878 int w = m_actualSize.width() / (m_rects.size() / 2);
880 int center = m_actualSize.height() / 2;
882 QRect *rectsp = m_rects.data();
883 for (
uint i = 0; i < (
uint)m_rects.size(); i++)
884 drawRect(
p, &(rectsp[i]), i, center, w, h);
889 static class SquaresFactory :
public VisFactory
892 const QString &
name(
void)
const override
894 static QString s_name = QCoreApplication::translate(
"Visualizers",
907 return new Squares();
911 #endif // FFTW3_SUPPORT
918 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Being Initialised"));
923 double sample_rate = 44100.0;
927 double concert_A = 440.0;
928 double semi_tone = pow(2.0, 1.0/12.0);
931 double bottom_A = concert_A / 2.0 / 2.0 / 2.0 / 2.0;
933 double current_freq = bottom_A;
940 double samples_required = sample_rate/current_freq * 20.0;
941 if (samples_required > sample_rate/4.0)
944 samples_required = sample_rate/4.0;
946 if (samples_required < sample_rate/(
double)
m_fps * 0.75)
948 samples_required = sample_rate/(double)
m_fps * 0.75;
953 current_freq *= semi_tone;
993 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Being Resized"));
998 double key_unit_size = (double)
m_size.width() / 54.0;
999 if (key_unit_size < 10.0)
1000 key_unit_size = 10.0;
1002 double white_width_pct = .8;
1003 double black_width_pct = .6;
1004 double black_offset_pct = .05;
1006 double white_height_pct = 6;
1007 double black_height_pct = 4;
1011 double left = (double)
m_size.width() / 2.0 - (4.0*7.0 + 3.5) * key_unit_size;
1012 double top_of_keys = (double)
m_size.height() / 2.0 - key_unit_size * white_height_pct / 2.0;
1018 int note = ((int)key - 3 + 12) % 12;
1021 left += key_unit_size*7.0;
1024 double center = 0.0;
1025 double offset = 0.0;
1026 bool is_black =
false;
1030 case 0: center = 0.5;
break;
1031 case 1: center = 1.0; is_black =
true; offset = -1;
break;
1032 case 2: center = 1.5;
break;
1033 case 3: center = 2.0; is_black =
true; offset = +1;
break;
1034 case 4: center = 2.5;
break;
1035 case 5: center = 3.5;
break;
1036 case 6: center = 4.0; is_black =
true; offset = -2;
break;
1037 case 7: center = 4.5;
break;
1038 case 8: center = 5.0; is_black =
true; offset = 0;
break;
1039 case 9: center = 5.5;
break;
1040 case 10: center = 6.0; is_black =
true; offset = 2;
break;
1041 case 11: center = 6.5;
break;
1045 double width = (is_black ? black_width_pct:white_width_pct) * key_unit_size;
1046 double height = (is_black? black_height_pct:white_height_pct) * key_unit_size;
1049 left + center * key_unit_size
1051 + (is_black ? (offset * black_offset_pct * key_unit_size):0.0),
1091 bool allZero =
true;
1101 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Node offset=%1 too far backwards : NEW SONG").
arg(node->
m_offset.count()));
1108 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Already seen node offset=%1, returning without processing").
arg(node->
m_offset.count()));
1117 for (
uint i = 0; i < n; i++)
1124 for (
uint i = 0; i < n; i++)
1132 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Hit an empty node, and returning empty-handed"));
1142 for (
uint i = 0; i < n; i++)
1156 if (n_samples >
m_pianoData[key].samples_process_before_display_update)
1172 if(magnitude_av > 0.0F)
1174 magnitude_av =
log(magnitude_av);
1182 if (magnitude_av < 0.0F)
1194 if (
m_pianoData[key].max_magnitude_seen < magnitude_av)
1198 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Updated Key %1 from %2 samples, magnitude=%3")
1199 .
arg(key).
arg(n_samples).
arg(magnitude_av));
1246 for (
uint key = 0; key < n; key++)
1248 if (
m_pianoData[key].max_magnitude_seen <
static_cast<float>(mag))
1263 for (
int key_i = n - 1; key_i >= 0; key_i--)
1266 if (
m_pianoData[key].max_magnitude_seen <
static_cast<float>(mag))
1282 for (
uint key = 0; key < n; key++)
1285 if (magnitude_max < mag)
1286 magnitude_max = mag;
1288 magnitudep[key] = mag;
1292 for (
uint key = 0; key < n; key++)
1297 double per = magnitudep[key] / magnitude_max;
1298 per =
clamp(per, 1.0, 0.0);
1302 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Display key %1, magnitude=%2, seen=%3")
1309 p->fillRect(rectsp[key], QColor(
int(r), int(g), int(b)));
1313 for (
uint key = 0; key < n; key++)
1318 double per = magnitudep[key]/magnitude_max;
1319 per =
clamp(per, 1.0, 0.0);
1328 p->fillRect(rectsp[key], QColor(
int(r), int(g), int(b)));
1337 const QString &
name(
void)
const override
1339 static QString s_name = QCoreApplication::translate(
"Visualizers",
1357 m_lastCycle(QDateTime::currentDateTime())
1453 #define ALBUMARTCYCLETIME 10
1482 if (imageFilename.startsWith(
"myth://"))
1484 auto *rf =
new RemoteFile(imageFilename,
false,
false, 0ms);
1487 bool ret = rf->SaveAs(data);
1492 art.loadFromData(data);
1495 if (!imageFilename.isEmpty())
1496 art.load(imageFilename);
1505 m_image = art.scaled(
m_size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
1530 const QString &
name(
void)
const override
1532 static QString s_name = QCoreApplication::translate(
"Visualizers",
1576 const QString &
name(
void)
const override
1578 static QString s_name = QCoreApplication::translate(
"Visualizers",