Audacity  3.0.3
Public Member Functions | Static Public Member Functions | Protected Member Functions | Private Attributes | List of all members
SimpleBlockFile Class Reference

A BlockFile that reads and writes uncompressed data using libsndfile. More...

#include <SimpleBlockFile.h>

Inheritance diagram for SimpleBlockFile:
[legend]
Collaboration diagram for SimpleBlockFile:
[legend]

Public Member Functions

 SimpleBlockFile (wxFileNameWrapper &&baseFileName, samplePtr sampleData, size_t sampleLen, sampleFormat format)
 Create a disk file and write summary and sample data to it. More...
 
 SimpleBlockFile (wxFileNameWrapper &&existingFile, size_t len, float min, float max, float rms)
 Create the memory structure to refer to the given block file. More...
 
virtual ~SimpleBlockFile ()
 
bool ReadSummary (ArrayOf< char > &data) override
 Read the summary section of the disk file. More...
 
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. More...
 
BlockFilePtr Copy (wxFileNameWrapper &&newFileName) override
 Create a NEW block file identical to this one. More...
 
void SaveXML (XMLWriter &xmlFile) override
 Write an XML representation of this file. More...
 
DiskByteCount GetSpaceUsage () const override
 
void Recover () override
 

Static Public Member Functions

static BlockFilePtr BuildFromXML (DirManager &dm, const wxChar **attrs)
 static More...
 

Protected Member Functions

bool WriteSimpleBlockFile (samplePtr sampleData, size_t sampleLen, sampleFormat format, void *summaryData)
 

Private Attributes

sampleFormat mFormat
 

Detailed Description

A BlockFile that reads and writes uncompressed data using libsndfile.

A block file that writes the audio data to an .au file and reads it back using libsndfile.

There are two ways to construct a simple block file. One is to supply data and have the constructor write the file. The other is for when the file already exists and we simply want to create the data structure to refer to it.

Definition at line 34 of file SimpleBlockFile.h.

Constructor & Destructor Documentation

◆ SimpleBlockFile() [1/2]

SimpleBlockFile::SimpleBlockFile ( wxFileNameWrapper &&  baseFileName,
samplePtr  sampleData,
size_t  sampleLen,
sampleFormat  format 
)

Create a disk file and write summary and sample data to it.

Constructs a SimpleBlockFile based on sample data and writes it to disk.

Parameters
baseFileNameThe filename to use, but without an extension. This constructor will add the appropriate extension (.au in this case).
sampleDataThe sample data to be written to this block.
sampleLenThe number of samples to be written to this block.
formatThe format of the given samples.
allowDeferredWriteAllow deferred write-caching

Definition at line 77 of file SimpleBlockFile.cpp.

79  :
80  BlockFile {
81  (baseFileName.SetExt(wxT("au")), std::move(baseFileName)),
82  sampleLen
83  }
84 {
85  mFormat = format;
86 
87  bool bSuccess = WriteSimpleBlockFile(sampleData, sampleLen, format, NULL);
88  if (!bSuccess)
89  throw FileException{
90  FileException::Cause::Write, GetFileName().name };
91 }

◆ SimpleBlockFile() [2/2]

SimpleBlockFile::SimpleBlockFile ( wxFileNameWrapper &&  existingFile,
size_t  len,
float  min,
float  max,
float  rms 
)

Create the memory structure to refer to the given block file.

Construct a SimpleBlockFile memory structure that will point to an existing block file. This file must exist and be a valid block file.

Parameters
existingFileThe disk file this SimpleBlockFile should use.

Definition at line 97 of file SimpleBlockFile.cpp.

98  :
99  BlockFile{ std::move(existingFile), len }
100 {
101  // Set an invalid format to force GetSpaceUsage() to read it from the file.
102  mFormat = (sampleFormat) 0;
103 
104  mMin = min;
105  mMax = max;
106  mRMS = rms;
107 }

◆ ~SimpleBlockFile()

SimpleBlockFile::~SimpleBlockFile ( )
virtual

Definition at line 109 of file SimpleBlockFile.cpp.

110 {
111 }

Member Function Documentation

◆ BuildFromXML()

BlockFilePtr SimpleBlockFile::BuildFromXML ( DirManager &  dm,
const wxChar **  attrs 
)
static

