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