MythTV  master
videovisualspectrum.cpp
Go to the documentation of this file.
1 // QT
2 #include <QPen>
3 
4 // MythTV
5 #include "videovisualspectrum.h"
6 
7 // FFmpeg
8 #define FFTW_N 512
9 extern "C" {
10 #include "libavutil/mem.h"
11 }
12 
13 // Std
14 #include <algorithm>
15 
17  : VideoVisual(Audio, Render)
18 {
19  m_lin = static_cast<myth_fftw_float*>(av_malloc(sizeof(myth_fftw_float)*FFTW_N));
20  m_rin = static_cast<myth_fftw_float*>(av_malloc(sizeof(myth_fftw_float)*FFTW_N));
21  m_lout = static_cast<myth_fftw_complex*>(av_malloc(sizeof(myth_fftw_complex)*(FFTW_N/2+1)));
22  m_rout = static_cast<myth_fftw_complex*>(av_malloc(sizeof(myth_fftw_complex)*(FFTW_N/2+1)));
23 
24  m_lplan = fftw_plan_dft_r2c_1d(FFTW_N, m_lin, reinterpret_cast<myth_fftw_complex_cast*>(m_lout), FFTW_MEASURE);
25  m_rplan = fftw_plan_dft_r2c_1d(FFTW_N, m_rin, reinterpret_cast<myth_fftw_complex_cast*>(m_rout), FFTW_MEASURE);
26 }
27 
29 {
30  av_freep(&m_lin);
31  av_freep(&m_rin);
32  av_freep(&m_lout);
33  av_freep(&m_rout);
34  fftw_destroy_plan(m_lplan);
35  fftw_destroy_plan(m_rplan);
36 }
37 
38 template<typename T> T sq(T a) { return a*a; };
39 
40 void VideoVisualSpectrum::Draw(const QRect Area, MythPainter* Painter, QPaintDevice* Device)
41 {
42  if (m_disabled)
43  return;
44 
45  uint i = 0;
46  {
47  QMutexLocker locker(mutex());
48  VisualNode* node = GetNode();
49  if (Area.isEmpty() || !Painter)
50  return;
51 
52  if (!Initialise(Area))
53  return;
54 
55  if (node)
56  {
57  i = static_cast<uint>(node->m_length);
58  fast_real_set_from_short(m_lin, node->m_left, node->m_length);
59  if (node->m_right)
60  fast_real_set_from_short(m_rin, node->m_right, node->m_length);
61  }
62  }
63 
64  fast_reals_set(m_lin + i, m_rin + i, 0, FFTW_N - i);
65  fftw_execute(m_lplan);
66  fftw_execute(m_rplan);
67 
68  double falloff = std::clamp(((static_cast<double>(SetLastUpdate().count())) / 40.0) * m_falloff, 0.0, 2048.0);
69  for (int l = 0, r = m_scale.range(); l < m_scale.range(); l++, r++)
70  {
71  int index = m_scale[l];
72 
73  // The 1D output is Hermitian symmetric (Yk = Yn-k) so Yn = Y0 etc.
74  // The dft_r2c_1d plan doesn't output these redundant values
75  // and furthermore they're not allocated in the ctor
76  double tmp = 2 * sq(real(m_lout[index]));
77  double magL = (tmp > 1.) ? (log(tmp) - 22.0) * m_scaleFactor : 0.;
78 
79  tmp = 2 * sq(real(m_rout[index]));
80  double magR = (tmp > 1.) ? (log(tmp) - 22.0) * m_scaleFactor : 0.;
81 
82  if (magL > m_range)
83  magL = 1.0;
84 
85  if (magL < m_magnitudes[l])
86  {
87  tmp = m_magnitudes[l] - falloff;
88  if (tmp < magL)
89  tmp = magL;
90  magL = tmp;
91  }
92 
93  if (magL < 1.0)
94  magL = 1.0;
95 
96  if (magR > m_range)
97  magR = 1.0;
98 
99  if (magR < m_magnitudes[r])
100  {
101  tmp = m_magnitudes[r] - falloff;
102  if (tmp < magR)
103  tmp = magR;
104  magR = tmp;
105  }
106 
107  if (magR < 1.0)
108  magR = 1.0;
109 
110  m_magnitudes[l] = magL;
111  m_magnitudes[r] = magR;
112  }
113 
114  DrawPriv(Painter, Device);
115 }
116 
118 {
119  std::fill(m_magnitudes.begin(), m_magnitudes.end(), 0.0);
121 }
122 
123 void VideoVisualSpectrum::DrawPriv(MythPainter* Painter, QPaintDevice* Device)
124 {
125  static const QBrush kBrush(QColor(0, 0, 200, 180));
126  static const QPen kPen(QColor(255, 255, 255, 255));
127  double range = m_area.top() + m_area.height() / 2.0;
128  int count = m_scale.range();
129  Painter->Begin(Device);
130  for (int i = 0; i < count; i++)
131  {
132  m_rects[i].setTop(static_cast<int>(range - static_cast<int>(m_magnitudes[i])));
133  m_rects[i].setBottom(static_cast<int>(range + static_cast<int>(m_magnitudes[i + count])));
134  if (m_rects[i].height() > 4)
135  Painter->DrawRect(m_rects[i], kBrush, kPen, 255);
136  }
137  Painter->End();
138 }
139 
140 bool VideoVisualSpectrum::Initialise(const QRect Area)
141 {
142  if (Area == m_area)
143  return true;
144 
145  m_area = Area;
146  m_barWidth = m_area.width() / m_numSamples;
147  if (m_barWidth < 6)
148  m_barWidth = 6;
149  m_scale.setMax(192, m_area.width() / m_barWidth);
150 
151  m_magnitudes.resize(m_scale.range() * 2);
152  std::fill(m_magnitudes.begin(), m_magnitudes.end(), 0.0);
153  InitialisePriv();
154  return true;
155 }
156 
158 {
159  m_range = m_area.height() / 2.0;
160  m_rects.resize(m_scale.range());
161  int y = m_area.top() + static_cast<int>(m_range);
162  for (int i = 0, x = m_area.left(); i < m_rects.size(); i++, x+= m_barWidth)
163  m_rects[i].setRect(x, y, m_barWidth - 1, 1);
164 
165  m_scaleFactor = (static_cast<double>(m_area.height()) / 2.0) / log(static_cast<double>(FFTW_N));
166  m_falloff = static_cast<double>(m_area.height()) / 150.0;
167 
168  LOG(VB_GENERAL, LOG_INFO, DESC + QString("Initialised Spectrum with %1 bars").arg(m_scale.range()));
169  return true;
170 }
171 
173 {
174  public:
175  const QString &name() const override;
176  VideoVisual *Create(AudioPlayer* Audio, MythRender* Render) const override;
177  bool SupportedRenderer(RenderType /*Type*/) override { return true; }
179 
180 const QString& VideoVisualSpectrumFactory::name() const
181 {
182  static QString s_name(SPECTRUM_NAME);
183  return s_name;
184 }
185 
187 {
188  return new VideoVisualSpectrum(Audio, Render);
189 }
VideoVisualSpectrum::m_lplan
fftw_plan m_lplan
Definition: videovisualspectrum.h:31
VideoVisualSpectrum::m_scale
LogScale m_scale
Definition: videovisualspectrum.h:27
VideoVisualSpectrum::InitialisePriv
virtual bool InitialisePriv()
Definition: videovisualspectrum.cpp:157
AudioPlayer
Definition: audioplayer.h:24
VisualNode
Definition: videovisual.h:24
VideoVisualSpectrum::m_rects
QVector< QRect > m_rects
Definition: videovisualspectrum.h:39
VideoVisual::prepare
void prepare() override
Definition: videovisual.cpp:76
VideoVisual::m_disabled
bool m_disabled
Definition: videovisual.h:70
VideoVisualSpectrumFactory::name
const QString & name() const override
Definition: videovisualspectrum.cpp:180
arg
arg(title).arg(filename).arg(doDelete))
VideoVisualSpectrum::m_rin
myth_fftw_float * m_rin
Definition: videovisualspectrum.h:34
VideoVisualSpectrum::Initialise
virtual bool Initialise(QRect Area)
Definition: videovisualspectrum.cpp:140
VideoVisualSpectrum::m_magnitudes
QVector< double > m_magnitudes
Definition: videovisualspectrum.h:25
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythPainter::DrawRect
virtual void DrawRect(QRect area, const QBrush &fillBrush, const QPen &linePen, int alpha)
Definition: mythpainter.cpp:157
FFTW_N
#define FFTW_N
Definition: videovisualspectrum.cpp:8
Device
A device containing images (ie. USB stick, CD, storage group etc)
Definition: imagemanager.cpp:33
VideoVisualSpectrum::m_lout
myth_fftw_complex * m_lout
Definition: videovisualspectrum.h:35
VideoVisualSpectrum::m_lin
myth_fftw_float * m_lin
Definition: videovisualspectrum.h:33
sq
T sq(T a)
Definition: videovisualspectrum.cpp:38
VisualNode::m_left
short * m_left
Definition: videovisual.h:36
VideoVisualSpectrum::m_rout
myth_fftw_complex * m_rout
Definition: videovisualspectrum.h:36
tmp
static guint32 * tmp
Definition: goom_core.cpp:31
VideoVisualSpectrum::m_barWidth
int m_barWidth
Definition: videovisualspectrum.h:40
VideoVisualSpectrum
Definition: videovisualspectrum.h:9
DESC
#define DESC
Definition: videovisual.h:19
VideoVisualSpectrum::m_range
double m_range
Definition: videovisualspectrum.h:26
VisualNode::m_right
short * m_right
Definition: videovisual.h:37
LogScale::range
int range() const
Definition: videovisualdefs.h:20
VideoVisualFactory
Definition: videovisual.h:77
MythTV::Visual::mutex
QMutex * mutex()
Definition: visual.h:26
LogScale::setMax
void setMax(int maxscale, int maxrange)
Definition: videovisualdefs.h:22
clamp
float clamp(float val, float minimum, float maximum)
Definition: mythmiscutil.h:59
VideoVisualSpectrumFactory::SupportedRenderer
bool SupportedRenderer(RenderType) override
Definition: videovisualspectrum.cpp:177
VideoVisualSpectrum::m_falloff
double m_falloff
Definition: videovisualspectrum.h:29
RenderType
RenderType
Definition: mythrender_base.h:15
VideoVisualSpectrum::VideoVisualSpectrum
VideoVisualSpectrum(AudioPlayer *Audio, MythRender *Render)
Definition: videovisualspectrum.cpp:16
VideoVisualSpectrumFactory
Definition: videovisualspectrum.cpp:172
uint
unsigned int uint
Definition: compat.h:140
MythPainter::End
virtual void End()
Definition: mythpainter.h:53
VideoVisualSpectrum::~VideoVisualSpectrum
~VideoVisualSpectrum() override
Definition: videovisualspectrum.cpp:28
VideoVisualSpectrumFactory::Create
VideoVisual * Create(AudioPlayer *Audio, MythRender *Render) const override
Definition: videovisualspectrum.cpp:186
VisualNode::m_length
long m_length
Definition: videovisual.h:38
VideoVisualSpectrum::m_numSamples
int m_numSamples
Definition: videovisualspectrum.h:24
SPECTRUM_NAME
#define SPECTRUM_NAME
Definition: videovisualspectrum.h:7
MythRender
Definition: mythrender_base.h:23
MythPainter
Definition: mythpainter.h:32
common.utilities.log
def log(debug, txt)
Definition: utilities.py:7
VideoVisualSpectrumFactory
VideoVisualSpectrumFactory VideoVisualSpectrumFactory
videovisualspectrum.h
VideoVisualSpectrum::prepare
void prepare() override
Definition: videovisualspectrum.cpp:117
VideoVisual
Definition: videovisual.h:42
VideoVisualSpectrum::Draw
void Draw(QRect Area, MythPainter *Painter, QPaintDevice *Device) override
Definition: videovisualspectrum.cpp:40
VideoVisualSpectrum::DrawPriv
virtual void DrawPriv(MythPainter *Painter, QPaintDevice *Device)
Definition: videovisualspectrum.cpp:123
VideoVisualSpectrum::m_rplan
fftw_plan m_rplan
Definition: videovisualspectrum.h:32
VideoVisualSpectrum::m_scaleFactor
double m_scaleFactor
Definition: videovisualspectrum.h:28
VideoVisual::m_area
QRect m_area
Definition: videovisual.h:71
VideoVisual::GetNode
VisualNode * GetNode(void)
Definition: videovisual.cpp:82
MythPainter::Begin
virtual void Begin(QPaintDevice *)
Definition: mythpainter.h:52
VideoVisual::SetLastUpdate
std::chrono::milliseconds SetLastUpdate(void)
Definition: videovisual.cpp:57