static

Definition at line 292 of file SimpleBlockFile.cpp.

293 {
294  wxFileNameWrapper fileName;
295  float min = 0.0f, max = 0.0f, rms = 0.0f;
296  size_t len = 0;
297  double dblValue;
298  long nValue;
299 
300  while(*attrs)
301  {
302  const wxChar *attr = *attrs++;
303  const wxChar *value = *attrs++;
304  if (!value)
305  break;
306 
307  const wxString strValue = value;
308  if (!wxStricmp(attr, wxT("filename")) &&
309  // Can't use XMLValueChecker::IsGoodFileName here, but do part of its test.
311  (strValue.length() + 1 + dm.GetProjectDataDir().length() <= PLATFORM_MAX_PATH))
312  {
313  if (!dm.AssignFile(fileName, strValue, false))
314  // Make sure fileName is back to uninitialized state so we can detect problem later.
315  fileName.Clear();
316  }
317  else if (!wxStrcmp(attr, wxT("len")) &&
318  XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue) &&
319  nValue > 0)
320  len = nValue;
321  else if (XMLValueChecker::IsGoodString(strValue) && Internat::CompatibleToDouble(strValue, &dblValue))
322  { // double parameters
323  if (!wxStricmp(attr, wxT("min")))
324  min = dblValue;
325  else if (!wxStricmp(attr, wxT("max")))
326  max = dblValue;
327  else if (!wxStricmp(attr, wxT("rms")) && (dblValue >= 0.0))
328  rms = dblValue;
329  }
330  }
331 
332  return make_blockfile<SimpleBlockFile>
333  (std::move(fileName), len, min, max, rms);
334 }

References Internat::CompatibleToDouble(), XMLValueChecker::IsGoodFileString(), XMLValueChecker::IsGoodInt(), XMLValueChecker::IsGoodString(), min(), and PLATFORM_MAX_PATH.

Here is the call graph for this function:

◆ Copy()

BlockFilePtr SimpleBlockFile::Copy ( wxFileNameWrapper &&  newFileName)
override

Create a NEW block file identical to this one.

Create a copy of this BlockFile, but using a different disk file.

Parameters
newFileNameThe name of the NEW file to use.

Definition at line 339 of file SimpleBlockFile.cpp.

340 {
341  auto newBlockFile = make_blockfile<SimpleBlockFile>
342  (std::move(newFileName), mLen, mMin, mMax, mRMS);
343 
344  return newBlockFile;
345 }

Referenced by ODDecodeBlockFile::Copy().

Here is the caller graph for this function:

◆ GetSpaceUsage()

auto SimpleBlockFile::GetSpaceUsage ( ) const
override

Definition at line 347 of file SimpleBlockFile.cpp.

348 {
349  // Don't know the format, so it must be read from the file
350  if (mFormat == (sampleFormat) 0)
351  {
352  // Check sample format
353  wxFFile file(mFileName.GetFullPath(), wxT("rb"));
354  if (!file.IsOpened())
355  {
356  return 0;
357  }
358 
359  auHeader header;
360 
361  if (file.Read(&header, sizeof(header)) != sizeof(header))
362  {
363  // Corrupt file
364  return 0;
365  }
366 
367  wxUint32 encoding;
368 
369  if (header.magic == 0x2e736e64)
370  encoding = header.encoding; // correct endianness
371  else
372  encoding = SwapUintEndianess(header.encoding);
373 
374  switch (encoding)
375  {
376  case AU_SAMPLE_FORMAT_16:
378  break;
379  case AU_SAMPLE_FORMAT_24:
381  break;
382  default:
383  // floatSample is a safe default (we will never loose data)
385  break;
386  }
387 
388  file.Close();
389  }
390 
391  return (
392  sizeof(auHeader) +
393  mSummaryInfo.totalSummaryBytes +
394  (GetLength() * SAMPLE_SIZE_DISK(mFormat))
395  );
396 }

References AU_SAMPLE_FORMAT_16, AU_SAMPLE_FORMAT_24, auHeader::encoding, floatSample, int16Sample, int24Sample, auHeader::magic, mFormat, SAMPLE_SIZE_DISK, and SwapUintEndianess().

Here is the call graph for this function:

◆ ReadData()

