Audacity  2.2.2
LegacyBlockFile.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  LegacyBlockFile.cpp
6 
7  Dominic Mazzoni
8 
9 ******************************************************************//******************************************************************/
19 
20 
21 #include "../Audacity.h"
22 #include "LegacyBlockFile.h"
23 
24 #include <float.h>
25 #include <math.h>
26 
27 #include <wx/filefn.h>
28 #include <wx/file.h>
29 #include <wx/ffile.h>
30 #include <wx/utils.h>
31 #include <wx/log.h>
32 
33 #include "../MemoryX.h"
34 #include "../FileFormats.h"
35 #include "../Internat.h"
36 
37 #include "sndfile.h"
38 
39 void ComputeLegacySummaryInfo(const wxFileName &fileName,
40  size_t summaryLen,
42  SummaryInfo *info,
43  bool noRMS,bool Silent,
44  float *min, float *max, float *rms)
45 {
46  int fields = 3; /* min, max, rms */
47 
48  if (noRMS)
49  fields = 2;
50 
51  info->fields = fields;
52  info->format = format;
53  info->bytesPerFrame =
54  SAMPLE_SIZE(info->format) * fields;
55  info->totalSummaryBytes = summaryLen;
56  info->offset64K = 20; /* legacy header tag len */
57  info->frames64K = (summaryLen-20) /
58  (info->bytesPerFrame * 256);
59  info->offset256 = info->offset64K +
60  (info->frames64K * info->bytesPerFrame);
61  info->frames256 =
62  (summaryLen - 20 -
63  (info->frames64K * info->bytesPerFrame)) /
64  info->bytesPerFrame;
65 
66  //
67  // Compute the min, max, and RMS of the block from the
68  // 64K summary data
69  //
70 
71  Floats summary{ info->frames64K * fields };
72  SampleBuffer data(info->frames64K * fields,
73  info->format);
74 
75  int read;
76  {
77  Maybe<wxLogNull> silence{};
78  const wxString fullPath{ fileName.GetFullPath() };
79  wxFFile summaryFile(fullPath, wxT("rb"));
80  if (Silent)
81  silence.create();
82 
83  // FIXME: TRAP_ERR no report to user of absent summary files.
84  if (!summaryFile.IsOpened()) {
85  wxLogWarning(wxT("Unable to access summary file %s; substituting silence for remainder of session"),
86  fullPath);
87 
88  read = info->frames64K * info->bytesPerFrame;
89  memset(data.ptr(), 0, read);
90  }
91  else{
92  // FIXME: TRAP_ERR Seek in summary file could fail.
93  summaryFile.Seek(info->offset64K);
94  read = summaryFile.Read(data.ptr(),
95  info->frames64K *
96  info->bytesPerFrame);
97  }
98  }
99 
100  int count = read / info->bytesPerFrame;
101 
102  CopySamples(data.ptr(), info->format,
103  (samplePtr)summary.get(), floatSample, count);
104 
105  (*min) = FLT_MAX;
106  (*max) = FLT_MIN;
107  float sumsq = 0;
108 
109  for(int i=0; i<count; i++) {
110  if (summary[fields*i] < (*min))
111  (*min) = summary[fields*i];
112  if (summary[fields*i+1] > (*max))
113  (*max) = summary[fields*i+1];
114  if (fields >= 3)
115  sumsq += summary[fields*i+2]*summary[fields*i+2];
116  }
117  if (fields >= 3)
118  (*rms) = sqrt(sumsq / count);
119  else
120  (*rms) = 0;
121 }
122 
129  size_t summaryLen,
130  size_t len,
131  bool noRMS):
132  BlockFile{ std::move(existingFile), len },
133  mFormat(format)
134 {
135 
136  sampleFormat summaryFormat;
137 
138  if (noRMS)
139  summaryFormat = int16Sample;
140  else
141  summaryFormat = floatSample;
142 
143  ComputeLegacySummaryInfo(mFileName,
144  summaryLen, summaryFormat,
145  &mSummaryInfo, noRMS, FALSE,
146  &mMin, &mMax, &mRMS);
147 }
148 
150 {
151 }
152 
159 {
161  wxFFile summaryFile(mFileName.GetFullPath(), wxT("rb"));
162  size_t read;
163  {
164  Maybe<wxLogNull> silence{};
165  if (mSilentLog)
166  silence.create();
167 
168  if (!summaryFile.IsOpened()) {
169 
170  memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
171 
172  mSilentLog = TRUE;
173 
174  return false;
175  }
176 
177  read = summaryFile.Read(data.get(), mSummaryInfo.totalSummaryBytes);
178  }
179  mSilentLog = FALSE;
180 
181  if (read != mSummaryInfo.totalSummaryBytes) {
182  memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
183  return false;
184  }
185 
186  return true;
187 }
188 
197  size_t start, size_t len, bool mayThrow) const
198 {
199  sf_count_t origin = (mSummaryInfo.totalSummaryBytes / SAMPLE_SIZE(mFormat));
200  return CommonReadData( mayThrow,
201  mFileName, mSilentLog, nullptr, origin, 0, data, format, start, len,
202  &mFormat, mLen
203  );
204 }
205 
207 // may throw
208 {
209  xmlFile.StartTag(wxT("legacyblockfile"));
210 
211  xmlFile.WriteAttr(wxT("name"), mFileName.GetFullName());
212  xmlFile.WriteAttr(wxT("len"), mLen);
213  if (mSummaryInfo.fields < 3)
214  xmlFile.WriteAttr(wxT("norms"), 1);
215  xmlFile.WriteAttr(wxT("summarylen"), mSummaryInfo.totalSummaryBytes);
216 
217  xmlFile.EndTag(wxT("legacyblockfile"));
218 }
219 
220 // BuildFromXML methods should always return a BlockFile, not NULL,
221 // even if the result is flawed (e.g., refers to nonexistent file),
222 // as testing will be done in DirManager::ProjectFSCK().
224 BlockFilePtr LegacyBlockFile::BuildFromXML(const wxString &projDir, const wxChar **attrs,
225  size_t len, sampleFormat format)
226 {
227  wxFileNameWrapper fileName;
228  size_t summaryLen = 0;
229  bool noRMS = false;
230  long nValue;
231 
232  while(*attrs)
233  {
234  const wxChar *attr = *attrs++;
235  const wxChar *value = *attrs++;
236  if (!value)
237  break;
238 
239  const wxString strValue = value;
240  if (!wxStricmp(attr, wxT("name")) && XMLValueChecker::IsGoodFileName(strValue, projDir))
241  //v Should this be
242  // dm.AssignFile(fileName, strValue, false);
243  // as in PCMAliasBlockFile::BuildFromXML? Test with an old project.
244  fileName.Assign(projDir, strValue);
245  else if (XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue))
246  { // integer parameters
247  if (!wxStrcmp(attr, wxT("len")) && (nValue >= 0))
248  len = nValue;
249  else if (!wxStrcmp(attr, wxT("norms")))
250  noRMS = (nValue != 0);
251  else if (!wxStrcmp(attr, wxT("format")) && XMLValueChecker::IsValidSampleFormat(nValue))
252  format = (sampleFormat)nValue;
253  else if (!wxStrcmp(attr, wxT("summarylen")) && (nValue > 0))
254  // Note attribute "summarylen" was written as int, no need for 64 bits
255  summaryLen = nValue;
256  }
257  }
258 
259  return make_blockfile<LegacyBlockFile>
260  (std::move(fileName), format, summaryLen, len, noRMS);
261 }
262 
267 {
268  return make_blockfile<LegacyBlockFile>
269  (std::move(newFileName),
271  mLen, mSummaryInfo.fields < 3);
272 }
273 
275 {
276  wxFFile dataFile(mFileName.GetFullPath());
277  return dataFile.Length();
278 }
279 
281 {
282 
283 
284 }
int bytesPerFrame
Definition: BlockFile.h:36
sampleFormat format
Definition: BlockFile.h:35
virtual void StartTag(const wxString &name)
Definition: XMLWriter.cpp:78
A BlockFile is a chunk of immutable audio data.
Definition: BlockFile.h:56
wxFileNameWrapper mFileName
Definition: BlockFile.h:235
virtual void WriteAttr(const wxString &name, const wxString &value)
Definition: XMLWriter.cpp:131
virtual void EndTag(const wxString &name)
Definition: XMLWriter.cpp:101
void ComputeLegacySummaryInfo(const wxFileName &fileName, size_t summaryLen, sampleFormat format, SummaryInfo *info, bool noRMS, bool Silent, float *min, float *max, float *rms)
size_t frames256
Definition: BlockFile.h:39
LegacyBlockFile(wxFileNameWrapper &&existingFile, sampleFormat format, size_t summaryLen, size_t len, bool noRMS)
Create the memory structure to refer to the given block file.
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:117
int offset64K
Definition: BlockFile.h:38
void CopySamples(samplePtr src, sampleFormat srcFormat, samplePtr dst, sampleFormat dstFormat, unsigned int len, bool highQuality, unsigned int srcStride, unsigned int dstStride)
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
bool mSilentLog
Definition: BlockFile.h:239
sampleFormat mFormat
Definition: MemoryX.h:204
static BlockFilePtr BuildFromXML(const wxString &dir, const wxChar **attrs, size_t len, sampleFormat format)
static
SummaryInfo mSummaryInfo
Definition: BlockFile.h:237
static bool IsGoodInt(const wxString &strInt)
Check that the supplied string can be converted to a long (32bit) integer.
unsigned long long DiskByteCount
Definition: BlockFile.h:152
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
int format
Definition: ExportPCM.cpp:56
sampleFormat
Definition: Types.h:188
char * samplePtr
Definition: Types.h:203
Works with BlockFile to hold info about max and min and RMS over multiple samples, which in turn allows rapid drawing when zoomed out.
Definition: BlockFile.h:30
size_t totalSummaryBytes
Definition: BlockFile.h:41
size_t ReadData(samplePtr data, sampleFormat format, size_t start, size_t len, bool mayThrow) const override
Read the data section of the disk file.
int min(int a, int b)
samplePtr ptr() const
Definition: SampleFormat.h:81
void Recover() override
if the on-disk state disappeared, either recover it (if it was
size_t mLen
Definition: BlockFile.h:236
static bool IsValidSampleFormat(const int nValue)
static size_t CommonReadData(bool mayThrow, const wxFileName &fileName, bool &mSilentLog, const AliasBlockFile *pAliasFile, sampleCount origin, unsigned channel, samplePtr data, sampleFormat format, size_t start, size_t len, const sampleFormat *pLegacyFormat=nullptr, size_t legacyLen=0)
Definition: BlockFile.cpp:483
int fields
Definition: BlockFile.h:34
size_t frames64K
Definition: BlockFile.h:37
DiskByteCount GetSpaceUsage() const override
bool ReadSummary(ArrayOf< char > &data) override
Read the summary section of the disk file.
static bool IsGoodFileName(const wxString &strFileName, const wxString &strDirName=wxEmptyString)
int offset256
Definition: BlockFile.h:40
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:22
BlockFilePtr Copy(wxFileNameWrapper &&newFileName) override
Create a NEW block file identical to this one.
void SaveXML(XMLWriter &xmlFile) override
Write an XML representation of this file.
void create(Args &&...args)
Definition: MemoryX.h:251
virtual ~LegacyBlockFile()