Chris@392: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@392: Chris@392: /* Chris@392: Sonic Visualiser Chris@392: An audio file viewer and annotation editor. Chris@392: Centre for Digital Music, Queen Mary, University of London. Chris@392: This file copyright 2006 Chris Cannam. Chris@392: Chris@392: This program is free software; you can redistribute it and/or Chris@392: modify it under the terms of the GNU General Public License as Chris@392: published by the Free Software Foundation; either version 2 of the Chris@392: License, or (at your option) any later version. See the file Chris@392: COPYING included with this distribution for more information. Chris@392: */ Chris@392: Chris@1362: #ifndef SV_CSV_FORMAT_H Chris@1362: #define SV_CSV_FORMAT_H Chris@392: Chris@392: #include Chris@392: #include Chris@392: Chris@1585: #include Chris@1585: Chris@1047: #include "base/BaseTypes.h" Chris@1047: Chris@392: class CSVFormat Chris@392: { Chris@392: public: Chris@392: enum ModelType { Chris@1429: OneDimensionalModel, Chris@1429: TwoDimensionalModel, Chris@628: TwoDimensionalModelWithDuration, Chris@897: TwoDimensionalModelWithDurationAndPitch, Chris@1488: ThreeDimensionalModel, Chris@1488: WaveFileModel Chris@392: }; Chris@392: Chris@392: enum TimingType { Chris@1429: ExplicitTiming, Chris@1429: ImplicitTiming Chris@392: }; Chris@628: Chris@392: enum TimeUnits { Chris@1429: TimeSeconds, Chris@990: TimeMilliseconds, Chris@1429: TimeAudioFrames, Chris@1429: TimeWindows, Chris@392: }; Chris@392: Chris@629: enum ColumnPurpose { Chris@629: ColumnUnknown, Chris@629: ColumnStartTime, Chris@629: ColumnEndTime, Chris@629: ColumnDuration, Chris@629: ColumnValue, Chris@897: ColumnPitch, Chris@629: ColumnLabel Chris@629: }; Chris@629: Chris@629: enum ColumnQuality { Chris@1512: ColumnNumeric = 1, // No non-numeric values were seen in sample Chris@1512: ColumnIntegral = 2, // All sampled values were integers Chris@1512: ColumnIncreasing = 4, // Sampled values were monotonically increasing Chris@1512: ColumnSmall = 8, // All sampled values had magnitude < 1 Chris@1512: ColumnLarge = 16, // Values "quickly" grew to over 1000 Chris@1512: ColumnSigned = 32, // Some negative values were seen Chris@1512: ColumnNearEmpty = 64, // Nothing in this column beyond first row Chris@629: }; Chris@629: typedef unsigned int ColumnQualities; Chris@392: Chris@1515: enum AudioSampleRange { Chris@1515: SampleRangeSigned1 = 0, // -1 .. 1 Chris@1515: SampleRangeUnsigned255, // 0 .. 255 Chris@1515: SampleRangeSigned32767, // -32768 .. 32767 Chris@1515: SampleRangeOther // Other/unknown: Normalise on load Chris@1515: }; Chris@1515: Chris@392: CSVFormat() : // arbitrary defaults Chris@392: m_modelType(TwoDimensionalModel), Chris@392: m_timingType(ExplicitTiming), Chris@392: m_timeUnits(TimeSeconds), Chris@1585: m_separator(""), Chris@392: m_sampleRate(44100), Chris@392: m_windowSize(1024), Chris@629: m_columnCount(0), Chris@629: m_variableColumnCount(false), Chris@1516: m_audioSampleRange(SampleRangeOther), Chris@629: m_allowQuoting(true), Chris@629: m_maxExampleCols(0) Chris@392: { } Chris@629: Chris@629: CSVFormat(QString path); // guess format Chris@629: Chris@629: /** Chris@629: * Guess the format of the given CSV file, setting the fields in Chris@629: * this object accordingly. If the current separator is the empty Chris@629: * string, the separator character will also be guessed; otherwise Chris@629: * the current separator will be used. The other properties of Chris@629: * this object will be set according to guesses from the file. Chris@1524: * Chris@1524: * The properties that are guessed from the file contents are: Chris@1524: * separator, column count, variable-column-count flag, audio Chris@1524: * sample range, timing type, time units, column qualities, column Chris@1524: * purposes, and model type. The sample rate and window size Chris@1524: * cannot be guessed and will not be changed by this function. Chris@1524: * Note also that this function will never guess WaveFileModel for Chris@1524: * the model type. Chris@1524: * Chris@1524: * Return false if there is some fundamental error, e.g. the file Chris@1524: * could not be opened at all. Return true otherwise. Note that Chris@1524: * this function returns true even if the file doesn't appear to Chris@1524: * make much sense as a data format. Chris@629: */ Chris@1524: bool guessFormatFor(QString path); Chris@628: Chris@628: ModelType getModelType() const { return m_modelType; } Chris@628: TimingType getTimingType() const { return m_timingType; } Chris@628: TimeUnits getTimeUnits() const { return m_timeUnits; } Chris@1047: sv_samplerate_t getSampleRate() const { return m_sampleRate; } Chris@929: int getWindowSize() const { return m_windowSize; } Chris@630: int getColumnCount() const { return m_columnCount; } Chris@1516: AudioSampleRange getAudioSampleRange() const { return m_audioSampleRange; } Chris@631: bool getAllowQuoting() const { return m_allowQuoting; } Chris@631: QChar getSeparator() const { Chris@1585: if (m_separator == "") return ','; Chris@631: else return m_separator[0]; Chris@631: } Chris@1585: // set rather than QSet to ensure a fixed order Chris@1585: std::set getPlausibleSeparators() const { Chris@1585: return m_plausibleSeparators; Chris@1585: } Chris@630: Chris@628: void setModelType(ModelType t) { m_modelType = t; } Chris@628: void setTimingType(TimingType t) { m_timingType = t; } Chris@628: void setTimeUnits(TimeUnits t) { m_timeUnits = t; } Chris@631: void setSeparator(QChar s) { m_separator = s; } Chris@1047: void setSampleRate(sv_samplerate_t r) { m_sampleRate = r; } Chris@1009: void setWindowSize(int s) { m_windowSize = s; } Chris@630: void setColumnCount(int c) { m_columnCount = c; } Chris@1516: void setAudioSampleRange(AudioSampleRange r) { m_audioSampleRange = r; } Chris@631: void setAllowQuoting(bool q) { m_allowQuoting = q; } Chris@392: Chris@631: QList getColumnPurposes() const { return m_columnPurposes; } Chris@629: void setColumnPurposes(QList cl) { m_columnPurposes = cl; } Chris@631: Chris@631: ColumnPurpose getColumnPurpose(int i); Chris@631: ColumnPurpose getColumnPurpose(int i) const; Chris@631: void setColumnPurpose(int i, ColumnPurpose p); Chris@392: Chris@629: // read-only; only valid if format has been guessed: Chris@1510: const QList &getColumnQualities() const { Chris@1510: return m_columnQualities; Chris@1510: } Chris@629: Chris@629: // read-only; only valid if format has been guessed: Chris@1510: const QList &getExample() const { Chris@1510: return m_example; Chris@1510: } Chris@1510: Chris@392: int getMaxExampleCols() const { return m_maxExampleCols; } Chris@1429: Chris@392: protected: Chris@628: ModelType m_modelType; Chris@628: TimingType m_timingType; Chris@628: TimeUnits m_timeUnits; Chris@1585: QString m_separator; // "" or a single char - basically QChar option Chris@1585: std::set m_plausibleSeparators; Chris@1047: sv_samplerate_t m_sampleRate; Chris@929: int m_windowSize; Chris@392: Chris@629: int m_columnCount; Chris@629: bool m_variableColumnCount; Chris@629: Chris@629: QList m_columnQualities; Chris@629: QList m_columnPurposes; Chris@629: Chris@1515: AudioSampleRange m_audioSampleRange; Chris@1515: Chris@629: QList m_prevValues; Chris@629: Chris@629: bool m_allowQuoting; Chris@392: Chris@392: QList m_example; Chris@392: int m_maxExampleCols; Chris@629: Chris@629: void guessSeparator(QString line); Chris@629: void guessQualities(QString line, int lineno); Chris@629: void guessPurposes(); Chris@1515: void guessAudioSampleRange(); Chris@392: }; Chris@392: Chris@392: #endif