]> git.sesse.net Git - kdenlive/blobdiff - testingArea/audioEnvelope.cpp
Audio envelope calculation extracted into own class, mean and standard deviation...
[kdenlive] / testingArea / audioEnvelope.cpp
diff --git a/testingArea/audioEnvelope.cpp b/testingArea/audioEnvelope.cpp
new file mode 100644 (file)
index 0000000..23184e3
--- /dev/null
@@ -0,0 +1,134 @@
+/***************************************************************************
+ *   Copyright (C) 2012 by Simon Andreas Eugster (simon.eu@gmail.com)      *
+ *   This file is part of kdenlive. See www.kdenlive.org.                  *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ ***************************************************************************/
+
+#include "audioEnvelope.h"
+
+#include "audioStreamInfo.h"
+#include <QImage>
+#include <QTime>
+#include <cmath>
+#include <iostream>
+
+AudioEnvelope::AudioEnvelope(Mlt::Producer *producer) :
+    m_envelope(NULL),
+    m_producer(producer),
+    m_envelopeStdDevCalculated(false)
+{
+    m_info = new AudioInfo(m_producer);
+}
+
+AudioEnvelope::~AudioEnvelope()
+{
+    if (m_envelope != NULL) {
+        delete m_envelope;
+    }
+    delete m_info;
+}
+
+
+void AudioEnvelope::loadEnvelope()
+{
+    Q_ASSERT(m_envelope == NULL);
+
+    std::cout << "Loading envelope ..." << std::endl;
+
+    m_envelopeSize = m_producer->get_length();
+
+    int samplingRate = m_info->info(0)->samplingRate();
+    mlt_audio_format format_s16 = mlt_audio_s16;
+    int channels = 1;
+
+    Mlt::Frame *frame;
+    int64_t position;
+    int samples;
+
+    m_envelope = new uint64_t[m_envelopeSize];
+    m_envelopeMax = 0;
+    m_envelopeMean = 0;
+
+    QTime t;
+    t.start();
+    for (int i = 0; i < m_envelopeSize; i++) {
+
+        frame = m_producer->get_frame(i);
+        position = mlt_frame_get_position(frame->get_frame());
+        samples = mlt_sample_calculator(m_producer->get_fps(), samplingRate, position);
+
+        int16_t *data = static_cast<int16_t*>(frame->get_audio(format_s16, samplingRate, channels, samples));
+
+        uint64_t sum = 0;
+        for (int k = 0; k < samples; k++) {
+            sum += fabs(data[k]);
+        }
+        m_envelope[i] = sum;
+
+        m_envelopeMean += sum;
+        if (sum > m_envelopeMax) {
+            m_envelopeMax = sum;
+        }
+    }
+    m_envelopeMean /= m_envelopeSize;
+    std::cout << "Calculating the envelope (" << m_envelopeSize << " frames) took "
+              << t.elapsed() << " ms." << std::endl;
+}
+
+int64_t AudioEnvelope::loadStdDev()
+{
+    if (m_envelopeStdDevCalculated) {
+        std::cout << "Standard deviation already calculated, not re-calculating." << std::endl;
+    } else {
+
+        if (m_envelope == NULL) {
+            loadEnvelope();
+        }
+
+        m_envelopeStdDev = 0;
+        for (int i = 0; i < m_envelopeSize; i++) {
+            m_envelopeStdDev += sqrt((m_envelope[i]-m_envelopeMean)*(m_envelope[i]-m_envelopeMean)/m_envelopeSize);
+        }
+        m_envelopeStdDevCalculated = true;
+
+    }
+    return m_envelopeStdDev;
+}
+
+QImage AudioEnvelope::drawEnvelope()
+{
+    if (m_envelope == NULL) {
+        loadEnvelope();
+    }
+
+    QImage img(m_envelopeSize, 400, QImage::Format_ARGB32);
+    img.fill(qRgb(255,255,255));
+    double fy;
+    for (int x = 0; x < img.width(); x++) {
+        fy = m_envelope[x]/double(m_envelopeMax) * img.height();
+        for (int y = img.height()-1; y > img.height()-1-fy; y--) {
+            img.setPixel(x,y, qRgb(50, 50, 50));
+        }
+    }
+    return img;
+}
+
+void AudioEnvelope::dumpInfo() const
+{
+    if (m_envelope == NULL) {
+        std::cout << "Envelope not generated, no information available." << std::endl;
+    } else {
+        std::cout << "Envelope info" << std::endl
+                  << "* size = " << m_envelopeSize << std::endl
+                  << "* max = " << m_envelopeMax << std::endl
+                  << "* ยต = " << m_envelopeMean << std::endl
+                     ;
+        if (m_envelopeStdDevCalculated) {
+            std::cout << "* s = " << m_envelopeStdDev << std::endl;
+        }
+    }
+}