| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- #include <QPaintEvent>
- #include <QPainter>
- #include <QWidget>
- #include <QtMath>
- #include <algorithm>
- #include "audio_effect_helper.h"
- #define MAX_AUDIO_VAULE 0xffff // unsigned 16bit pcm audio max value
- BarHelper::BarHelper()
- {
- m_datafmt.sample_fmt = 16;
- m_datafmt.channel = 1;
- QLinearGradient gradient(QPointF(50, 200), QPointF(50, 0));
- gradient.setColorAt(0.0, Qt::white);
- gradient.setColorAt(1.0, QColor(0xa6, 0xce, 0x39));
- m_background = QBrush(QColor(64, 32, 64));
- m_brush = QBrush(gradient);
- m_pen = QPen(Qt::green, 2); // QPen(Qt::black);
- m_textPen = QPen(Qt::white);
- m_textFont.setPixelSize(50);
- }
- void BarHelper::draw_data_bar(QPainter* painter, std::vector<int>& data, int n, int w, int h, int h_inter)
- {
- assert(data.size() == n);
- auto w_step = (w - (n - 1) * h_inter) * 1.0 / n;
- for (int i = 0; i < n; ++i)
- {
- auto top = data[i]; // rand() % height;
- QRectF rt(i * (w_step + h_inter), h - top, w_step, top);
- painter->drawRect(rt);
- }
- }
- void BarHelper::draw_data_line(QPainter* painter, std::vector<int>& data, int n, int w, int h, int h_inter)
- {
- painter->setPen(m_pen);
- auto w_step = (w - (n - 1) * h_inter) * 1.0 / n;
- for (size_t i = 0; i < n - 1; ++i)
- {
- qreal x1 = i * (w_step + h_inter);
- qreal y1 = h - data[i];
- qreal x2 = x1 + (w_step + h_inter);
- qreal y2 = h - data[i + 1];
- // painter->drawRect(rt);
- QLine line = QLine(QPoint(x1, y1), QPoint(x2, y2));
- painter->drawLine(line);
- }
- }
- void BarHelper::draw_data_arc(QPainter* painter, std::vector<int>& data, int n, int w, int h)
- {
- assert(data.size() == n);
- const qreal s_radius = 50.0;
- QPointF center(w * 1.0 / 2, h * 1.0 / 2);
- painter->translate(center);
- painter->setBrush(QBrush(Qt::red));
- const int spanAngle = 360 / n * 16;
- for (int i = 0; i < n; ++i)
- {
- qreal radius = data[i] + s_radius;
- QRect bounds(-radius, -radius, 2 * radius, 2 * radius);
- int startAngle = 360 * i / n * 16;
- painter->drawArc(bounds, startAngle, spanAngle);
- }
- }
- void BarHelper::draw_data_polygon(QPainter* painter, std::vector<int>& data, int n, int w, int h, int r_offset)
- {
- assert(data.size() == n);
- QPointF center(w * 1.0 / 2, h * 1.0 / 2);
- painter->translate(center);
- const int pt_size = 4;
- const int inter_a = 0;
- const qreal s_radius = r_offset;
- QPointF points[pt_size] = {};
- for (int i = 0; i < n; ++i)
- {
- qreal radius = data[i] + s_radius;
- float startAngle = 360 * i / n;
- float stopAngle = 360 * (i + 1) / n - inter_a;
- float start_d = qDegreesToRadians(startAngle);
- float stop_d = qDegreesToRadians(stopAngle);
- points[0] = QPointF(qCos(start_d) * s_radius, qSin(start_d) * s_radius);
- points[1] = QPointF(qCos(start_d) * radius, qSin(start_d) * radius);
- points[2] = QPointF(qCos(stop_d) * radius, qSin(stop_d) * radius);
- points[3] = QPointF(qCos(stop_d) * s_radius, qSin(stop_d) * s_radius);
- painter->drawPolygon(points, 4);
- }
- }
- void BarHelper::draw_data_style(QPainter* painter, const QRect& rt, const AudioData& data)
- {
- int width = rt.width();
- int height = rt.height();
- int h_inter = 2;
- assert(data.len <= BUFFER_LEN);
- std::vector<int> v_data;
- get_data(data, v_data);
- if (v_data.size() == 0)
- return;
- int n = 128;
- normal_overzero(v_data);
- if (m_visualFmt.vType == e_VtSampleing)
- {
- data_sample(v_data, n);
- normal_audio_to_size(v_data, height);
- }
- else
- {
- data_frequency(v_data, n);
- }
- if (m_visualFmt.gType == e_GtBar)
- {
- draw_data_bar(painter, v_data, n, width, height, h_inter);
- }
- else if (m_visualFmt.gType == e_GtLine)
- {
- draw_data_line(painter, v_data, n, width, height, h_inter);
- }
- else if (m_visualFmt.gType == e_GtPie)
- {
- int r_offset = 30;
- normal_to_size(v_data, qMin(width / 2 - r_offset, height / 2 - r_offset));
- draw_data_polygon(painter, v_data, n, width, height, r_offset);
- }
- else
- {
- qDebug() << "Not handled yet.\n";
- }
- }
- void BarHelper::paint(QPainter* painter, QPaintEvent* event, const AudioData& data)
- {
- auto rt = event->rect();
- painter->fillRect(rt, m_background);
- // painter->translate(0, -1 * rt.height() / 2);
- painter->save();
- painter->setBrush(m_brush);
- draw_data_style(painter, rt, data);
- painter->restore();
- }
- void BarHelper::get_data(const AudioData& data, std::vector<int>& v, bool left) const
- {
- v.clear();
- // unsigned 16bit
- const int16_t* p = (int16_t*)data.buffer;
- uint32_t len = data.len / sizeof(int16_t);
- int start = left ? 0 : 1;
- for (uint32_t i = start; i < len; i += 2)
- v.push_back(*(p + i));
- // qDebug() << "data size: " << v.size();
- }
- /* v data samples to num*/
- void BarHelper::data_sample_old(std::vector<int>& v, const uint32_t num)
- {
- auto size = v.size();
- if (num <= 0 || size < num)
- {
- v.insert(v.end(), num - size, 0);
- return;
- }
- auto numItems = size / num;
- if (numItems <= 1)
- {
- v.erase(v.begin() + num, v.end());
- return;
- }
- for (size_t i = 0; i < num; i++)
- {
- auto& value = v[i];
- value = v[i * numItems];
- /*for (int j = 1; j < numItems; j++) {
- value += v[i * numItems + j];
- }*/
- }
- v.erase(v.begin() + num, v.end());
- }
- void BarHelper::data_sample(std::vector<int>& v, const uint32_t num)
- {
- auto size = v.size();
- if (num <= 0 || size < num)
- {
- v.insert(v.end(), num - size, 0);
- return;
- }
- auto numItems = size / num;
- if (numItems <= 1)
- {
- v.erase(v.begin() + num, v.end());
- return;
- }
- while (v.size() / num >= 2)
- {
- binary_data(v);
- }
- v.erase(v.begin() + num, v.end());
- }
- void BarHelper::binary_data(std::vector<int>& v)
- {
- auto j = 0;
- for (size_t i = 0; i < v.size(); i += 2)
- v[j++] = v[i];
- v.erase(v.begin() + j, v.end());
- }
- void BarHelper::normal_overzero(std::vector<int>& v)
- {
- int min = *std::min_element(v.begin(), v.end());
- // int max = *std::max_element(v.begin(), v.end());
- // qDebug() << "before size: " << v.size() << ",Max value: " << max << ",Min
- // value: " << min;
- if (min < 0)
- {
- min *= -1;
- for (int& x : v)
- x += min;
- }
- }
- void BarHelper::normal_audio_to_size(std::vector<int>& v, const int size)
- {
- if (size <= 0)
- return;
- #if 0
- static int maxValue = 0xff;
- int max = *std::max_element(v.begin(), v.end());
- if (maxValue < max)
- maxValue = max;
- #else
- int maxValue = MAX_AUDIO_VAULE;
- #endif
- for (auto& x : v)
- {
- x = (x > maxValue) ? maxValue : x;
- x = (x * size) / maxValue;
- }
- }
- void BarHelper::normal_to_size(std::vector<int>& v, const int size)
- {
- if (size <= 0)
- return;
- int maxValue = *std::max_element(v.begin(), v.end());
- if (size >= maxValue)
- return;
- for (auto& x : v)
- {
- x = (x > size) ? size : x;
- x = (x * size) / maxValue;
- }
- }
- void BarHelper::normal_data(std::vector<int>& v, const int height)
- {
- normal_overzero(v);
- normal_audio_to_size(v, height);
- }
- void BarHelper::data_frequency(std::vector<int>& v, const uint32_t num)
- {
- auto size = v.size();
- if (num <= 0 || size < num)
- {
- v.insert(v.end(), num - size, 0);
- return;
- }
- std::vector<int> res(num, 0);
- #if 0
- static uint32_t maxValue = 0xff;
- int max = *std::max_element(v.begin(), v.end());
- if (maxValue < max)
- maxValue = max;
- #else
- int maxValue = MAX_AUDIO_VAULE;
- #endif
- const uint16_t step = ceil((maxValue + 1) * 1.0 / num);
- for (const auto& i : v)
- {
- uint32_t index = (i % maxValue) / step;
- assert(index < num);
- res[index % num]++;
- }
- v = res;
- }
|