# HG changeset patch # User Chris Cannam # Date 1536764291 -3600 # Node ID 8068a0bee55058a15603dc4b6272a3dcba2044d9 # Parent c0d8356e274f1ed9a4c0cc0b275421fe6ec5e893# Parent f33ee2702447d3edffa09a69d2f0a618a56e2dd3 Merge from branch import-audio-data diff -r c0d8356e274f -r 8068a0bee550 files.pri --- a/files.pri Thu Aug 09 16:09:52 2018 +0100 +++ b/files.pri Wed Sep 12 15:58:11 2018 +0100 @@ -50,6 +50,7 @@ widgets/ColourMapComboBox.h \ widgets/ColourNameDialog.h \ widgets/CommandHistory.h \ + widgets/CSVAudioFormatDialog.h \ widgets/CSVFormatDialog.h \ widgets/Fader.h \ widgets/InteractiveFileFinder.h \ @@ -135,6 +136,7 @@ widgets/ColourMapComboBox.cpp \ widgets/ColourNameDialog.cpp \ widgets/CommandHistory.cpp \ + widgets/CSVAudioFormatDialog.cpp \ widgets/CSVFormatDialog.cpp \ widgets/Fader.cpp \ widgets/InteractiveFileFinder.cpp \ diff -r c0d8356e274f -r 8068a0bee550 layer/LayerFactory.h --- a/layer/LayerFactory.h Thu Aug 09 16:09:52 2018 +0100 +++ b/layer/LayerFactory.h Wed Sep 12 15:58:11 2018 +0100 @@ -13,8 +13,8 @@ COPYING included with this distribution for more information. */ -#ifndef _LAYER_FACTORY_H_ -#define _LAYER_FACTORY_H_ +#ifndef SV_LAYER_FACTORY_H +#define SV_LAYER_FACTORY_H #include #include diff -r c0d8356e274f -r 8068a0bee550 widgets/CSVAudioFormatDialog.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widgets/CSVAudioFormatDialog.cpp Wed Sep 12 15:58:11 2018 +0100 @@ -0,0 +1,220 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2018 Chris Cannam and QMUL. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "CSVAudioFormatDialog.h" + +#include "layer/LayerFactory.h" + +#include "TextAbbrev.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "base/Debug.h" + +CSVAudioFormatDialog::CSVAudioFormatDialog(QWidget *parent, CSVFormat format, + int maxDisplayCols) : + QDialog(parent), + m_format(format), + m_maxDisplayCols(maxDisplayCols), + m_fuzzyColumn(-1) +{ + setModal(true); + setWindowTitle(tr("Select Audio Data Format")); + + QGridLayout *layout = new QGridLayout; + + int row = 0; + + layout->addWidget + (new QLabel(tr("Please select the correct data format for this file.")), + row++, 0, 1, 4); + + QFrame *exampleFrame = new QFrame; + exampleFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + exampleFrame->setLineWidth(2); + QGridLayout *exampleLayout = new QGridLayout; + exampleLayout->setSpacing(4); + exampleFrame->setLayout(exampleLayout); + + QPalette palette = exampleFrame->palette(); + palette.setColor(QPalette::Window, palette.color(QPalette::Base)); + exampleFrame->setPalette(palette); + + QFont fp; + fp.setPointSize(int(floor(fp.pointSize() * 0.9))); + + int columns = format.getColumnCount(); + QList example = m_format.getExample(); + + for (int i = 0; i < columns; ++i) { + + QComboBox *cpc = new QComboBox; + m_columnPurposeCombos.push_back(cpc); + exampleLayout->addWidget(cpc, 0, i); + connect(cpc, SIGNAL(activated(int)), this, SLOT(columnPurposeChanged(int))); + + if (i == m_maxDisplayCols && columns > i + 2) { + m_fuzzyColumn = i; + + cpc->addItem(tr("")); + cpc->addItem(tr("Audio channels")); + cpc->setCurrentIndex + (m_format.getColumnPurpose(i-1) == CSVFormat::ColumnValue ? + 1 : 0); + + exampleLayout->addWidget + (new QLabel(tr("(%1 more)").arg(columns - i)), 1, i); + break; + } + + cpc->addItem(tr("")); + cpc->addItem(tr("Audio channel")); + cpc->setCurrentIndex + (m_format.getColumnPurpose(i) == CSVFormat::ColumnValue ? 1 : 0); + + for (int j = 0; j < example.size() && j < 6; ++j) { + if (i >= example[j].size()) { + continue; + } + QLabel *label = new QLabel; + label->setTextFormat(Qt::PlainText); + QString text = TextAbbrev::abbreviate(example[j][i], 35); + label->setText(text); + label->setFont(fp); + label->setPalette(palette); + label->setIndent(8); + exampleLayout->addWidget(label, j+1, i); + } + } + + layout->addWidget(exampleFrame, row, 0, 1, 4); + layout->setColumnStretch(3, 10); + layout->setRowStretch(row++, 10); + + layout->addWidget(new QLabel(tr("Audio sample rate (Hz):")), row, 0); + + int sampleRates[] = { + 8000, 11025, 12000, 22050, 24000, 32000, + 44100, 48000, 88200, 96000, 176400, 192000 + }; + + m_sampleRateCombo = new QComboBox; + for (int i = 0; i < int(sizeof(sampleRates) / sizeof(sampleRates[0])); ++i) { + m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i])); + if (sampleRates[i] == m_format.getSampleRate()) { + m_sampleRateCombo->setCurrentIndex(i); + } + } + m_sampleRateCombo->setEditable(true); + + layout->addWidget(m_sampleRateCombo, row++, 1); + connect(m_sampleRateCombo, SIGNAL(activated(QString)), + this, SLOT(sampleRateChanged(QString))); + connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)), + this, SLOT(sampleRateChanged(QString))); + + layout->addWidget(new QLabel(tr("Sample values are:")), row, 0); + + m_sampleRangeCombo = new QComboBox; + // NB must be in the same order as the CSVFormat::AudioSampleRange enum + m_sampleRangeCombo->addItem(tr("Floating-point in range -1 to 1")); + m_sampleRangeCombo->addItem(tr("8-bit in range 0 to 255")); + m_sampleRangeCombo->addItem(tr("16-bit in range -32768 to 32767")); + m_sampleRangeCombo->addItem(tr("Unknown range: normalise on load")); + m_sampleRangeCombo->setCurrentIndex(int(m_format.getAudioSampleRange())); + + layout->addWidget(m_sampleRangeCombo, row++, 1); + connect(m_sampleRangeCombo, SIGNAL(activated(int)), + this, SLOT(sampleRangeChanged(int))); + + QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok | + QDialogButtonBox::Cancel); + layout->addWidget(bb, row++, 0, 1, 4); + connect(bb, SIGNAL(accepted()), this, SLOT(accept())); + connect(bb, SIGNAL(rejected()), this, SLOT(reject())); + + setLayout(layout); + + updateFormatFromDialog(); +} + +CSVAudioFormatDialog::~CSVAudioFormatDialog() +{ +} + +CSVFormat +CSVAudioFormatDialog::getFormat() const +{ + return m_format; +} + +void +CSVAudioFormatDialog::sampleRateChanged(QString rateString) +{ + bool ok = false; + int sampleRate = rateString.toInt(&ok); + if (ok) m_format.setSampleRate(sampleRate); +} + +void +CSVAudioFormatDialog::sampleRangeChanged(int range) +{ + m_format.setAudioSampleRange((CSVFormat::AudioSampleRange)range); +} + +void +CSVAudioFormatDialog::columnPurposeChanged(int) +{ + updateFormatFromDialog(); +} + +void +CSVAudioFormatDialog::updateFormatFromDialog() +{ + m_format.setModelType(CSVFormat::WaveFileModel); + m_format.setTimingType(CSVFormat::ImplicitTiming); + m_format.setTimeUnits(CSVFormat::TimeAudioFrames); + + for (int i = 0; i < m_columnPurposeCombos.size(); ++i) { + + QComboBox *thisCombo = m_columnPurposeCombos[i]; + + CSVFormat::ColumnPurpose purpose = (thisCombo->currentIndex() == 1 ? + CSVFormat::ColumnValue : + CSVFormat::ColumnUnknown); + + if (i == m_fuzzyColumn) { + for (int j = i; j < m_format.getColumnCount(); ++j) { + m_format.setColumnPurpose(j, purpose); + } + } else { + m_format.setColumnPurpose(i, purpose); + } + } +} + + + diff -r c0d8356e274f -r 8068a0bee550 widgets/CSVAudioFormatDialog.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widgets/CSVAudioFormatDialog.h Wed Sep 12 15:58:11 2018 +0100 @@ -0,0 +1,57 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2018 Chris Cannam and QMUL. + + 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. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef SV_CSV_AUDIO_FORMAT_DIALOG_H +#define SV_CSV_AUDIO_FORMAT_DIALOG_H + +#include "data/fileio/CSVFormat.h" + +class QTableWidget; +class QComboBox; +class QLabel; + +#include + +class CSVAudioFormatDialog : public QDialog +{ + Q_OBJECT + +public: + CSVAudioFormatDialog(QWidget *parent, + CSVFormat initialFormat, + int maxDisplayCols = 5); + ~CSVAudioFormatDialog(); + + CSVFormat getFormat() const; + +protected slots: + void sampleRateChanged(QString); + void sampleRangeChanged(int); + void columnPurposeChanged(int purpose); + + void updateFormatFromDialog(); + +protected: + CSVFormat m_format; + int m_maxDisplayCols; + + QComboBox *m_sampleRateCombo; + QComboBox *m_sampleRangeCombo; + + QList m_columnPurposeCombos; + int m_fuzzyColumn; +}; + +#endif diff -r c0d8356e274f -r 8068a0bee550 widgets/CSVFormatDialog.cpp --- a/widgets/CSVFormatDialog.cpp Thu Aug 09 16:09:52 2018 +0100 +++ b/widgets/CSVFormatDialog.cpp Wed Sep 12 15:58:11 2018 +0100 @@ -4,7 +4,7 @@ Sonic Visualiser An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. - This file copyright 2006 Chris Cannam. + This file copyright 2006-2018 Chris Cannam and QMUL. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -48,8 +48,9 @@ int row = 0; - layout->addWidget(new QLabel(tr("Please select the correct data format for this file.")), - row++, 0, 1, 4); + layout->addWidget + (new QLabel(tr("Please select the correct data format for this file.")), + row++, 0, 1, 4); QFrame *exampleFrame = new QFrame; exampleFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); @@ -64,9 +65,6 @@ QFont fp; fp.setPointSize(int(floor(fp.pointSize() * 0.9))); -// fp.setFixedPitch(true); -// fp.setStyleHint(QFont::TypeWriter); -// fp.setFamily("Monospaced"); int columns = format.getColumnCount(); QList example = m_format.getExample(); @@ -77,15 +75,18 @@ m_columnPurposeCombos.push_back(cpc); exampleLayout->addWidget(cpc, 0, i); connect(cpc, SIGNAL(activated(int)), this, SLOT(columnPurposeChanged(int))); - + if (i == m_maxDisplayCols && columns > i + 2) { m_fuzzyColumn = i; + cpc->addItem(tr("")); cpc->addItem(tr("Values")); cpc->setCurrentIndex - (m_format.getColumnPurpose(i-1) == CSVFormat::ColumnUnknown ? 0 : 1); - exampleLayout->addWidget(new QLabel(tr("(%1 more)").arg(columns - i)), - 1, i); + (m_format.getColumnPurpose(i-1) == + CSVFormat::ColumnUnknown ? 0 : 1); + + exampleLayout->addWidget + (new QLabel(tr("(%1 more)").arg(columns - i)), 1, i); break; } @@ -98,7 +99,7 @@ cpc->addItem(tr("Pitch")); // ColumnPitch cpc->addItem(tr("Label")); // ColumnLabel cpc->setCurrentIndex(int(m_format.getColumnPurpose(i))); - + for (int j = 0; j < example.size() && j < 6; ++j) { if (i >= example[j].size()) { continue; @@ -132,12 +133,12 @@ for (auto &l: m_timingLabels) { m_timingTypeCombo->addItem(l.second); } - + layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2); - + connect(m_timingTypeCombo, SIGNAL(activated(int)), this, SLOT(timingTypeChanged(int))); - + m_initialTimingOption = TimingImplicit; if (m_format.getTimingType() == CSVFormat::ExplicitTiming) { switch (m_format.getTimeUnits()) { @@ -152,7 +153,7 @@ } } m_timingTypeCombo->setCurrentIndex(int(m_initialTimingOption)); - + m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):")); layout->addWidget(m_sampleRateLabel, row, 0); @@ -178,7 +179,7 @@ m_windowSizeLabel = new QLabel(tr("Frame increment between rows:")); layout->addWidget(m_windowSizeLabel, row, 0); - + m_windowSizeCombo = new QComboBox; for (int i = 0; i <= 16; ++i) { int value = 1 << i; @@ -188,7 +189,7 @@ } } m_windowSizeCombo->setEditable(true); - + layout->addWidget(m_windowSizeCombo, row++, 1); connect(m_windowSizeCombo, SIGNAL(activated(QString)), this, SLOT(windowSizeChanged(QString))); @@ -225,6 +226,10 @@ void CSVFormatDialog::updateModelLabel() { + if (!m_modelLabel) { + return; + } + LayerFactory *f = LayerFactory::getInstance(); QString s; @@ -244,9 +249,13 @@ case CSVFormat::ThreeDimensionalModel: s = f->getLayerPresentationName(LayerFactory::Colour3DPlot); break; + case CSVFormat::WaveFileModel: + s = f->getLayerPresentationName(LayerFactory::Waveform); + break; } - m_modelLabel->setText("\n" + tr("Data will be displayed in a %1 layer.").arg(s)); + m_modelLabel->setText("\n" + tr("Data will be displayed in a %1 layer.") + .arg(s)); } void @@ -341,6 +350,11 @@ QComboBox *cb = qobject_cast(o); if (!cb) return; + // Ensure a consistent set of column purposes, in case of a + // situation where some combinations are contradictory. Only + // updates the UI, does not update the stored format record from + // the UI - that's the job of updateFormatFromDialog + CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose)p; bool haveStartTime = false; // so as to update timing type combo appropriately @@ -412,7 +426,7 @@ updateFormatFromDialog(); updateComboVisibility(); } - + void CSVFormatDialog::updateFormatFromDialog() { @@ -422,23 +436,23 @@ m_format.setTimingType(CSVFormat::ExplicitTiming); m_format.setTimeUnits(CSVFormat::TimeSeconds); break; - + case TimingExplicitMsec: m_format.setTimingType(CSVFormat::ExplicitTiming); m_format.setTimeUnits(CSVFormat::TimeMilliseconds); break; - + case TimingExplicitSamples: m_format.setTimingType(CSVFormat::ExplicitTiming); m_format.setTimeUnits(CSVFormat::TimeAudioFrames); break; - + case TimingImplicit: m_format.setTimingType(CSVFormat::ImplicitTiming); m_format.setTimeUnits(CSVFormat::TimeWindows); break; } - + bool haveStartTime = false; bool haveDuration = false; bool havePitch = false; @@ -448,9 +462,9 @@ QComboBox *thisCombo = m_columnPurposeCombos[i]; - CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose) - (thisCombo->currentIndex()); - + CSVFormat::ColumnPurpose purpose = + (CSVFormat::ColumnPurpose) (thisCombo->currentIndex()); + if (i == m_fuzzyColumn) { for (int j = i; j < m_format.getColumnCount(); ++j) { if (purpose == CSVFormat::ColumnUnknown) { diff -r c0d8356e274f -r 8068a0bee550 widgets/CSVFormatDialog.h --- a/widgets/CSVFormatDialog.h Thu Aug 09 16:09:52 2018 +0100 +++ b/widgets/CSVFormatDialog.h Wed Sep 12 15:58:11 2018 +0100 @@ -13,8 +13,8 @@ COPYING included with this distribution for more information. */ -#ifndef _CSV_FORMAT_DIALOG_H_ -#define _CSV_FORMAT_DIALOG_H_ +#ifndef SV_CSV_FORMAT_DIALOG_H +#define SV_CSV_FORMAT_DIALOG_H #include "data/fileio/CSVFormat.h" @@ -29,7 +29,8 @@ Q_OBJECT public: - CSVFormatDialog(QWidget *parent, CSVFormat initialFormat, + CSVFormatDialog(QWidget *parent, + CSVFormat initialFormat, int maxDisplayCols = 5); ~CSVFormatDialog(); @@ -47,7 +48,7 @@ protected: CSVFormat m_format; int m_maxDisplayCols; - + enum TimingOption { TimingExplicitSeconds = 0, TimingExplicitMsec, @@ -57,6 +58,7 @@ std::map m_timingLabels; TimingOption m_initialTimingOption; + void columnPurposeChangedForAnnotationType(QComboBox *, int purpose); void updateComboVisibility(); void applyStartTimePurpose(); void removeStartTimePurpose();