size_t SimpleBlockFile::ReadData ( samplePtr  data,
sampleFormat  format,
size_t  start,
size_t  len,
bool  mayThrow 
) const
override

Read the data section of the disk file.

Read the data portion of the block file using libsndfile. Convert it to the given format if it is not already.

Parameters
dataThe buffer where the data will be stored
formatThe format the data will be stored in
startThe offset in this block file
lenThe number of samples to read

Definition at line 267 of file SimpleBlockFile.cpp.

269 {
270  return CommonReadData( mayThrow,
271  mFileName, mSilentLog, nullptr, 0, 0, data, format, start, len);
272 }

References format.

Referenced by ODDecodeBlockFile::ReadData().

Here is the caller graph for this function:

◆ ReadSummary()

bool SimpleBlockFile::ReadSummary ( ArrayOf< char > &  data)
override

Read the summary section of the disk file.

Read the summary section of the disk file.

Parameters
*dataThe buffer to write the data to. It must be at least mSummaryinfo.totalSummaryBytes long.

Definition at line 226 of file SimpleBlockFile.cpp.

227 {
228  data.reinit( mSummaryInfo.totalSummaryBytes );
229  //wxLogDebug("SimpleBlockFile::ReadSummary(): Reading summary from disk.");
230 
231  wxFFile file(mFileName.GetFullPath(), wxT("rb"));
232 
233  {
234  Optional<wxLogNull> silence{};
235  if (mSilentLog)
236  silence.emplace();
237  // FIXME: TRAP_ERR no report to user of absent summary files?
238  // filled with zero instead.
239  if (!file.IsOpened()){
240  memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
241  mSilentLog = TRUE;
242  return false;
243  }
244  }
245  mSilentLog = FALSE;
246 
247  // The offset is just past the au header
248  if( !file.Seek(sizeof(auHeader)) ||
249  file.Read(data.get(), mSummaryInfo.totalSummaryBytes) !=
250  mSummaryInfo.totalSummaryBytes ) {
251  memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
252  return false;
253  }
254 
255  FixSummary(data.get());
256 
257  return true;
258 }

References Optional< X >::emplace(), and ArrayOf< X >::reinit().

Referenced by ODDecodeBlockFile::ReadSummary().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Recover()

void SimpleBlockFile::Recover ( void  )
override

Definition at line 398 of file SimpleBlockFile.cpp.

398  {
399  wxFFile file(mFileName.GetFullPath(), wxT("wb"));
400 
401  if( !file.IsOpened() ){
402  // Can't do anything else.
403  return;
404  }
405 
406  auHeader header;
407  header.magic = 0x2e736e64;
408  header.dataOffset = sizeof(auHeader) + mSummaryInfo.totalSummaryBytes;
409 
410  // dataSize is optional, and we opt out
411  header.dataSize = 0xffffffff;
412  header.encoding = AU_SAMPLE_FORMAT_16;
413  header.sampleRate = 44100;
414  header.channels = 1;
415  file.Write(&header, sizeof(header));
416 
417  for(decltype(mSummaryInfo.totalSummaryBytes) i = 0;
418  i < mSummaryInfo.totalSummaryBytes; i++)
419  file.Write(wxT("\0"),1);
420 
421  for(decltype(mLen) i = 0; i < mLen * 2; i++)
422  file.Write(wxT("\0"),1);
423 
424 }

References AU_SAMPLE_FORMAT_16, auHeader::channels, auHeader::dataOffset, auHeader::dataSize, auHeader::encoding, auHeader::magic, and auHeader::sampleRate.

◆ SaveXML()

void SimpleBlockFile::SaveXML ( XMLWriter xmlFile)
override

Write an XML representation of this file.

Definition at line 274 of file SimpleBlockFile.cpp.

276 {
277  xmlFile.StartTag(wxT("simpleblockfile"));
278 
279  xmlFile.WriteAttr(wxT("filename"), mFileName.GetFullName());
280  xmlFile.WriteAttr(wxT("len"), mLen);
281  xmlFile.WriteAttr(wxT("min"), mMin);
282  xmlFile.WriteAttr(wxT("max"), mMax);
283  xmlFile.WriteAttr(wxT("rms"), mRMS);
284 
285  xmlFile.EndTag(wxT("simpleblockfile"));
286 }

