]> git.sesse.net Git - kdenlive/blob - testingArea/audioEnvelope.cpp
Audio envelope calculation extracted into own class, mean and standard deviation...
[kdenlive] / testingArea / audioEnvelope.cpp
1 /***************************************************************************
2  *   Copyright (C) 2012 by Simon Andreas Eugster (simon.eu@gmail.com)      *
3  *   This file is part of kdenlive. See www.kdenlive.org.                  *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  ***************************************************************************/
10
11 #include "audioEnvelope.h"
12
13 #include "audioStreamInfo.h"
14 #include <QImage>
15 #include <QTime>
16 #include <cmath>
17 #include <iostream>
18
19 AudioEnvelope::AudioEnvelope(Mlt::Producer *producer) :
20     m_envelope(NULL),
21     m_producer(producer),
22     m_envelopeStdDevCalculated(false)
23 {
24     m_info = new AudioInfo(m_producer);
25 }
26
27 AudioEnvelope::~AudioEnvelope()
28 {
29     if (m_envelope != NULL) {
30         delete m_envelope;
31     }
32     delete m_info;
33 }
34
35
36 void AudioEnvelope::loadEnvelope()
37 {
38     Q_ASSERT(m_envelope == NULL);
39
40     std::cout << "Loading envelope ..." << std::endl;
41
42     m_envelopeSize = m_producer->get_length();
43
44     int samplingRate = m_info->info(0)->samplingRate();
45     mlt_audio_format format_s16 = mlt_audio_s16;
46     int channels = 1;
47
48     Mlt::Frame *frame;
49     int64_t position;
50     int samples;
51
52     m_envelope = new uint64_t[m_envelopeSize];
53     m_envelopeMax = 0;
54     m_envelopeMean = 0;
55
56     QTime t;
57     t.start();
58     for (int i = 0; i < m_envelopeSize; i++) {
59
60         frame = m_producer->get_frame(i);
61         position = mlt_frame_get_position(frame->get_frame());
62         samples = mlt_sample_calculator(m_producer->get_fps(), samplingRate, position);
63
64         int16_t *data = static_cast<int16_t*>(frame->get_audio(format_s16, samplingRate, channels, samples));
65
66         uint64_t sum = 0;
67         for (int k = 0; k < samples; k++) {
68             sum += fabs(data[k]);
69         }
70         m_envelope[i] = sum;
71
72         m_envelopeMean += sum;
73         if (sum > m_envelopeMax) {
74             m_envelopeMax = sum;
75         }
76     }
77     m_envelopeMean /= m_envelopeSize;
78     std::cout << "Calculating the envelope (" << m_envelopeSize << " frames) took "
79               << t.elapsed() << " ms." << std::endl;
80 }
81
82 int64_t AudioEnvelope::loadStdDev()
83 {
84     if (m_envelopeStdDevCalculated) {
85         std::cout << "Standard deviation already calculated, not re-calculating." << std::endl;
86     } else {
87
88         if (m_envelope == NULL) {
89             loadEnvelope();
90         }
91
92         m_envelopeStdDev = 0;
93         for (int i = 0; i < m_envelopeSize; i++) {
94             m_envelopeStdDev += sqrt((m_envelope[i]-m_envelopeMean)*(m_envelope[i]-m_envelopeMean)/m_envelopeSize);
95         }
96         m_envelopeStdDevCalculated = true;
97
98     }
99     return m_envelopeStdDev;
100 }
101
102 QImage AudioEnvelope::drawEnvelope()
103 {
104     if (m_envelope == NULL) {
105         loadEnvelope();
106     }
107
108     QImage img(m_envelopeSize, 400, QImage::Format_ARGB32);
109     img.fill(qRgb(255,255,255));
110     double fy;
111     for (int x = 0; x < img.width(); x++) {
112         fy = m_envelope[x]/double(m_envelopeMax) * img.height();
113         for (int y = img.height()-1; y > img.height()-1-fy; y--) {
114             img.setPixel(x,y, qRgb(50, 50, 50));
115         }
116     }
117     return img;
118 }
119
120 void AudioEnvelope::dumpInfo() const
121 {
122     if (m_envelope == NULL) {
123         std::cout << "Envelope not generated, no information available." << std::endl;
124     } else {
125         std::cout << "Envelope info" << std::endl
126                   << "* size = " << m_envelopeSize << std::endl
127                   << "* max = " << m_envelopeMax << std::endl
128                   << "* ยต = " << m_envelopeMean << std::endl
129                      ;
130         if (m_envelopeStdDevCalculated) {
131             std::cout << "* s = " << m_envelopeStdDev << std::endl;
132         }
133     }
134 }