--- /dev/null
+/***************************************************************************
+ * 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 "audioInfo.h"
+
+#include "audioStreamInfo.h"
+#include <iostream>
+#include <cstdlib>
+
+AudioInfo::AudioInfo(Mlt::Producer *producer)
+{
+ // Since we already receive an MLT producer, we do not need to initialize MLT:
+ // Mlt::Factory::init(NULL);
+
+ // Get the number of streams and add the information of each of them if it is an audio stream.
+ int streams = atoi(producer->get("meta.media.nb_streams"));
+ for (int i = 0; i < streams; i++) {
+ std::string propertyName = QString("meta.media.%1.stream.type").arg(i).toStdString();
+
+ if (strcmp("audio", producer->get(propertyName.c_str())) == 0) {
+ m_list << new AudioStreamInfo(producer, i);
+ }
+
+ }
+}
+
+AudioInfo::~AudioInfo()
+{
+ foreach (AudioStreamInfo *info, m_list) {
+ delete info;
+ }
+}
+
+int AudioInfo::size() const
+{
+ return m_list.size();
+}
+
+AudioStreamInfo const* AudioInfo::info(int pos) const
+{
+ Q_ASSERT(pos >= 0);
+ Q_ASSERT(pos <= m_list.size());
+
+ return m_list.at(pos);
+}
+
+void AudioInfo::dumpInfo() const
+{
+ foreach (AudioStreamInfo *info, m_list) {
+ info->dumpInfo();
+ }
+}
+/***************************************************************************
+ * 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 <QMap>
#include <QFile>
+#include <QTime>
+#include <QImage>
+#include <QFileInfo>
+#include <QDateTime>
#include <mlt++/Mlt.h>
#include <iostream>
#include <cstdlib>
+#include <cmath>
-int info(char *filename)
-{
-
- // Initialize MLT
- Mlt::Factory::init(NULL);
-
- // Load an arbitrary profile
- Mlt::Profile prof("hdv_1080_25p");
-
-
- std::cout << "MLT initialized, profile loaded. Loading clips ..." << std::endl;
-
-
- Mlt::Producer producer(prof, filename);
- if (!producer.is_valid()) {
- std::cout << filename << " is invalid." << std::endl;
- return 2;
- }
- std::cout << "Successfully loaded producer " << filename << std::endl;
-
- int streams = atoi(producer.get("meta.media.nb_streams"));
- std::cout << "Number of streams: " << streams << std::endl;
-
- int audioStream = -1;
- for (int i = 0; i < streams; i++) {
- std::string propertyName = QString("meta.media.%1.stream.type").arg(i).toStdString();
- std::cout << "Producer " << i << ": " << producer.get(propertyName.c_str());
- if (strcmp("audio", producer.get(propertyName.c_str())) == 0) {
- std::cout << " (Using this stream)";
- audioStream = i;
- }
- std::cout << std::endl;
- }
-
- if (audioStream >= 0) {
- QMap<QString, QString> map;
- map.insert("Sampling format", QString("meta.media.%1.codec.sample_fmt").arg(audioStream));
- map.insert("Sampling rate", QString("meta.media.%1.codec.sample_rate").arg(audioStream));
- map.insert("Bit rate", QString("meta.media.%1.codec.bit_rate").arg(audioStream));
- map.insert("Channels", QString("meta.media.%1.codec.channels").arg(audioStream));
- map.insert("Codec", QString("meta.media.%1.codec.name").arg(audioStream));
- map.insert("Codec, long name", QString("meta.media.%1.codec.long_name").arg(audioStream));
-
- std::cout << "Audio properties (stream " << audioStream << ")" << std::endl;
- foreach (QString key, map.keys()) {
- std::string value = map.value(key).toStdString();
- std::cout << "\t" << key.toStdString() << ": " << producer.get(value.c_str())
- << " (" << value << ")" << std::endl;
- }
- }
-
- return 0;
-}
+#include "audioInfo.h"
+#include "audioStreamInfo.h"
int main(int argc, char *argv[])
{
std::cout << "Trying to align (1)\n\t" << fileSub << "\nto fit on (2)\n\t" << fileMain
<< "\n, result will indicate by how much (1) has to be moved." << std::endl;
+ // Initialize MLT
+ Mlt::Factory::init(NULL);
+
+ // Load an arbitrary profile
+ Mlt::Profile prof("hdv_1080_25p");
- info(fileMain);
- info(fileSub);
+ // Load the MLT producers
+ Mlt::Producer prodMain(prof, fileMain);
+ if (!prodMain.is_valid()) {
+ std::cout << fileMain << " is invalid." << std::endl;
+ return 2;
+ }
+ Mlt::Producer profSub(prof, fileSub);
+ if (!profSub.is_valid()) {
+ std::cout << fileSub << " is invalid." << std::endl;
+ return 2;
+ }
-/*
- Mlt::Frame *frame = producer.get_frame();
+ AudioInfo infoMain(&prodMain);
+ AudioInfo infoSub(&profSub);
+ infoMain.dumpInfo();
+ infoSub.dumpInfo();
+ prodMain.get_fps();
- float *data = (float*)frame->get_audio(format, samplingRate, channels, nSamples);
- producer.set("video_index", "-1");
- if (KdenliveSettings::normaliseaudiothumbs()) {
- Mlt::Filter m_convert(prof, "volume");
- m_convert.set("gain", "normalise");
- producer.attach(m_convert);
+ int framesToFetch = prodMain.get_length();
+ std::cout << "Length: " << framesToFetch
+ << " (Seconds: " << framesToFetch/prodMain.get_fps() << ")"
+ << std::endl;
+ if (framesToFetch > 5000) {
+ framesToFetch = 5000;
}
- int last_val = 0;
- int val = 0;
- double framesPerSecond = mlt_producer_get_fps(producer.get_producer());
- Mlt::Frame *mlt_frame;
+ mlt_audio_format format_s16 = mlt_audio_s16;
+ int samplingRate = infoMain.info(0)->samplingRate();
+ int channels = 1;
- for (int z = (int) frame; z < (int)(frame + lengthInFrames) && producer.is_valid() && !m_abortAudioThumb; z++) {
- val = (int)((z - frame) / (frame + lengthInFrames) * 100.0);
- if (last_val != val && val > 1) {
- setThumbsProgress(i18n("Creating audio thumbnail for %1", url.fileName()), val);
- last_val = val;
+ 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]);
}
- 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()));
- qint16* pcm = static_cast<qint16*>(mlt_frame->get_audio(audioFormat, frequency, channels, samples));
- for (int c = 0; c < channels; c++) {
- QByteArray audioArray;
- audioArray.resize(arrayWidth);
- for (int i = 0; i < audioArray.size(); i++) {
- audioArray[i] = ((*(pcm + c + i * samples / audioArray.size())) >> 9) + 127 / 2 ;
- }
- f.write(audioArray);
- storeIn[z][c] = audioArray;
- }
- } else {
- f.write(QByteArray(arrayWidth, '\x00'));
+ envelope[i] = sum;
+
+ if (sum > max) {
+ max = sum;
}
- delete mlt_frame;
}
- f.close();
- setThumbsProgress(i18n("Creating audio thumbnail for %1", url.fileName()), -1);
- if (m_abortAudioThumb) {
- f.remove();
- } else {
- clip->updateAudioThumbnail(storeIn);
- }*/
+ 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);
+ std::cout << "Saved volume envelope as "
+ << QFileInfo(outImg).absoluteFilePath().toStdString()
+ << std::endl;
return 0;
--- /dev/null
+/***************************************************************************
+ * 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 "audioStreamInfo.h"
+
+#include <iostream>
+#include <cstdlib>
+
+AudioStreamInfo::AudioStreamInfo(Mlt::Producer *producer, int audioStreamIndex) :
+ m_audioStreamIndex(audioStreamIndex)
+{
+
+ std::string key;
+
+ key = QString("meta.media.%1.codec.sample_fmt").arg(audioStreamIndex).toStdString();
+ m_samplingFormat = QString(producer->get(key.c_str()));
+
+ key = QString("meta.media.%1.codec.sample_rate").arg(audioStreamIndex).toStdString();
+ m_samplingRate = atoi(producer->get(key.c_str()));
+
+ key = QString("meta.media.%1.codec.bit_rate").arg(audioStreamIndex).toStdString();
+ m_bitRate = atoi(producer->get(key.c_str()));
+
+ key = QString("meta.media.%1.codec.channels").arg(audioStreamIndex).toStdString();
+ m_channels = atoi(producer->get(key.c_str()));
+
+ key = QString("meta.media.%1.codec.name").arg(audioStreamIndex).toStdString();
+ m_codecName = QString(producer->get(key.c_str()));
+
+ key = QString("meta.media.%1.codec.long_name").arg(audioStreamIndex).toStdString();
+ m_codecLongName = QString(producer->get(key.c_str()));
+}
+AudioStreamInfo::~AudioStreamInfo()
+{
+}
+
+int AudioStreamInfo::streamIndex() const { return m_audioStreamIndex; }
+int AudioStreamInfo::samplingRate() const { return m_samplingRate; }
+int AudioStreamInfo::channels() const { return m_channels; }
+int AudioStreamInfo::bitrate() const { return m_bitRate; }
+const QString& AudioStreamInfo::codecName(bool longName) const
+{
+ if (longName) {
+ return m_codecLongName;
+ } else {
+ return m_codecName;
+ }
+}
+
+void AudioStreamInfo::dumpInfo() const
+{
+ std::cout << "Info for audio stream " << m_audioStreamIndex << std::endl
+ << "\tCodec: " << m_codecLongName.toStdString() << " (" << m_codecName.toStdString() << ")" << std::endl
+ << "\tChannels: " << m_channels << std::endl
+ << "\tSampling rate: " << m_samplingRate << std::endl
+ << "\tBit rate: " << m_bitRate << std::endl
+ ;
+
+}