References XMLWriter::EndTag(), XMLWriter::StartTag(), and XMLWriter::WriteAttr().

Referenced by ODDecodeBlockFile::SaveXML().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ WriteSimpleBlockFile()

bool SimpleBlockFile::WriteSimpleBlockFile ( samplePtr  sampleData,
size_t  sampleLen,
sampleFormat  format,
void *  summaryData 
)
protected

Definition at line 113 of file SimpleBlockFile.cpp.

118 {
119  wxFFile file(mFileName.GetFullPath(), wxT("wb"));
120  if( !file.IsOpened() ){
121  // Can't do anything else.
122  return false;
123  }
124 
125  auHeader header;
126 
127  // AU files can be either big or little endian. Which it is is
128  // determined implicitly by the byte-order of the magic 0x2e736e64
129  // (.snd). We want it to be native-endian, so we write the magic
130  // to memory and then let it write that to a file in native
131  // endianness
132  header.magic = 0x2e736e64;
133 
134  // We store the summary data at the end of the header, so the data
135  // offset is the length of the summary data plus the length of the header
136  header.dataOffset = sizeof(auHeader) + mSummaryInfo.totalSummaryBytes;
137 
138  // dataSize is optional, and we opt out
139  header.dataSize = 0xffffffff;
140 
141  switch(format) {
142  case int16Sample:
143  header.encoding = AU_SAMPLE_FORMAT_16;
144  break;
145 
146  case int24Sample:
147  header.encoding = AU_SAMPLE_FORMAT_24;
148  break;
149 
150  case floatSample:
152  break;
153  }
154 
155  // TODO: don't fabricate
156  header.sampleRate = 44100;
157 
158  // BlockFiles are always mono
159  header.channels = 1;
160 
161  // Write the file
162  ArrayOf<char> cleanup;
163  if (!summaryData)
164  summaryData = /*BlockFile::*/CalcSummary(sampleData, sampleLen, format, cleanup);
165  // PRL: cleanup fixes a possible memory leak!
166 
167  size_t nBytesToWrite = sizeof(header);
168  size_t nBytesWritten = file.Write(&header, nBytesToWrite);
169  if (nBytesWritten != nBytesToWrite)
170  {
171  wxLogDebug(wxT("Wrote %lld bytes, expected %lld."), (long long) nBytesWritten, (long long) nBytesToWrite);
172  return false;
173  }
174 
175  nBytesToWrite = mSummaryInfo.totalSummaryBytes;
176  nBytesWritten = file.Write(summaryData, nBytesToWrite);
177  if (nBytesWritten != nBytesToWrite)
178  {
179  wxLogDebug(wxT("Wrote %lld bytes, expected %lld."), (long long) nBytesWritten, (long long) nBytesToWrite);
180  return false;
181  }
182 
183  if( format == int24Sample )
184  {
185  // we can't write the buffer directly to disk, because 24-bit samples
186  // on disk need to be packed, not padded to 32 bits like they are in
187  // memory
188  int *int24sampleData = (int*)sampleData;
189 
190  for( size_t i = 0; i < sampleLen; i++ )
191  {
192  nBytesToWrite = 3;
193  nBytesWritten =
194  #if wxBYTE_ORDER == wxBIG_ENDIAN
195  file.Write((char*)&int24sampleData[i] + 1, nBytesToWrite);
196  #else
197  file.Write((char*)&int24sampleData[i], nBytesToWrite);
198  #endif
199  if (nBytesWritten != nBytesToWrite)
200  {
201  wxLogDebug(wxT("Wrote %lld bytes, expected %lld."), (long long) nBytesWritten, (long long) nBytesToWrite);
202  return false;
203  }
204  }
205  }
206  else
207  {
208  // for all other sample formats we can write straight from the buffer
209  // to disk
210  nBytesToWrite = sampleLen * SAMPLE_SIZE(format);
211  nBytesWritten = file.Write(sampleData, nBytesToWrite);
212  if (nBytesWritten != nBytesToWrite)
213  {
214  wxLogDebug(wxT("Wrote %lld bytes, expected %lld."), (long long) nBytesWritten, (long long) nBytesToWrite);
215  return false;
216  }
217  }
218 
219  return true;
220 }

