summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2016-02-10 03:01:05 +0100
committerRobin Gareus <robin@gareus.org>2016-02-10 03:01:05 +0100
commitc1642fead82c58e7ca546b375aaf95459a803d96 (patch)
tree0e7fe62415b6183bc887990e6815f3cd8772f955 /libs/ardour
parent883a6a3d4e0481d1145e62c995ed937e69245a94 (diff)
Post-export Analysis
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/export_analysis.h60
-rw-r--r--libs/ardour/ardour/export_graph_builder.h12
-rw-r--r--libs/ardour/ardour/export_status.h3
-rw-r--r--libs/ardour/export_graph_builder.cc28
-rw-r--r--libs/ardour/export_handler.cc15
-rw-r--r--libs/ardour/export_status.cc1
6 files changed, 105 insertions, 14 deletions
diff --git a/libs/ardour/ardour/export_analysis.h b/libs/ardour/ardour/export_analysis.h
new file mode 100644
index 0000000000..bab79bba4e
--- /dev/null
+++ b/libs/ardour/ardour/export_analysis.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 Robin Gareus <robin@gareus.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ardour_export_analysis_h__
+#define __ardour_export_analysis_h__
+
+#include <map>
+#include <cstring>
+#include <boost/shared_ptr.hpp>
+
+#include "ardour/types.h"
+
+namespace ARDOUR {
+ struct ExportAnalysis {
+ public:
+ ExportAnalysis ()
+ : loudness (0)
+ , loudness_range (0)
+ , have_loudness (false)
+ {
+ memset (_peaks, 0, sizeof(_peaks));
+ memset (_spectrum, 0, sizeof(_spectrum));
+ }
+
+ ExportAnalysis (const ExportAnalysis& other)
+ : loudness (other.loudness)
+ , loudness_range (other.loudness_range)
+ , have_loudness (other.have_loudness)
+ {
+ memcpy (_peaks, other._peaks, sizeof(_peaks));
+ memcpy (_spectrum, other._spectrum, sizeof(_spectrum));
+ }
+
+ float loudness;
+ float loudness_range;
+ bool have_loudness;
+ PeakData _peaks[800];
+ float _spectrum[800][256];
+ };
+
+ typedef boost::shared_ptr<ExportAnalysis> ExportAnalysisPtr;
+ typedef std::map<std::string, ExportAnalysisPtr> AnalysisResults;
+
+} // namespace ARDOUR
+#endif
diff --git a/libs/ardour/ardour/export_graph_builder.h b/libs/ardour/ardour/export_graph_builder.h
index 3e9fb58a15..d14a00997a 100644
--- a/libs/ardour/ardour/export_graph_builder.h
+++ b/libs/ardour/ardour/export_graph_builder.h
@@ -22,6 +22,7 @@
#define __ardour_export_graph_builder_h__
#include "ardour/export_handler.h"
+#include "ardour/export_analysis.h"
#include "audiographer/utils/identity_vertex.h"
@@ -32,6 +33,7 @@ namespace AudioGrapher {
class SampleRateConverter;
class PeakReader;
class Normalizer;
+ class Analyser;
template <typename T> class Chunker;
template <typename T> class SampleFormatConverter;
template <typename T> class Interleaver;
@@ -55,7 +57,9 @@ class LIBARDOUR_API ExportGraphBuilder
typedef boost::shared_ptr<AudioGrapher::Sink<Sample> > FloatSinkPtr;
typedef boost::shared_ptr<AudioGrapher::IdentityVertex<Sample> > IdentityVertexPtr;
+ typedef boost::shared_ptr<AudioGrapher::Analyser> AnalysisPtr;
typedef std::map<ExportChannelPtr, IdentityVertexPtr> ChannelMap;
+ typedef std::map<std::string, AnalysisPtr> AnalysisMap;
public:
@@ -71,9 +75,14 @@ class LIBARDOUR_API ExportGraphBuilder
void cleanup (bool remove_out_files = false);
void set_current_timespan (boost::shared_ptr<ExportTimespan> span);
void add_config (FileSpec const & config);
+ void get_analysis_results (AnalysisResults& results);
private:
+ void add_analyser (const std::string& fn, AnalysisPtr ap) {
+ analysis_map.insert (std::make_pair (fn, ap));
+ }
+
void add_split_config (FileSpec const & config);
class Encoder {
@@ -125,6 +134,7 @@ class LIBARDOUR_API ExportGraphBuilder
boost::ptr_list<Encoder> children;
int data_width;
+ AnalysisPtr analyser;
// Only one of these should be available at a time
FloatConverterPtr float_converter;
IntConverterPtr int_converter;
@@ -245,6 +255,8 @@ class LIBARDOUR_API ExportGraphBuilder
std::list<Normalizer *> normalizers;
+ AnalysisMap analysis_map;
+
Glib::ThreadPool thread_pool;
};
diff --git a/libs/ardour/ardour/export_status.h b/libs/ardour/ardour/export_status.h
index 95921629c7..f250ae0dc6 100644
--- a/libs/ardour/ardour/export_status.h
+++ b/libs/ardour/ardour/export_status.h
@@ -24,6 +24,7 @@
#include <stdint.h>
#include "ardour/libardour_visibility.h"
+#include "ardour/export_analysis.h"
#include "ardour/types.h"
#include "pbd/signals.h"
@@ -79,6 +80,8 @@ class LIBARDOUR_API ExportStatus {
volatile uint32_t total_normalize_cycles;
volatile uint32_t current_normalize_cycle;
+ AnalysisResults result_map;
+
private:
volatile bool _aborted;
volatile bool _errors;
diff --git a/libs/ardour/export_graph_builder.cc b/libs/ardour/export_graph_builder.cc
index c054d85242..685db817d4 100644
--- a/libs/ardour/export_graph_builder.cc
+++ b/libs/ardour/export_graph_builder.cc
@@ -28,6 +28,7 @@
#include "audiographer/general/chunker.h"
#include "audiographer/general/interleaver.h"
#include "audiographer/general/normalizer.h"
+#include "audiographer/general/analyser.h"
#include "audiographer/general/peak_reader.h"
#include "audiographer/general/sample_format_converter.h"
#include "audiographer/general/sr_converter.h"
@@ -110,6 +111,7 @@ ExportGraphBuilder::reset ()
channel_configs.clear ();
channels.clear ();
normalizers.clear ();
+ analysis_map.clear();
}
void
@@ -174,6 +176,16 @@ ExportGraphBuilder::add_config (FileSpec const & config)
}
void
+ExportGraphBuilder::get_analysis_results (AnalysisResults& results) {
+ for (AnalysisMap::iterator i = analysis_map.begin(); i != analysis_map.end(); ++i) {
+ ExportAnalysisPtr p = i->second->result ();
+ if (p) {
+ results.insert (std::make_pair (i->first, p));
+ }
+ }
+}
+
+void
ExportGraphBuilder::add_split_config (FileSpec const & config)
{
for (ChannelConfigList::iterator it = channel_configs.begin(); it != channel_configs.end(); ++it) {
@@ -287,39 +299,39 @@ ExportGraphBuilder::Encoder::copy_files (std::string orig_path)
/* SFC */
-ExportGraphBuilder::SFC::SFC (ExportGraphBuilder &, FileSpec const & new_config, framecnt_t max_frames)
+ExportGraphBuilder::SFC::SFC (ExportGraphBuilder &parent, FileSpec const & new_config, framecnt_t max_frames)
: data_width(0)
{
config = new_config;
data_width = sndfile_data_width (Encoder::get_real_format (config));
unsigned channels = new_config.channel_config->get_n_chans();
+ analyser.reset (new Analyser (config.format->sample_rate(), channels, max_frames,
+ (framecnt_t) ceil (parent.timespan->get_length () * config.format->sample_rate () / (double) parent.session.nominal_frame_rate ())));
+ parent.add_analyser (config.filename->get_path (config.format), analyser);
if (data_width == 8 || data_width == 16) {
short_converter = ShortConverterPtr (new SampleFormatConverter<short> (channels));
short_converter->init (max_frames, config.format->dither_type(), data_width);
add_child (config);
+ analyser->add_output (short_converter);
} else if (data_width == 24 || data_width == 32) {
int_converter = IntConverterPtr (new SampleFormatConverter<int> (channels));
int_converter->init (max_frames, config.format->dither_type(), data_width);
add_child (config);
+ analyser->add_output (int_converter);
} else {
int actual_data_width = 8 * sizeof(Sample);
float_converter = FloatConverterPtr (new SampleFormatConverter<Sample> (channels));
float_converter->init (max_frames, config.format->dither_type(), actual_data_width);
add_child (config);
+ analyser->add_output (float_converter);
}
}
ExportGraphBuilder::FloatSinkPtr
ExportGraphBuilder::SFC::sink ()
{
- if (data_width == 8 || data_width == 16) {
- return short_converter;
- } else if (data_width == 24 || data_width == 32) {
- return int_converter;
- } else {
- return float_converter;
- }
+ return analyser;
}
void
diff --git a/libs/ardour/export_handler.cc b/libs/ardour/export_handler.cc
index 70c807b7de..6b59afec89 100644
--- a/libs/ardour/export_handler.cc
+++ b/libs/ardour/export_handler.cc
@@ -295,11 +295,12 @@ ExportHandler::command_output(std::string output, size_t size)
void
ExportHandler::finish_timespan ()
{
+ graph_builder->get_analysis_results (export_status->result_map);
+
while (config_map.begin() != timespan_bounds.second) {
ExportFormatSpecPtr fmt = config_map.begin()->second.format;
std::string filename = config_map.begin()->second.filename->get_path(fmt);
-
if (fmt->with_cue()) {
export_cd_marker_file (current_timespan, fmt, filename, CDMarkerCUE);
}
@@ -312,15 +313,17 @@ ExportHandler::finish_timespan ()
export_cd_marker_file (current_timespan, fmt, filename, MP4Chaps);
}
+ /* close file first, otherwise TagLib enounters an ERROR_SHARING_VIOLATION
+ * The process cannot access the file because it is being used.
+ * ditto for post-export and upload.
+ */
+ graph_builder->reset ();
+
if (fmt->tag()) {
- /* close file first, otherwise TagLib enounters an ERROR_SHARING_VIOLATION
- * The process cannot access the file because it is being used.
- *
- * TODO: check Umlauts and encoding in filename.
+ /* TODO: check Umlauts and encoding in filename.
* TagLib eventually calls CreateFileA(),
*/
export_status->active_job = ExportStatus::Tagging;
- graph_builder->reset ();
AudiofileTagger::tag_file(filename, *SessionMetadata::Metadata());
}
diff --git a/libs/ardour/export_status.cc b/libs/ardour/export_status.cc
index 4b48a8edd7..170073974b 100644
--- a/libs/ardour/export_status.cc
+++ b/libs/ardour/export_status.cc
@@ -52,6 +52,7 @@ ExportStatus::init ()
total_normalize_cycles = 0;
current_normalize_cycle = 0;
+ result_map.clear();
}
void