]> git.sesse.net Git - kdenlive/commitdiff
Audio envelope calculation extracted into own class, mean and standard deviation...
authorSimon A. Eugster <simon.eu@gmail.com>
Tue, 14 Feb 2012 10:58:56 +0000 (11:58 +0100)
committerSimon A. Eugster <simon.eu@gmail.com>
Tue, 14 Feb 2012 10:58:56 +0000 (11:58 +0100)
src/clipmanager.cpp
testingArea/CMakeLists.txt
testingArea/audioEnvelope.cpp [new file with mode: 0644]
testingArea/audioEnvelope.h [new file with mode: 0644]
testingArea/audioOffset.cpp

index 45f1fc9fd940c9d37843467d6e101c69659f2992..25d5a092eaf009b1920e13c2ac20e050163b4185 100644 (file)
@@ -305,7 +305,7 @@ void ClipManager::slotGetAudioThumbs()
             producer.seek(z);
             mlt_frame = producer.get_frame();
             if (mlt_frame && mlt_frame->is_valid()) {
-                int samples = mlt_sample_calculator(framesPerSecond, frequency, mlt_frame_get_position(mlt_frame->get_frame()));
+                int samples = mlt_sample_calculator(framesPerSecond, frequency, mlt_frame->get_position());
                 qint16* pcm = static_cast<qint16*>(mlt_frame->get_audio(audioFormat, frequency, channels, samples));
                 for (int c = 0; c < channels; c++) {
                     QByteArray audioArray;
index d08ae2b15c0480b03910441aa47a204dabafc71c..da4c533eab9606a25aad736fade7145c5a4bc497 100644 (file)
@@ -7,7 +7,7 @@ include_directories(
 )
 include(${QT_USE_FILE})
 
-add_executable(audioOffset  audioOffset.cpp audioInfo.cpp audioStreamInfo.cpp)
+add_executable(audioOffset  audioOffset.cpp audioInfo.cpp audioStreamInfo.cpp audioEnvelope.cpp)
 target_link_libraries(audioOffset 
   ${QT_LIBRARIES}
   ${LIBMLT_LIBRARY}
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;
+        }
+    }
+}
diff --git a/testingArea/audioEnvelope.h b/testingArea/audioEnvelope.h
new file mode 100644 (file)
index 0000000..b679d36
--- /dev/null
@@ -0,0 +1,44 @@
+/***************************************************************************
+ *   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.                                   *
+ ***************************************************************************/
+
+#ifndef AUDIOENVELOPE_H
+#define AUDIOENVELOPE_H
+
+#include "audioInfo.h"
+#include <mlt++/Mlt.h>
+
+class QImage;
+class AudioEnvelope
+{
+public:
+    AudioEnvelope(Mlt::Producer *producer);
+    ~AudioEnvelope();
+
+    void loadEnvelope();
+    int64_t loadStdDev();
+
+    QImage drawEnvelope();
+
+    void dumpInfo() const;
+
+private:
+    uint64_t *m_envelope;
+    Mlt::Producer *m_producer;
+    AudioInfo *m_info;
+
+    int m_envelopeSize;
+    uint64_t m_envelopeMax;
+    uint64_t m_envelopeMean;
+    uint64_t m_envelopeStdDev;
+
+    bool m_envelopeStdDevCalculated;
+};
+
+#endif // AUDIOENVELOPE_H
index d8e8eede305a73ed47c27c37ba3004c4987c6ced..6eb549858cec8c7bfd44fd2cee395197956dd652 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "audioInfo.h"
 #include "audioStreamInfo.h"
+#include "audioEnvelope.h"
 
 int main(int argc, char *argv[])
 {
@@ -71,57 +72,23 @@ int main(int argc, char *argv[])
         framesToFetch = 5000;
     }
 
-    mlt_audio_format format_s16 = mlt_audio_s16;
-    int samplingRate = infoMain.info(0)->samplingRate();
-    int channels = 1;
+    AudioEnvelope envelopeMain(&prodMain);
+    envelopeMain.loadEnvelope();
+    envelopeMain.loadStdDev();
+    envelopeMain.dumpInfo();
 
-    Mlt::Frame *frame;
-    int64_t position;
-    int samples;
-
-    uint64_t envelope[framesToFetch];
-    uint64_t max = 0;
-
-    QTime t;
-    t.start();
-    for (int i = 0; i < framesToFetch; i++) {
-
-        frame = prodMain.get_frame(i);
-        position = mlt_frame_get_position(frame->get_frame());
-        samples = mlt_sample_calculator(prodMain.get_fps(), infoMain.info(0)->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]);
-        }
-        envelope[i] = sum;
-
-        if (sum > max) {
-            max = sum;
-        }
-    }
-    std::cout << "Calculating the envelope (" << framesToFetch << " frames) took "
-              << t.elapsed() << " ms." << std::endl;
-
-    QImage img(framesToFetch, 400, QImage::Format_ARGB32);
-    img.fill(qRgb(255,255,255));
-    double fy;
-    for (int x = 0; x < img.width(); x++) {
-        fy = envelope[x]/double(max) * img.height();
-        for (int y = img.height()-1; y > img.height()-1-fy; y--) {
-            img.setPixel(x,y, qRgb(50, 50, 50));
-        }
-    }
 
     QString outImg = QString("envelope-%1.png")
             .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss"));
-    img.save(outImg);
+    envelopeMain.drawEnvelope().save(outImg);
     std::cout << "Saved volume envelope as "
               << QFileInfo(outImg).absoluteFilePath().toStdString()
               << std::endl;
 
+
     return 0;
 
 }
+
+
+