"Fossies" - the Fresh Open Source Software Archive

Member "ssr-0.4.2/src/GUI/AudioPreviewer.cpp" (18 May 2020, 5149 Bytes) of package /linux/privat/ssr-0.4.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "AudioPreviewer.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.4.1_vs_0.4.2.

    1 /*
    2 Copyright (c) 2012-2020 Maarten Baert <maarten-baert@hotmail.com>
    3 
    4 This file is part of SimpleScreenRecorder.
    5 
    6 SimpleScreenRecorder is free software: you can redistribute it and/or modify
    7 it under the terms of the GNU General Public License as published by
    8 the Free Software Foundation, either version 3 of the License, or
    9 (at your option) any later version.
   10 
   11 SimpleScreenRecorder is distributed in the hope that it will be useful,
   12 but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 GNU General Public License for more details.
   15 
   16 You should have received a copy of the GNU General Public License
   17 along with SimpleScreenRecorder.  If not, see <http://www.gnu.org/licenses/>.
   18 */
   19 
   20 #include "AudioPreviewer.h"
   21 
   22 #include "SampleCast.h"
   23 #include "Logger.h"
   24 
   25 AudioPreviewer::AudioPreviewer(QWidget* parent)
   26     : QWidget(parent) {
   27 
   28     {
   29         SharedLock lock(&m_shared_data);
   30         lock->m_channel_data.resize(1);
   31         lock->m_next_samples = 0;
   32         lock->m_next_frame_time = hrt_time_micro();
   33         lock->m_frame_rate = 20;
   34     }
   35 
   36     setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
   37 
   38     connect(this, SIGNAL(NeedsUpdate()), this, SLOT(update()), Qt::QueuedConnection);
   39 
   40 }
   41 
   42 AudioPreviewer::~AudioPreviewer() {
   43 
   44     // disconnect
   45     ConnectAudioSource(NULL);
   46 
   47 }
   48 
   49 void AudioPreviewer::Reset() {
   50     SharedLock lock(&m_shared_data);
   51     lock->m_channel_data.clear();
   52     lock->m_channel_data.resize(1);
   53     lock->m_next_samples = 0;
   54     emit NeedsUpdate();
   55 }
   56 
   57 void AudioPreviewer::SetFrameRate(unsigned int frame_rate) {
   58     SharedLock lock(&m_shared_data);
   59     lock->m_frame_rate = std::max(1u, frame_rate);
   60 }
   61 
   62 void AudioPreviewer::ReadAudioSamples(unsigned int channels, unsigned int sample_rate, AVSampleFormat format, unsigned int sample_count, const uint8_t* data, int64_t timestamp) {
   63     Q_UNUSED(sample_rate);
   64     Q_UNUSED(timestamp);
   65     SharedLock lock(&m_shared_data);
   66 
   67     if(sample_count == 0)
   68         return;
   69 
   70     // save the samples
   71     lock->m_channel_data.resize(channels);
   72     switch(format) {
   73         case AV_SAMPLE_FMT_S16: {
   74             const int16_t *data_in = (const int16_t*) data;
   75             for(size_t i = 0; i < sample_count; ++i) {
   76                 for(unsigned int c = 0; c < channels; ++c) {
   77                     lock->m_channel_data[c].Analyze(*(data_in++));
   78                 }
   79             }
   80             break;
   81         }
   82         case AV_SAMPLE_FMT_S32: {
   83             const int32_t *data_in = (const int32_t*) data;
   84             for(size_t i = 0; i < sample_count; ++i) {
   85                 for(unsigned int c = 0; c < channels; ++c) {
   86                     lock->m_channel_data[c].Analyze(*(data_in++));
   87                 }
   88             }
   89             break;
   90         }
   91         case AV_SAMPLE_FMT_FLT: {
   92             const float *data_in = (const float*) data;
   93             for(size_t i = 0; i < sample_count; ++i) {
   94                 for(unsigned int c = 0; c < channels; ++c) {
   95                     lock->m_channel_data[c].Analyze(*(data_in++));
   96                 }
   97             }
   98             break;
   99         }
  100         default: {
  101             assert(false); // unsupported sample format
  102             break;
  103         }
  104     }
  105     lock->m_next_samples += sample_count;
  106 
  107     // check the time
  108     int64_t time = hrt_time_micro();
  109     if(time < lock->m_next_frame_time)
  110         return;
  111     lock->m_next_frame_time = std::max(lock->m_next_frame_time + 1000000 / lock->m_frame_rate, time);
  112 
  113     // move the low/high values from 'next' to 'current'
  114     for(unsigned int c = 0; c < channels; ++c) {
  115         lock->m_channel_data[c].m_current_peak = lock->m_channel_data[c].m_next_peak;
  116         lock->m_channel_data[c].m_current_rms = sqrt(lock->m_channel_data[c].m_next_rms / (float) lock->m_next_samples);
  117         lock->m_channel_data[c].m_next_peak = 0.0f;
  118         lock->m_channel_data[c].m_next_rms = 0.0f;
  119     }
  120     lock->m_next_samples = 0;
  121 
  122     emit NeedsUpdate();
  123 
  124 }
  125 
  126 void AudioPreviewer::paintEvent(QPaintEvent* event) {
  127     Q_UNUSED(event);
  128     QPainter painter(this);
  129 
  130     std::vector<ChannelData> channel_data;
  131     {
  132         SharedLock lock(&m_shared_data);
  133         channel_data = lock->m_channel_data;
  134     }
  135 
  136     painter.fillRect(rect(), QColor(200, 200, 200));
  137 
  138     int w = width() - 1, h = height() - 1;
  139 
  140     QLinearGradient grad1(0.0, 0.0, (double) width(), 0.0);
  141     grad1.setColorAt(0.0, QColor(0, 255, 0));
  142     grad1.setColorAt(0.5, QColor(255, 255, 0));
  143     grad1.setColorAt(1.0, QColor(255, 0, 0));
  144     QLinearGradient grad2(0.0, 0.0, (double) width(), 0.0);
  145     grad2.setColorAt(0.0, QColor(0, 150, 0));
  146     grad2.setColorAt(0.5, QColor(150, 150, 0));
  147     grad2.setColorAt(1.0, QColor(150, 0, 0));
  148     painter.setPen(Qt::NoPen);
  149     unsigned int n = channel_data.size();
  150     for(unsigned int c = 0; c < n; ++c) {
  151         // the scale goes down to 80dB which corresponds to 1.0e-4 (for sound pressure, 20dB = 10x)
  152         float val_peak = log10(fmax(1.0e-4f, channel_data[c].m_current_peak)) / 4.0f + 1.0f;
  153         float val_rms = log10(fmax(1.0e-4f, channel_data[c].m_current_rms)) / 4.0f + 1.0f;
  154         int x1 = 0, x2 = (int) round((float) w * val_rms), x3 = (int) round((float) w * val_peak);
  155         int y1 = h * c / n, y2 = h * (c + 1) / n;
  156         painter.setBrush(grad1);
  157         painter.drawRect(x1, y1, x2 - x1, y2 - y1);
  158         painter.setBrush(grad2);
  159         painter.drawRect(x2, y1, x3 - x2, y2 - y1);
  160     }
  161 
  162     painter.setPen(QColor(0, 0, 0));
  163     painter.setBrush(Qt::NoBrush);
  164     painter.setRenderHint(QPainter::Antialiasing);
  165     for(unsigned int c = 0; c < n; ++c) {
  166         int y1 = h * c / n, y2 = h * (c + 1) / n;
  167         painter.drawRect(QRectF(0.5, (qreal) y1 + 0.5, (qreal) w, (qreal) (y2 - y1)));
  168     }
  169 
  170 }