summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2018-03-26 16:26:32 +0100
committerCarl Hetherington <cth@carlh.net>2018-03-26 16:26:32 +0100
commitf0192490565c72aa9838f40cbab56c4c0c60e522 (patch)
treecf0f287a164f3a25607f0df13210a5dcc0ffd235 /src
parent00dffac67c88b509c1c77da85fe2769049714135 (diff)
Add time axis to audio analysis (part of #1082).
Diffstat (limited to 'src')
-rw-r--r--src/lib/analyse_audio_job.cc2
-rw-r--r--src/lib/audio_analysis.cc12
-rw-r--r--src/lib/audio_analysis.h20
-rw-r--r--src/wx/audio_plot.cc56
-rw-r--r--src/wx/timeline_time_axis_view.cc19
-rw-r--r--src/wx/wx_util.cc23
-rw-r--r--src/wx/wx_util.h1
7 files changed, 108 insertions, 25 deletions
diff --git a/src/lib/analyse_audio_job.cc b/src/lib/analyse_audio_job.cc
index b96c7047b..db917301a 100644
--- a/src/lib/analyse_audio_job.cc
+++ b/src/lib/analyse_audio_job.cc
@@ -163,6 +163,8 @@ AnalyseAudioJob::run ()
_analysis->set_analysis_gain (ac->gain ());
}
+ _analysis->set_samples_per_point (_samples_per_point);
+ _analysis->set_sample_rate (_film->audio_frame_rate ());
_analysis->write (_film->audio_analysis_path (_playlist));
set_progress (1);
diff --git a/src/lib/audio_analysis.cc b/src/lib/audio_analysis.cc
index 61cdd5fcc..b58a3127d 100644
--- a/src/lib/audio_analysis.cc
+++ b/src/lib/audio_analysis.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
@@ -90,6 +90,8 @@ AudioAnalysis::AudioAnalysis (boost::filesystem::path filename)
_loudness_range = f.optional_number_child<float> ("LoudnessRange");
_analysis_gain = f.optional_number_child<double> ("AnalysisGain");
+ _samples_per_point = f.optional_number_child<int64_t> ("SamplesPerPoint");
+ _sample_rate = f.optional_number_child<int64_t> ("SampleRate");
}
void
@@ -156,6 +158,14 @@ AudioAnalysis::write (boost::filesystem::path filename)
root->add_child("AnalysisGain")->add_child_text (raw_convert<string> (_analysis_gain.get ()));
}
+ if (_samples_per_point) {
+ root->add_child("SamplesPerPoint")->add_child_text (raw_convert<string> (_samples_per_point.get()));
+ }
+
+ if (_sample_rate) {
+ root->add_child("SampleRate")->add_child_text (raw_convert<string> (_sample_rate.get()));
+ }
+
doc->write_to_file_formatted (filename.string ());
}
diff --git a/src/lib/audio_analysis.h b/src/lib/audio_analysis.h
index 6da651c95..0a5e6194d 100644
--- a/src/lib/audio_analysis.h
+++ b/src/lib/audio_analysis.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
@@ -100,6 +100,22 @@ public:
_analysis_gain = gain;
}
+ boost::optional<int64_t> samples_per_point () const {
+ return _samples_per_point;
+ }
+
+ void set_samples_per_point (int64_t spp) {
+ _samples_per_point = spp;
+ }
+
+ boost::optional<int> sample_rate () const {
+ return _sample_rate;
+ }
+
+ void set_sample_rate (int sr) {
+ _sample_rate = sr;
+ }
+
void write (boost::filesystem::path);
float gain_correction (boost::shared_ptr<const Playlist> playlist);
@@ -115,6 +131,8 @@ private:
* happened.
*/
boost::optional<double> _analysis_gain;
+ boost::optional<int64_t> _samples_per_point;
+ boost::optional<int> _sample_rate;
static int const _current_state_version;
};
diff --git a/src/wx/audio_plot.cc b/src/wx/audio_plot.cc
index fe031aaac..493d99f5e 100644
--- a/src/wx/audio_plot.cc
+++ b/src/wx/audio_plot.cc
@@ -122,7 +122,7 @@ struct Metrics
double db_label_width;
int height;
int y_origin;
- float x_scale;
+ float x_scale; ///< pixels per data point
float y_scale;
};
@@ -142,7 +142,7 @@ AudioPlot::paint ()
return;
}
- wxGraphicsPath grid = gc->CreatePath ();
+ wxGraphicsPath h_grid = gc->CreatePath ();
gc->SetFont (gc->CreateFont (*wxSMALL_FONT));
wxDouble db_label_height;
wxDouble db_label_descent;
@@ -161,15 +161,59 @@ AudioPlot::paint ()
for (int i = _minimum; i <= 0; i += 10) {
int const y = (metrics.height - (i - _minimum) * metrics.y_scale) - metrics.y_origin;
- grid.MoveToPoint (metrics.db_label_width - 4, y);
- grid.AddLineToPoint (metrics.db_label_width + data_width, y);
+ h_grid.MoveToPoint (metrics.db_label_width - 4, y);
+ h_grid.AddLineToPoint (metrics.db_label_width + data_width, y);
gc->DrawText (std_to_wx (String::compose ("%1dB", i)), 0, y - (db_label_height / 2));
}
gc->SetPen (wxPen (wxColour (200, 200, 200)));
- gc->StrokePath (grid);
+ gc->StrokePath (h_grid);
- gc->DrawText (_("Time"), data_width, metrics.height - metrics.y_origin + db_label_height / 2);
+ if (_analysis->samples_per_point() && _analysis->sample_rate()) {
+
+ /* Draw an x axis with marks */
+
+ wxGraphicsPath v_grid = gc->CreatePath ();
+
+ DCPOMATIC_ASSERT (_analysis->samples_per_point().get() != 0.0);
+ double const pps = _analysis->sample_rate().get() * metrics.x_scale / _analysis->samples_per_point().get();
+
+ gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 1, wxPENSTYLE_SOLID));
+
+ double const mark_interval = calculate_mark_interval (rint (128 / pps));
+
+ DCPTime t = DCPTime::from_seconds (mark_interval);
+ while ((t.seconds() * pps) < data_width) {
+ double tc = t.seconds ();
+ int const h = tc / 3600;
+ tc -= h * 3600;
+ int const m = tc / 60;
+ tc -= m * 60;
+ int const s = tc;
+
+ wxString str = wxString::Format (wxT ("%02d:%02d:%02d"), h, m, s);
+ wxDouble str_width;
+ wxDouble str_height;
+ wxDouble str_descent;
+ wxDouble str_leading;
+ gc->GetTextExtent (str, &str_width, &str_height, &str_descent, &str_leading);
+
+ int const tx = llrintf (metrics.db_label_width + t.seconds() * pps);
+ gc->DrawText (str, tx - str_width / 2, metrics.height - metrics.y_origin + db_label_height);
+
+ v_grid.MoveToPoint (tx, metrics.height - metrics.y_origin + 4);
+ v_grid.AddLineToPoint (tx, metrics.y_origin);
+
+ t += DCPTime::from_seconds (mark_interval);
+ }
+
+ gc->SetPen (wxPen (wxColour (200, 200, 200)));
+ gc->StrokePath (v_grid);
+
+ } else {
+ /* This is an old analysis without samples_per_point information */
+ gc->DrawText (_("Time"), data_width, metrics.height - metrics.y_origin + db_label_height / 2);
+ }
if (_type_visible[AudioPoint::PEAK]) {
for (int c = 0; c < MAX_DCP_AUDIO_CHANNELS; ++c) {
diff --git a/src/wx/timeline_time_axis_view.cc b/src/wx/timeline_time_axis_view.cc
index 45bf7e7cf..1947faa0b 100644
--- a/src/wx/timeline_time_axis_view.cc
+++ b/src/wx/timeline_time_axis_view.cc
@@ -20,6 +20,7 @@
#include "timeline_time_axis_view.h"
#include "timeline.h"
+#include "wx_util.h"
#include <wx/wx.h>
#include <wx/graphics.h>
@@ -56,23 +57,7 @@ TimelineTimeAxisView::do_paint (wxGraphicsContext* gc, list<dcpomatic::Rect<int>
gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 1, wxPENSTYLE_SOLID));
- double mark_interval = rint (128 / pps);
- if (mark_interval > 5) {
- mark_interval -= lrint (mark_interval) % 5;
- }
- if (mark_interval > 10) {
- mark_interval -= lrint (mark_interval) % 10;
- }
- if (mark_interval > 60) {
- mark_interval -= lrint (mark_interval) % 60;
- }
- if (mark_interval > 3600) {
- mark_interval -= lrint (mark_interval) % 3600;
- }
-
- if (mark_interval < 1) {
- mark_interval = 1;
- }
+ double const mark_interval = calculate_mark_interval (rint (128 / pps));
wxGraphicsPath path = gc->CreatePath ();
path.MoveToPoint (_timeline.tracks_position().x, _y);
diff --git a/src/wx/wx_util.cc b/src/wx/wx_util.cc
index e017f404d..4cd0d4bd7 100644
--- a/src/wx/wx_util.cc
+++ b/src/wx/wx_util.cc
@@ -414,3 +414,26 @@ path_from_file_dialog (wxFileDialog* dialog, string extension)
{
return boost::filesystem::path(wx_to_std(dialog->GetPath())).replace_extension(extension);
}
+
+double
+calculate_mark_interval (double mark_interval)
+{
+ if (mark_interval > 5) {
+ mark_interval -= lrint (mark_interval) % 5;
+ }
+ if (mark_interval > 10) {
+ mark_interval -= lrint (mark_interval) % 10;
+ }
+ if (mark_interval > 60) {
+ mark_interval -= lrint (mark_interval) % 60;
+ }
+ if (mark_interval > 3600) {
+ mark_interval -= lrint (mark_interval) % 3600;
+ }
+
+ if (mark_interval < 1) {
+ mark_interval = 1;
+ }
+
+ return mark_interval;
+}
diff --git a/src/wx/wx_util.h b/src/wx/wx_util.h
index e36a35e1e..2691eccf4 100644
--- a/src/wx/wx_util.h
+++ b/src/wx/wx_util.h
@@ -83,6 +83,7 @@ extern wxString time_to_timecode (DCPTime t, double fps);
extern void setup_audio_channels_choice (wxChoice* choice, int minimum);
extern wxSplashScreen* maybe_show_splash ();
extern boost::filesystem::path path_from_file_dialog (wxFileDialog* dialog, std::string extension);
+extern double calculate_mark_interval (double start);
extern void checked_set (FilePickerCtrl* widget, boost::filesystem::path value);
extern void checked_set (wxSpinCtrl* widget, int value);