1 /***************************************************************************
2 * Copyright (C) 2012 by Simon Andreas Eugster (simon.eu@gmail.com) *
3 * This file is part of kdenlive. See www.kdenlive.org. *
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 ***************************************************************************/
11 #include "audioEnvelope.h"
13 #include "audioStreamInfo.h"
20 AudioEnvelope::AudioEnvelope(const QString &url, Mlt::Producer *producer, int offset, int length) :
24 m_envelopeSize(producer->get_length()),
28 m_envelopeStdDevCalculated(false),
29 m_envelopeIsNormalized(false)
31 // make a copy of the producer to avoid audio playback issues
32 QString path = QString::fromUtf8(producer->get("resource"));
33 if (path == QLatin1String("<playlist>") || path == QLatin1String("<tractor>") || path ==QLatin1String( "<producer>"))
35 m_producer = new Mlt::Producer(*(producer->profile()), path.toUtf8().constData());
36 if (!m_producer || !m_producer->is_valid()) {
37 qDebug()<<"// Cannot create envelope for producer: "<<path;
39 m_info = new AudioInfo(m_producer);
41 Q_ASSERT(m_offset >= 0);
43 Q_ASSERT(m_length+m_offset <= m_envelopeSize);
44 m_envelopeSize = m_length;
48 AudioEnvelope::~AudioEnvelope()
50 if (m_envelope != NULL) {
59 const int64_t *AudioEnvelope::envelope()
61 if (m_envelope == NULL) {
66 int AudioEnvelope::envelopeSize() const
68 return m_envelopeSize;
70 int64_t AudioEnvelope::maxValue() const
78 void AudioEnvelope::loadEnvelope()
80 Q_ASSERT(m_envelope == NULL);
82 std::cout << "Loading envelope ..." << std::endl;
84 int samplingRate = m_info->info(0)->samplingRate();
85 mlt_audio_format format_s16 = mlt_audio_s16;
92 m_envelope = new int64_t[m_envelopeSize];
99 m_producer->seek(m_offset);
100 m_producer->set_speed(1.0); // This is necessary, otherwise we don't get any new frames in the 2nd run.
101 for (int i = 0; i < m_envelopeSize; ++i) {
103 frame = m_producer->get_frame(i);
104 position = mlt_frame_get_position(frame->get_frame());
105 samples = mlt_sample_calculator(m_producer->get_fps(), samplingRate, position);
107 int16_t *data = static_cast<int16_t*>(frame->get_audio(format_s16, samplingRate, channels, samples));
110 for (int k = 0; k < samples; k++) {
111 sum += fabs(data[k]);
115 m_envelopeMean += sum;
116 if (sum > m_envelopeMax) {
120 // std::cout << position << "|" << m_producer->get_playtime()
121 // << "-" << m_producer->get_in() << "+" << m_producer->get_out() << " ";
126 if (m_length > 0 && count > m_length) {
130 m_envelopeMean /= m_envelopeSize;
131 std::cout << "Calculating the envelope (" << m_envelopeSize << " frames) took "
132 << t.elapsed() << " ms." << std::endl;
135 int64_t AudioEnvelope::loadStdDev()
137 if (m_envelopeStdDevCalculated) {
138 std::cout << "Standard deviation already calculated, not re-calculating." << std::endl;
141 if (m_envelope == NULL) {
145 m_envelopeStdDev = 0;
146 for (int i = 0; i < m_envelopeSize; ++i) {
147 m_envelopeStdDev += sqrt((m_envelope[i]-m_envelopeMean)*(m_envelope[i]-m_envelopeMean)/m_envelopeSize);
149 m_envelopeStdDevCalculated = true;
152 return m_envelopeStdDev;
155 void AudioEnvelope::normalizeEnvelope(bool clampTo0)
157 if (m_envelope == NULL) {
161 if (!m_envelopeIsNormalized) {
165 for (int i = 0; i < m_envelopeSize; ++i) {
167 m_envelope[i] -= m_envelopeMean;
170 if (m_envelope[i] < 0) { m_envelope[i] = 0; }
173 if (m_envelope[i] > m_envelopeMax) {
174 m_envelopeMax = m_envelope[i];
177 newMean += m_envelope[i];
179 m_envelopeMean = newMean / m_envelopeSize;
181 m_envelopeIsNormalized = true;
186 QImage AudioEnvelope::drawEnvelope()
188 if (m_envelope == NULL) {
192 QImage img(m_envelopeSize, 400, QImage::Format_ARGB32);
193 img.fill(qRgb(255,255,255));
195 if (m_envelopeMax == 0)
199 for (int x = 0; x < img.width(); x++) {
200 fy = m_envelope[x]/double(m_envelopeMax) * img.height();
201 for (int y = img.height()-1; y > img.height()-1-fy; y--) {
202 img.setPixel(x,y, qRgb(50, 50, 50));
208 void AudioEnvelope::dumpInfo() const
210 if (m_envelope == NULL) {
211 std::cout << "Envelope not generated, no information available." << std::endl;
213 std::cout << "Envelope info" << std::endl
214 << "* size = " << m_envelopeSize << std::endl
215 << "* max = " << m_envelopeMax << std::endl
216 << "* ยต = " << m_envelopeMean << std::endl
218 if (m_envelopeStdDevCalculated) {
219 std::cout << "* s = " << m_envelopeStdDev << std::endl;