File: BWFFile.hpp

package info (click to toggle)
jtdx 2.2.159%2Bimproved-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 75,336 kB
  • sloc: cpp: 38,503; f90: 31,141; python: 27,061; ansic: 11,772; sh: 409; fortran: 353; makefile: 232
file content (209 lines) | stat: -rw-r--r-- 7,404 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#ifndef BWF_FILE_HPP__
#define BWF_FILE_HPP__

#include <array>

#include <QFile>
#include <QMap>
#include <QByteArray>

#include "pimpl_h.hpp"

class QObject;
class QString;
class QAudioFormat;

//
// BWFFile - Broadcast Wave Format File (a.k.a. WAV file)
//
// The  BWF file  format is  a  backward compatible  variation of  the
// Microsoft  WAV file  format. It  contains  an extra  chunk with  id
// 'bext' that contains metadata defined by the EBU in:
//
//  https://tech.ebu.ch/docs/tech/tech3285.pdf
//
// Also relevant is the recommendation document:
//
//  https://tech.ebu.ch/docs/r/r098.pdf
//
// which suggests a format to the free text coding history field.
//
// This class also supports the LIST-INFO chunk type which also allows
// metadata to be  added to a WAV  file, the defined INFO  tag ids are
// documented here:
//
//  http://bwfmetaedit.sourceforge.net/listinfo.html
//
// These  ids  are not  enforced  but  they  are recommended  as  most
// operating systems and audio applications  recognize some or more of
// them. Notably Microsoft Windows is not one of the operating systems
// that  does :(  In fact  there seems  to be  no documented  metadata
// tagging format that Windows Explorer recognizes.
//
// Changes to  the 'bext' fields  and the LIST-INFO dictionary  may be
// made right up  until the file is closed as  the relevant chunks are
// saved to the end of the file after the end of the sample data.
//
// This class emulates the QFile class, in fact it uses a QFile object
// instance internally and forwards many of its operations directly to
// it.
//
// BWFFile  is a  QIODevice subclass  and the  implementation provides
// access to  the audio sample  data contained in  the BWF file  as if
// only that data were  in the file. I.e. the first  sample is at file
// offset zero  and the  size of the  file is the  size of  the sample
// data.  The headers,  trailers and  metadata are  hidden but  can be
// accessed by the operations below.
//
class BWFFile
  : public QIODevice
{
  Q_OBJECT
public:
  using FileHandleFlags = QFile::FileHandleFlags;
  using Permissions = QFile::Permissions;
  using FileError = QFile::FileError;
  using MemoryMapFlags = QFile::MemoryMapFlags;
  using InfoDictionary = QMap<std::array<char, 4>, QByteArray>;
  using UMID = std::array<quint8, 64>;

  explicit BWFFile (QAudioFormat const&, QObject * parent = nullptr);
  explicit BWFFile (QAudioFormat const&, QString const& name,
                    QObject * parent = nullptr);

  // The  InfoDictionary should  contain  valid  WAV format  LIST-INFO
  // identifiers as keys, a list of them can be found here:
  //
  // http://bwfmetaedit.sourceforge.net/listinfo.html
  //
  // For  files  opened for  ReadOnly  access  the dictionary  is  not
  // written to  the file.  For  files opened ReadWrite,  any existing
  // LIST-INFO tags will  be merged into the dictionary  when the file
  // is opened and if the file  is modified the merged dictionary will
  // be written back to the file.
  //
  // Note that the sample  data may no be in the  native endian, it is
  // the   callers   responsibility   to  do   any   required   endian
  // conversions. The  internal data is  always in native  endian with
  // conversions  being handled  automatically. Use  the BWF::format()
  // operation     to    access     the    format     including    the
  // QAudioFormat::byteOrder()  operation to  determine the  data byte
  // ordering.
  //
  explicit BWFFile (QAudioFormat const&, QString const& name,
                    InfoDictionary const&, QObject * parent = nullptr);

  ~BWFFile ();
  QAudioFormat const& format () const;
  InfoDictionary& list_info ();

  //
  // Broadcast Audio Extension fields
  //
  // If any of these modifiers are  called then a "bext" chunk will be
  // written to the file if the  file is writeable and the sample data
  // is modified.
  //
  enum class BextVersion : quint16 {v_0, v_1, v_2};
  BextVersion bext_version () const;
  void bext_version (BextVersion = BextVersion::v_2);

  QByteArray bext_description () const;
  void bext_description (QByteArray const&); // max 256 bytes

  QByteArray bext_originator () const;
  void bext_originator (QByteArray const&);        // max 32 bytes

  QByteArray bext_originator_reference () const;
  void bext_originator_reference (QByteArray const&); // max 32 bytes

  QDateTime bext_origination_date_time () const;
  void bext_origination_date_time (QDateTime const&); // 1s resolution

  quint64 bext_time_reference () const;
  void bext_time_reference (quint64); // samples since midnight at start

  UMID bext_umid () const; // bext version >= 1 only
  void bext_umid (UMID const&);

  quint16 bext_loudness_value () const;
  void bext_loudness_value (quint16); // bext version >= 2 only

  quint16 bext_loudness_range () const;
  void bext_loudness_range (quint16); // bext version >= 2 only

  quint16 bext_max_true_peak_level () const;
  void bext_max_true_peak_level (quint16); // bext version >= 2 only

  quint16 bext_max_momentary_loudness () const;
  void bext_max_momentary_loudness (quint16); // bext version >= 2 only

  quint16 bext_max_short_term_loudness () const;
  void bext_max_short_term_loudness (quint16); // bext version >= 2 only

  QByteArray bext_coding_history () const;
  void bext_coding_history (QByteArray const&); // See EBU R 98


  // Emulate QFile interface
  bool open (OpenMode) override;
  bool open (FILE *, OpenMode, FileHandleFlags = QFile::DontCloseHandle);
  bool open (int fd, OpenMode, FileHandleFlags = QFile::DontCloseHandle);
  bool copy (QString const& new_name);
  bool exists () const;
  bool link (QString const& link_name);
  bool remove ();
  bool rename (QString const& new_name);
  void setFileName (QString const& name);
  QString symLinkTarget () const;
  QString fileName () const;
  Permissions permissions () const;

  // Resize is of the sample data portion, header and trailer chunks
  // are excess to the given size
  bool resize (qint64 new_size);

  bool setPermissions (Permissions permissions);
  FileError error () const;
  bool flush ();
  int handle () const;

  // The mapping offset is relative to the start of the sample data
  uchar * map (qint64 offset, qint64 size,
               MemoryMapFlags = QFile::NoOptions);
  bool unmap (uchar * address);

  void unsetError ();


  //
  // QIODevice implementation
  //

  // The size returned is of the sample data only, header and trailer
  // chunks are hidden and handled internally
  qint64 size () const override;

  bool isSequential () const override;

  // The reset  operation clears the  'bext' and LIST-INFO as  if they
  // were  never supplied.  If the  file  is writable  the 'bext'  and
  // LIST-INFO chunks will not be  written making the resulting file a
  // lowest common denominator WAV file.
  bool reset () override;

  // Seek offsets are relative to the start of the sample data
  bool seek (qint64) override;

  void close () override;

protected:
  qint64 readData (char * data, qint64 max_size) override;
  qint64 writeData (char const* data, qint64 max_size) override;

private:
  class impl;
  pimpl<impl> m_;
};

#endif