2 * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "ardour/analysis_graph.h"
21 #include "ardour/route.h"
22 #include "ardour/session.h"
24 #include "timecode/time.h"
26 #include "audiographer/process_context.h"
27 #include "audiographer/general/chunker.h"
28 #include "audiographer/general/interleaver.h"
29 #include "audiographer/general/analyser.h"
30 #include "audiographer/general/peak_reader.h"
34 using namespace ARDOUR;
35 using namespace AudioGrapher;
37 AnalysisGraph::AnalysisGraph (Session *s)
39 , _max_chunksize (8192)
44 _buf = (Sample *) malloc(sizeof(Sample) * _max_chunksize);
45 _mixbuf = (Sample *) malloc(sizeof(Sample) * _max_chunksize);
46 _gainbuf = (float *) malloc(sizeof(float) * _max_chunksize);
49 AnalysisGraph::~AnalysisGraph ()
57 AnalysisGraph::analyze_region (boost::shared_ptr<AudioRegion> region)
59 interleaver.reset (new Interleaver<Sample> ());
60 interleaver->init (region->n_channels(), _max_chunksize);
61 chunker.reset (new Chunker<Sample> (_max_chunksize));
62 analyser.reset (new Analyser (
63 _session->nominal_frame_rate(),
68 interleaver->add_output(chunker);
69 chunker->add_output (analyser);
72 framecnt_t length = region->length();
74 framecnt_t chunk = std::min (_max_chunksize, length - x);
76 for (unsigned int channel = 0; channel < region->n_channels(); ++channel) {
77 memset (_buf, 0, chunk * sizeof (Sample));
78 n = region->read_at (_buf, _mixbuf, _gainbuf, region->position() + x, chunk, channel);
79 ConstProcessContext<Sample> context (_buf, n, 1);
80 if (n < _max_chunksize) {
81 context().set_flag (ProcessContext<Sample>::EndOfInput);
83 interleaver->input (channel)->process (context);
86 std::cerr << "AnalysisGraph::analyze_region read zero samples\n";
92 Progress (_frames_read, _frames_end);
97 _results.insert (std::make_pair (region->name(), analyser->result ()));
101 AnalysisGraph::analyze_range (boost::shared_ptr<Route> route, boost::shared_ptr<AudioPlaylist> pl, const std::list<AudioRange>& range)
103 const uint32_t n_audio = route->n_inputs().n_audio();
105 for (std::list<AudioRange>::const_iterator j = range.begin(); j != range.end(); ++j) {
107 interleaver.reset (new Interleaver<Sample> ());
108 interleaver->init (n_audio, _max_chunksize);
109 chunker.reset (new Chunker<Sample> (_max_chunksize));
110 analyser.reset (new Analyser (48000.f, n_audio, _max_chunksize, (*j).length()));
112 interleaver->add_output(chunker);
113 chunker->add_output (analyser);
116 while (x < j->length()) {
117 framecnt_t chunk = std::min (_max_chunksize, (*j).length() - x);
119 for (uint32_t channel = 0; channel < n_audio; ++channel) {
120 n = pl->read (_buf, _mixbuf, _gainbuf, (*j).start + x, chunk, channel);
122 ConstProcessContext<Sample> context (_buf, n, 1);
123 if (n < _max_chunksize) {
124 context().set_flag (ProcessContext<Sample>::EndOfInput);
126 interleaver->input (channel)->process (context);
130 Progress (_frames_read, _frames_end);
136 std::string name = string_compose (_("%1 (%2..%3)"), route->name(),
137 Timecode::timecode_format_sampletime (
139 _session->nominal_frame_rate(),
141 Timecode::timecode_format_sampletime (
142 (*j).start + (*j).length(),
143 _session->nominal_frame_rate(),
146 _results.insert (std::make_pair (name, analyser->result ()));