References AU_SAMPLE_FORMAT_16, AU_SAMPLE_FORMAT_24, AU_SAMPLE_FORMAT_FLOAT, auHeader::channels, auHeader::dataOffset, auHeader::dataSize, auHeader::encoding, floatSample, format, int16Sample, int24Sample, auHeader::magic, SAMPLE_SIZE, and auHeader::sampleRate.

Referenced by ODDecodeBlockFile::WriteODDecodeBlockFile().

Here is the caller graph for this function:

Member Data Documentation

◆ mFormat

sampleFormat SimpleBlockFile::mFormat
mutableprivate

Definition at line 73 of file SimpleBlockFile.h.

Referenced by GetSpaceUsage().


The documentation for this class was generated from the following files:
XMLWriter::EndTag
virtual void EndTag(const wxString &name)
Definition: XMLWriter.cpp:99
Optional::emplace
X & emplace(Args &&... args)
Definition: MemoryX.h:193
AU_SAMPLE_FORMAT_FLOAT
@ AU_SAMPLE_FORMAT_FLOAT
Definition: SimpleBlockFile.h:22
Optional
Like a smart pointer, allows for object to not exist (nullptr)
Definition: MemoryX.h:144
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
SAMPLE_SIZE_DISK
#define SAMPLE_SIZE_DISK(SampleFormat)
Return the size on disk of one uncompressed sample (bytes)
Definition: SampleFormat.h:59
FileException::Cause::Write
@ Write
most important to detect when storage space is exhausted
auHeader::dataOffset
wxUint32 dataOffset
Definition: SimpleBlockFile.h:27
auHeader::dataSize
wxUint32 dataSize
Definition: SimpleBlockFile.h:28
ArrayOf::reinit
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
FileException
Thrown for failure of file or database operations in deeply nested places.
Definition: FileException.h:19
auHeader::channels
wxUint32 channels
Definition: SimpleBlockFile.h:31
SAMPLE_SIZE
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:44
int24Sample
@ int24Sample
Definition: SampleFormat.h:33
SimpleBlockFile::mFormat
sampleFormat mFormat
Definition: SimpleBlockFile.h:73
XMLValueChecker::IsGoodString
static bool IsGoodString(const wxString &str)
Definition: XMLTagHandler.cpp:38
floatSample
@ floatSample
Definition: SampleFormat.h:34
auHeader::sampleRate
wxUint32 sampleRate
Definition: SimpleBlockFile.h:30
int16Sample
@ int16Sample
Definition: SampleFormat.h:32
format
int format
Definition: ExportPCM.cpp:56
SwapUintEndianess
static wxUint32 SwapUintEndianess(wxUint32 in)
Definition: SimpleBlockFile.cpp:55
XMLValueChecker::IsGoodFileString
static bool IsGoodFileString(const FilePath &str)
Definition: XMLTagHandler.cpp:70
sampleFormat
sampleFormat
Definition: SampleFormat.h:29
SimpleBlockFile::WriteSimpleBlockFile
bool WriteSimpleBlockFile(samplePtr sampleData, size_t sampleLen, sampleFormat format, void *summaryData)
Definition: SimpleBlockFile.cpp:113
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
auHeader::magic
wxUint32 magic
Definition: SimpleBlockFile.h:26
XMLWriter::WriteAttr
void WriteAttr(const wxString &name, const Identifier &value)
Definition: XMLWriter.h:34
PLATFORM_MAX_PATH
#define PLATFORM_MAX_PATH
Definition: FileNames.h:22
auHeader
The auHeader is a structure used by SimpleBlockFile for .au file format. There probably is an 'offici...
Definition: SimpleBlockFile.h:25
AU_SAMPLE_FORMAT_24
@ AU_SAMPLE_FORMAT_24
Definition: SimpleBlockFile.h:21
ArrayOf< char >
XMLWriter::StartTag
virtual void StartTag(const wxString &name)
Definition: XMLWriter.cpp:76
Internat::CompatibleToDouble
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
Definition: Internat.cpp:134
AU_SAMPLE_FORMAT_16
@ AU_SAMPLE_FORMAT_16
Definition: SimpleBlockFile.h:20
auHeader::encoding
wxUint32 encoding
Definition: SimpleBlockFile.h:29