#include "selection.h"
#include "audio_region_view.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
using namespace ARDOUR;
using namespace PBD;
-AnalysisWindow::AnalysisWindow() :
-
- source_selection_label (_("Signal source")),
- source_selection_ranges_rb (_("Selected ranges")),
- source_selection_regions_rb (_("Selected regions")),
-
- display_model_label (_("Display model")),
- display_model_composite_separate_rb (_("Composite graphs for each track")),
- display_model_composite_all_tracks_rb (_("Composite graph of all tracks")),
-
- show_minmax_button (_("Show frequency power range")),
- show_normalized_button (_("Normalize values")),
-
- fft_graph (16384)
+AnalysisWindow::AnalysisWindow()
+ : source_selection_label (_("Signal source"))
+ , source_selection_ranges_rb (_("Selected ranges"))
+ , source_selection_regions_rb (_("Selected regions"))
+ , show_minmax_button (_("Show frequency power range"))
+ , show_normalized_button (_("Fit dB range"))
+ , show_proportional_button (_("Proportional Spectrum, -18dB"))
+ , fft_graph (16384)
{
set_name(_("FFT analysis window"));
set_title (_("Spectral Analysis"));
sigc::bind ( sigc::mem_fun(*this, &AnalysisWindow::source_selection_changed), &source_selection_regions_rb));
}
- vbox.pack_start(hseparator1, false, false);
-
- // "Display model"
- vbox.pack_start(display_model_label, false, false);
- {
- Gtk::RadioButtonGroup group = display_model_composite_separate_rb.get_group();
- display_model_composite_all_tracks_rb.set_group (group);
-
- display_model_composite_separate_rb.set_active();
-
- vbox.pack_start (display_model_composite_separate_rb, false, false);
- vbox.pack_start (display_model_composite_all_tracks_rb, false, false);
-
- // "Composite graphs for all tracks"
- display_model_composite_separate_rb.signal_toggled().connect (
- sigc::bind ( sigc::mem_fun(*this, &AnalysisWindow::display_model_changed), &display_model_composite_separate_rb));
-
- // "Composite graph of all tracks"
- display_model_composite_all_tracks_rb.signal_toggled().connect (
- sigc::bind ( sigc::mem_fun(*this, &AnalysisWindow::display_model_changed), &display_model_composite_all_tracks_rb));
- }
-
// Analyze button
refresh_button.set_name("EditorGTKButton");
refresh_button.set_label(_("Re-analyze data"));
+
refresh_button.signal_clicked().connect ( sigc::bind ( sigc::mem_fun(*this, &AnalysisWindow::analyze_data), &refresh_button));
vbox.pack_start(refresh_button, false, false, 10);
+ vbox.pack_start(hseparator1, false, false);
// Feature checkboxes
- // minmax
- show_minmax_button.signal_toggled().connect( sigc::mem_fun(*this, &AnalysisWindow::show_minmax_changed));
- vbox.pack_start(show_minmax_button, false, false);
-
- // normalize
+ // normalize, fit y-range
show_normalized_button.signal_toggled().connect( sigc::mem_fun(*this, &AnalysisWindow::show_normalized_changed));
vbox.pack_start(show_normalized_button, false, false);
+ // minmax
+ show_minmax_button.signal_toggled().connect( sigc::mem_fun(*this, &AnalysisWindow::show_minmax_changed));
+ vbox.pack_start(show_minmax_button, false, false);
+ // pink-noise / proportional spectrum
+ show_proportional_button.signal_toggled().connect( sigc::mem_fun(*this, &AnalysisWindow::show_proportional_changed));
+ vbox.pack_start(show_proportional_button, false, false);
fft_graph.set_show_normalized(show_normalized_button.get_active());
}
+void
+AnalysisWindow::show_proportional_changed()
+{
+ fft_graph.set_show_proportioanl(show_proportional_button.get_active());
+}
+
void
AnalysisWindow::set_rangemode()
{
}
void
-AnalysisWindow::analyze_data (Gtk::Button */*button*/)
+AnalysisWindow::analyze_data (Gtk::Button * /*button*/)
{
track_list_ready = false;
{
float *gain = (float *) malloc(sizeof(float) * fft_graph.windowSize());
Selection& s (PublicEditor::instance().get_selection());
- TimeSelection ts = s.time;
- RegionSelection ars = s.regions;
- for (TrackSelection::iterator i = s.tracks.begin(); i != s.tracks.end(); ++i) {
- boost::shared_ptr<AudioPlaylist> pl
- = boost::dynamic_pointer_cast<AudioPlaylist>((*i)->playlist());
- if (!pl)
- continue;
+ // if timeSelection
+ if (source_selection_ranges_rb.get_active()) {
+ TimeSelection ts = s.time;
- RouteUI *rui = dynamic_cast<RouteUI *>(*i);
- int n_inputs = rui->route()->n_inputs().n_audio(); // FFT is audio only
+ for (TrackSelection::iterator i = s.tracks.begin(); i != s.tracks.end(); ++i) {
+ boost::shared_ptr<AudioPlaylist> pl
+ = boost::dynamic_pointer_cast<AudioPlaylist>((*i)->playlist());
- // Busses don't have playlists, so we need to check that we actually are working with a playlist
- if (!pl || !rui)
- continue;
+ if (!pl)
+ continue;
- FFTResult *res = fft_graph.prepareResult(rui->color(), rui->route()->name());
+ RouteUI *rui = dynamic_cast<RouteUI *>(*i);
+ int n_inputs = rui->route()->n_inputs().n_audio(); // FFT is audio only
- // if timeSelection
- if (source_selection_ranges_rb.get_active()) {
-// cerr << "Analyzing ranges on track " << *&rui->route().name() << endl;
+ // Busses don't have playlists, so we need to check that we actually are working with a playlist
+ if (!pl || !rui)
+ continue;
+ // std::cerr << "Analyzing ranges on track " << rui->route()->name() << std::endl;
+
+ FFTResult *res = fft_graph.prepareResult(rui->route_color(), rui->route()->name());
for (std::list<AudioRange>::iterator j = ts.begin(); j != ts.end(); ++j) {
int n;
}
}
}
- } else if (source_selection_regions_rb.get_active()) {
-// cerr << "Analyzing selected regions on track " << *&rui->route().name() << endl;
-
- TimeAxisView *current_axis = (*i);
-
- for (RegionSelection::iterator j = ars.begin(); j != ars.end(); ++j) {
- // Check that the region is actually audio (so we can analyze it)
- AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*j);
- if (!arv)
- continue;
-
- // Check that the region really is selected on _this_ track/solo
- if ( &arv->get_time_axis_view() != current_axis)
- continue;
-
-// cerr << " - " << (*j)->region().name() << ": " << (*j)->region().length() << " samples starting at " << (*j)->region().position() << endl;
- int n;
- for (int channel = 0; channel < n_inputs; channel++) {
+ res->finalize();
- framecnt_t x = 0;
+ Gtk::TreeModel::Row newrow = *(tlmodel)->append();
+ newrow[tlcols.trackname] = rui->route()->name();
+ newrow[tlcols.visible] = true;
+ newrow[tlcols.color] = rui->route_color ();
+ newrow[tlcols.graph] = res;
+ }
+ } else if (source_selection_regions_rb.get_active()) {
+ RegionSelection ars = s.regions;
+ // std::cerr << "Analyzing selected regions" << std::endl;
+
+ for (RegionSelection::iterator j = ars.begin(); j != ars.end(); ++j) {
+ // Check that the region is actually audio (so we can analyze it)
+ AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*j);
+ if (!arv)
+ continue;
+
+ // std::cerr << " - " << (*j)->region().name() << ": " << (*j)->region().length() << " samples starting at " << (*j)->region().position() << std::endl;
+ RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView *>(&arv->get_time_axis_view());
+ if (!rtav) {
+ /* shouldn't happen... */
+ continue;
+ }
+ FFTResult *res = fft_graph.prepareResult(rtav->color(), arv->get_item_name());
+ int n;
+ for (unsigned int channel = 0; channel < arv->region()->n_channels(); channel++) {
- framecnt_t length = arv->region()->length();
+ framecnt_t x = 0;
+ framecnt_t length = arv->region()->length();
- while (x < length) {
- // TODO: What about stereo+ channels? composite all to one, I guess
+ while (x < length) {
+ // TODO: What about stereo+ channels? composite all to one, I guess
- n = fft_graph.windowSize();
- if (x + n >= length ) {
- n = length - x;
- }
+ n = fft_graph.windowSize();
+ if (x + n >= length ) {
+ n = length - x;
+ }
- memset (buf, 0, n * sizeof (Sample));
- n = arv->audio_region()->read_at(buf, mixbuf, gain, arv->region()->position() + x, n, channel);
+ memset (buf, 0, n * sizeof (Sample));
+ n = arv->audio_region()->read_at(buf, mixbuf, gain, arv->region()->position() + x, n, channel);
- if (n == 0)
- break;
+ if (n == 0)
+ break;
- if ( n < fft_graph.windowSize()) {
- for (int j = n; j < fft_graph.windowSize(); j++) {
- buf[j] = 0.0;
- }
+ if ( n < fft_graph.windowSize()) {
+ for (int j = n; j < fft_graph.windowSize(); j++) {
+ buf[j] = 0.0;
}
-
- res->analyzeWindow(buf);
-
- x += n;
}
- }
-// cerr << "Found: " << (*j)->get_item_name() << endl;
+ res->analyzeWindow(buf);
+ x += n;
+ }
}
+ // std::cerr << "Found: " << (*j)->get_item_name() << std::endl;
+ res->finalize();
- }
- res->finalize();
+ Gtk::TreeModel::Row newrow = *(tlmodel)->append();
+ newrow[tlcols.trackname] = arv->get_item_name();
+ newrow[tlcols.visible] = true;
+ newrow[tlcols.color] = rtav->color();
+ newrow[tlcols.graph] = res;
+ }
- Gtk::TreeModel::Row newrow = *(tlmodel)->append();
- newrow[tlcols.trackname] = rui->route()->name();
- newrow[tlcols.visible] = true;
- newrow[tlcols.color] = rui->color();
- newrow[tlcols.graph] = res;
}
free(buf);
free(mixbuf);
+ free(gain);
track_list_ready = true;
} /* end lock */