Audacity  3.0.3
Public Member Functions | Private Attributes | List of all members
PCMImportFileHandle Class Referencefinal

An ImportFileHandle for PCM data. More...

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

Public Member Functions

 PCMImportFileHandle (const FilePath &name, SFFile &&file, SF_INFO info)
 
 ~PCMImportFileHandle ()
 
TranslatableString GetFileDescription () override
 
ByteCount GetFileUncompressedBytes () override
 
ProgressResult Import (WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags) override
 
wxInt32 GetStreamCount () override
 
const TranslatableStringsGetStreamInfo () override
 
void SetStreamUsage (wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override
 
- Public Member Functions inherited from ImportFileHandle
 ImportFileHandle (const FilePath &filename)
 
virtual ~ImportFileHandle ()
 
void CreateProgress ()
 
virtual void SetStreamUsage (wxInt32 StreamID, bool Use)=0
 

Private Attributes

SFFile mFile
 
const SF_INFO mInfo
 
sampleFormat mFormat
 

Additional Inherited Members

- Public Types inherited from ImportFileHandle
using ProgressResult = BasicUI::ProgressResult
 
using ByteCount = unsigned long long
 
- Static Public Member Functions inherited from ImportFileHandle
static sampleFormat ChooseFormat (sampleFormat effectiveFormat)
 Choose appropriate format, which will not be narrower than the specified one. More...
 
- Protected Member Functions inherited from ImportFileHandle
std::shared_ptr< WaveTrackNewWaveTrack (WaveTrackFactory &trackFactory, sampleFormat effectiveFormat, double rate)
 Build a wave track with appropriate format, which will not be narrower than the specified one. More...
 
- Protected Attributes inherited from ImportFileHandle
FilePath mFilename
 
std::unique_ptr< ProgressDialogmProgress
 

Detailed Description

An ImportFileHandle for PCM data.

Definition at line 86 of file ImportPCM.cpp.

Constructor & Destructor Documentation

◆ PCMImportFileHandle()

PCMImportFileHandle::PCMImportFileHandle ( const FilePath name,
SFFile &&  file,
SF_INFO  info 
)

Definition at line 188 of file ImportPCM.cpp.

191  mFile(std::move(file)),
192  mInfo(info)
193 {
194  wxASSERT(info.channels >= 0);
195 
196  //
197  // Figure out the format to use.
198  //
199  // In general, go with the user's preferences. However, if
200  // the file is higher-quality, go with a format which preserves
201  // the quality of the original file.
202  //
203 
204  mFormat =
206 }

References ImportFileHandle::ChooseFormat(), mFormat, mInfo, and sf_subtype_to_effective_format().

Here is the call graph for this function:

◆ ~PCMImportFileHandle()

PCMImportFileHandle::~PCMImportFileHandle ( )

Definition at line 587 of file ImportPCM.cpp.

588 {
589 }

Member Function Documentation

◆ GetFileDescription()

TranslatableString PCMImportFileHandle::GetFileDescription ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 208 of file ImportPCM.cpp.

209 {
210  // Library strings
211  // See the major_formats and subtype_formats tables in command.c in
212  // libsndfile for this list of possibilities
213 
214 using Unevaluated = decltype(
215  /* major_formats */
216  XO("AIFF (Apple/SGI)")
217  , XO("AU (Sun/NeXT)")
218  , XO("AVR (Audio Visual Research)")
219  , XO("CAF (Apple Core Audio File)")
220  /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
221  , XO("FLAC (FLAC Lossless Audio Codec)")
222  , XO("HTK (HMM Tool Kit)")
223  , XO("IFF (Amiga IFF/SVX8/SV16)")
224  , XO("MAT4 (GNU Octave 2.0 / Matlab 4.2)")
225  , XO("MAT5 (GNU Octave 2.1 / Matlab 5.0)")
226  , XO("MPC (Akai MPC 2k)")
227  , XO("OGG (OGG Container format)")
228  , XO("PAF (Ensoniq PARIS)")
229  , XO("PVF (Portable Voice Format)")
230  , XO("RAW (header-less)")
231  , XO("RF64 (RIFF 64)")
232  , XO("SD2 (Sound Designer II)")
233  , XO("SDS (Midi Sample Dump Standard)")
234  , XO("SF (Berkeley/IRCAM/CARL)")
235  , XO("VOC (Creative Labs)")
236  , XO("W64 (SoundFoundry WAVE 64)")
237  , XO("WAV (Microsoft)")
238  , XO("WAV (NIST Sphere)")
239  , XO("WAVEX (Microsoft)")
240  , XO("WVE (Psion Series 3)")
241  , XO("XI (FastTracker 2)")
242 );
243 
244 using Unevaluated2 = decltype(
245  /* subtype_formats */
246  XO("Signed 8 bit PCM")
247  , XO("Signed 16 bit PCM")
248  , XO("Signed 24 bit PCM")
249  , XO("Signed 32 bit PCM")
250  , XO("Unsigned 8 bit PCM")
251  , XO("32 bit float")
252  , XO("64 bit float")
253  , XO("U-Law")
254  , XO("A-Law")
255  , XO("IMA ADPCM")
256  , XO("Microsoft ADPCM")
257  , XO("GSM 6.10")
258  , XO("32kbs G721 ADPCM")
259  , XO("24kbs G723 ADPCM")
260  , XO("12 bit DWVW")
261  , XO("16 bit DWVW")
262  , XO("24 bit DWVW")
263  , XO("VOX ADPCM")
264  , XO("16 bit DPCM")
265  , XO("8 bit DPCM")
266  , XO("Vorbis")
267 );
268 
269  auto untranslated = SFCall<wxString>(sf_header_name, mInfo.format);
270  return TranslatableString{
271  untranslated, {} };
272 }

References mInfo, sf_header_name(), and XO.

Here is the call graph for this function:

◆ GetFileUncompressedBytes()

auto PCMImportFileHandle::GetFileUncompressedBytes ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 274 of file ImportPCM.cpp.

275 {
276  return mInfo.frames * mInfo.channels * SAMPLE_SIZE(mFormat);
277 }

References SAMPLE_SIZE.

◆ GetStreamCount()

wxInt32 PCMImportFileHandle::GetStreamCount ( )
inlineoverridevirtual

Implements ImportFileHandle.

Definition at line 97 of file ImportPCM.cpp.

97 { return 1; }

◆ GetStreamInfo()

const TranslatableStrings& PCMImportFileHandle::GetStreamInfo ( )
inlineoverridevirtual

Implements ImportFileHandle.

Definition at line 99 of file ImportPCM.cpp.

100  {
101  static TranslatableStrings empty;
102  return empty;
103  }

◆ Import()

ProgressResult PCMImportFileHandle::Import ( WaveTrackFactory trackFactory,
TrackHolders outTracks,
Tags tags 
)
overridevirtual

Implements ImportFileHandle.

Definition at line 288 of file ImportPCM.cpp.

291 {
292  outTracks.clear();
293 
294  wxASSERT(mFile.get());
295 
296  CreateProgress();
297 
298  NewChannelGroup channels(mInfo.channels);
299 
300  {
301  // iter not used outside this scope.
302  auto iter = channels.begin();
303  for (int c = 0; c < mInfo.channels; ++iter, ++c)
304  *iter = NewWaveTrack(*trackFactory, mFormat, mInfo.samplerate);
305  }
306 
307  auto fileTotalFrames =
308  (sampleCount)mInfo.frames; // convert from sf_count_t
309  auto maxBlockSize = channels.begin()->get()->GetMaxBlockSize();
310  auto updateResult = ProgressResult::Cancelled;
311 
312  {
313  // Otherwise, we're in the "copy" mode, where we read in the actual
314  // samples from the file and store our own local copy of the
315  // samples in the tracks.
316 
317  // PRL: guard against excessive memory buffer allocation in case of many channels
318  using type = decltype(maxBlockSize);
319  if (mInfo.channels < 1)
320  return ProgressResult::Failed;
321  auto maxBlock = std::min(maxBlockSize,
322  std::numeric_limits<type>::max() /
323  (mInfo.channels * SAMPLE_SIZE(mFormat))
324  );
325  if (maxBlock < 1)
326  return ProgressResult::Failed;
327 
328  SampleBuffer srcbuffer, buffer;
329  wxASSERT(mInfo.channels >= 0);
330  while (NULL == srcbuffer.Allocate(maxBlock * mInfo.channels, mFormat).ptr() ||
331  NULL == buffer.Allocate(maxBlock, mFormat).ptr())
332  {
333  maxBlock /= 2;
334  if (maxBlock < 1)
335  return ProgressResult::Failed;
336  }
337 
338  decltype(fileTotalFrames) framescompleted = 0;
339 
340  long block;
341  do {
342  block = maxBlock;
343 
344  if (mFormat == int16Sample)
345  block = SFCall<sf_count_t>(sf_readf_short, mFile.get(), (short *)srcbuffer.ptr(), block);
346  //import 24 bit int as float and have the append function convert it. This is how PCMAliasBlockFile worked too.
347  else
348  block = SFCall<sf_count_t>(sf_readf_float, mFile.get(), (float *)srcbuffer.ptr(), block);
349 
350  if(block < 0 || block > (long)maxBlock) {
351  wxASSERT(false);
352  block = maxBlock;
353  }
354 
355  if (block) {
356  auto iter = channels.begin();
357  for(int c=0; c<mInfo.channels; ++iter, ++c) {
358  if (mFormat==int16Sample) {
359  for(int j=0; j<block; j++)
360  ((short *)buffer.ptr())[j] =
361  ((short *)srcbuffer.ptr())[mInfo.channels*j+c];
362  }
363  else {
364  for(int j=0; j<block; j++)
365  ((float *)buffer.ptr())[j] =
366  ((float *)srcbuffer.ptr())[mInfo.channels*j+c];
367  }
368 
369  iter->get()->Append(buffer.ptr(), (mFormat == int16Sample)?int16Sample:floatSample, block);
370  }
371  framescompleted += block;
372  }
373 
374  updateResult = mProgress->Update(
375  framescompleted.as_long_long(),
376  fileTotalFrames.as_long_long()
377  );
378  if (updateResult != ProgressResult::Success)
379  break;
380 
381  } while (block > 0);
382  }
383 
384  if (updateResult == ProgressResult::Failed || updateResult == ProgressResult::Cancelled) {
385  return updateResult;
386  }
387 
388  for(const auto &channel : channels)
389  channel->Flush();
390 
391  if (!channels.empty())
392  outTracks.push_back(std::move(channels));
393 
394  const char *str;
395 
396  str = sf_get_string(mFile.get(), SF_STR_TITLE);
397  if (str) {
398  tags->SetTag(TAG_TITLE, UTF8CTOWX(str));
399  }
400 
401  str = sf_get_string(mFile.get(), SF_STR_ALBUM);
402  if (str) {
403  tags->SetTag(TAG_ALBUM, UTF8CTOWX(str));
404  }
405 
406  str = sf_get_string(mFile.get(), SF_STR_ARTIST);
407  if (str) {
408  tags->SetTag(TAG_ARTIST, UTF8CTOWX(str));
409  }
410 
411  str = sf_get_string(mFile.get(), SF_STR_COMMENT);
412  if (str) {
413  tags->SetTag(TAG_COMMENTS, UTF8CTOWX(str));
414  }
415 
416  str = sf_get_string(mFile.get(), SF_STR_DATE);
417  if (str) {
418  tags->SetTag(TAG_YEAR, UTF8CTOWX(str));
419  }
420 
421  str = sf_get_string(mFile.get(), SF_STR_COPYRIGHT);
422  if (str) {
424  }
425 
426  str = sf_get_string(mFile.get(), SF_STR_SOFTWARE);
427  if (str) {
428  tags->SetTag(TAG_SOFTWARE, UTF8CTOWX(str));
429  }
430 
431  str = sf_get_string(mFile.get(), SF_STR_TRACKNUMBER);
432  if (str) {
433  tags->SetTag(TAG_TRACK, UTF8CTOWX(str));
434  }
435 
436  str = sf_get_string(mFile.get(), SF_STR_GENRE);
437  if (str) {
438  tags->SetTag(TAG_GENRE, UTF8CTOWX(str));
439  }
440 
441 #if defined(USE_LIBID3TAG)
442  if (((mInfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF) ||
443  ((mInfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV)) {
444  wxFFile f(mFilename, wxT("rb"));
445  if (f.IsOpened()) {
446  char id[5];
447  wxUint32 len;
448 
449  id[4] = '\0';
450 
451  f.Seek(12); // Skip filetype, length, and formtype
452 
453  while (!f.Error()) {
454  f.Read(id, 4); // Get chunk type
455  if (f.Eof()) {
456  break;
457  }
458  f.Read(&len, 4);
459  if((mInfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF)
460  len = wxUINT32_SWAP_ON_LE(len);
461 
462  if (wxStricmp(id, "ID3 ") != 0) { // must be case insensitive
463  f.Seek(len + (len & 0x01), wxFromCurrent);
464  continue;
465  }
466 
467 
468  id3_tag_holder tp;
469  {
470  ArrayOf<id3_byte_t> buffer{ len };
471  if (!buffer) {
472  break;
473  }
474 
475  f.Read(buffer.get(), len);
476  tp.reset( id3_tag_parse(buffer.get(), len) );
477  }
478 
479  if (!tp) {
480  break;
481  }
482 
483  // Loop through all frames
484  bool have_year = false;
485  for (int i = 0; i < (int) tp->nframes; i++) {
486  struct id3_frame *frame = tp->frames[i];
487 
488  // wxPrintf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id);
489  // wxPrintf("Desc: %s\n", frame->description);
490  // wxPrintf("Num fields: %d\n", frame->nfields);
491 
492  // for (int j = 0; j < (int) frame->nfields; j++) {
493  // wxPrintf("field %d type %d\n", j, frame->fields[j].type );
494  // if (frame->fields[j].type == ID3_FIELD_TYPE_STRINGLIST) {
495  // wxPrintf("num strings %d\n", frame->fields[j].stringlist.nstrings);
496  // }
497  // }
498 
499  wxString n, v;
500 
501  // Determine the tag name
502  if (strcmp(frame->id, ID3_FRAME_TITLE) == 0) {
503  n = TAG_TITLE;
504  }
505  else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0) {
506  n = TAG_ARTIST;
507  }
508  else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0) {
509  n = TAG_ALBUM;
510  }
511  else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0) {
512  n = TAG_TRACK;
513  }
514  else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0) {
515  // LLL: When libid3tag encounters the "TYER" tag, it converts it to a
516  // "ZOBS" (obsolete) tag and adds a "TDRC" tag at the end of the
517  // list of tags using the first 4 characters of the "TYER" tag.
518  // Since we write both the "TDRC" and "TYER" tags, the "TDRC" tag
519  // will always be encountered first in the list. We want use it
520  // since the converted "TYER" tag may have been truncated.
521  if (have_year) {
522  continue;
523  }
524  n = TAG_YEAR;
525  have_year = true;
526  }
527  else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0) {
528  n = TAG_COMMENTS;
529  }
530  else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0) {
531  n = TAG_GENRE;
532  }
533  else {
534  // Use frame description as default tag name. The descriptions
535  // may include several "meanings" separated by "/" characters, so
536  // we just use the first meaning
537  n = UTF8CTOWX(frame->description).BeforeFirst(wxT('/'));
538  }
539 
540  const id3_ucs4_t *ustr = NULL;
541 
542  if (n == TAG_COMMENTS) {
543  ustr = id3_field_getfullstring(&frame->fields[3]);
544  }
545  else if (frame->nfields == 3) {
546  ustr = id3_field_getstring(&frame->fields[1]);
547  if (ustr) {
548  // Is this duplication really needed?
549  MallocString<> convStr{ (char *)id3_ucs4_utf8duplicate(ustr) };
550  n = UTF8CTOWX(convStr.get());
551  }
552 
553  ustr = id3_field_getstring(&frame->fields[2]);
554  }
555  else if (frame->nfields >= 2) {
556  ustr = id3_field_getstrings(&frame->fields[1], 0);
557  }
558 
559  if (ustr) {
560  // Is this duplication really needed?
561  MallocString<> convStr{ (char *)id3_ucs4_utf8duplicate(ustr) };
562  v = UTF8CTOWX(convStr.get());
563  }
564 
565  if (!n.empty() && !v.empty()) {
566  tags->SetTag(n, v);
567  }
568  }
569 
570  // Convert v1 genre to name
571  if (tags->HasTag(TAG_GENRE)) {
572  long g = -1;
573  if (tags->GetTag(TAG_GENRE).ToLong(&g)) {
574  tags->SetTag(TAG_GENRE, tags->GetGenre(g));
575  }
576  }
577 
578  break;
579  }
580  }
581  }
582 #endif
583 
584  return updateResult;
585 }

References SampleBuffer::Allocate(), RefreshCode::Cancelled, ImportFileHandle::CreateProgress(), floatSample, Tags::GetGenre(), Tags::GetTag(), Tags::HasTag(), int16Sample, mFile, ImportFileHandle::mFilename, mFormat, min(), mInfo, ImportFileHandle::mProgress, ImportFileHandle::NewWaveTrack(), SampleBuffer::ptr(), SAMPLE_SIZE, Tags::SetTag(), str, BasicUI::Success, TAG_ALBUM, TAG_ARTIST, TAG_COMMENTS, TAG_COPYRIGHT, TAG_GENRE, TAG_SOFTWARE, TAG_TITLE, TAG_TRACK, TAG_YEAR, and UTF8CTOWX.

Here is the call graph for this function:

◆ SetStreamUsage()

void PCMImportFileHandle::SetStreamUsage ( wxInt32   WXUNUSEDStreamID,
bool   WXUNUSEDUse 
)
inlineoverride

Definition at line 105 of file ImportPCM.cpp.

106  {}

Member Data Documentation

◆ mFile

SFFile PCMImportFileHandle::mFile
private

Definition at line 109 of file ImportPCM.cpp.

Referenced by Import().

◆ mFormat

sampleFormat PCMImportFileHandle::mFormat
private

Definition at line 111 of file ImportPCM.cpp.

Referenced by Import(), and PCMImportFileHandle().

◆ mInfo

const SF_INFO PCMImportFileHandle::mInfo
private

Definition at line 110 of file ImportPCM.cpp.

Referenced by GetFileDescription(), Import(), and PCMImportFileHandle().


The documentation for this class was generated from the following file:
PCMImportFileHandle::mInfo
const SF_INFO mInfo
Definition: ImportPCM.cpp:110
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
SampleBuffer::Allocate
SampleBuffer & Allocate(size_t count, sampleFormat format)
Definition: SampleFormat.h:84
BasicUI::ProgressResult::Success
@ Success
TranslatableStrings
std::vector< TranslatableString > TranslatableStrings
Definition: TranslatableString.h:295
str
#define str(a)
Definition: DBConnection.cpp:30
Tags::HasTag
bool HasTag(const wxString &name) const
Definition: Tags.cpp:452
TAG_TRACK
#define TAG_TRACK
Definition: Tags.h:63
sf_header_name
wxString sf_header_name(int format)
Get the string name of the specified container format.
Definition: FileFormats.cpp:111
SAMPLE_SIZE
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:44
RefreshCode::Cancelled
@ Cancelled
Definition: RefreshCode.h:23
MallocString
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:274
XO
#define XO(s)
Definition: Internat.h:31
PCMImportFileHandle::mFile
SFFile mFile
Definition: ImportPCM.cpp:109
TAG_SOFTWARE
#define TAG_SOFTWARE
Definition: Tags.h:67
Tags::GetTag
wxString GetTag(const wxString &name) const
Definition: Tags.cpp:461
ImportFileHandle::mProgress
std::unique_ptr< ProgressDialog > mProgress
Definition: ImportPlugin.h:159
floatSample
@ floatSample
Definition: SampleFormat.h:34
ImportFileHandle::ImportFileHandle
ImportFileHandle(const FilePath &filename)
Definition: ImportPlugin.cpp:36
Tags::GetGenre
wxString GetGenre(int value)
Definition: Tags.cpp:428
ImportFileHandle::CreateProgress
void CreateProgress()
Definition: ImportPlugin.cpp:45
ImportFileHandle::NewWaveTrack
std::shared_ptr< WaveTrack > NewWaveTrack(WaveTrackFactory &trackFactory, sampleFormat effectiveFormat, double rate)
Build a wave track with appropriate format, which will not be narrower than the specified one.
Definition: ImportPlugin.cpp:69
Tags::SetTag
void SetTag(const wxString &name, const wxString &value, const bool bSpecialTag=false)
Definition: Tags.cpp:486
ImportFileHandle::ChooseFormat
static sampleFormat ChooseFormat(sampleFormat effectiveFormat)
Choose appropriate format, which will not be narrower than the specified one.
Definition: ImportPlugin.cpp:54
int16Sample
@ int16Sample
Definition: SampleFormat.h:32
sf_subtype_to_effective_format
sampleFormat sf_subtype_to_effective_format(unsigned int format)
Choose the narrowest value in the sampleFormat enumeration for a given libsndfile format.
Definition: FileFormats.cpp:229
name
const TranslatableString name
Definition: Distortion.cpp:98
UTF8CTOWX
#define UTF8CTOWX(X)
Definition: Internat.h:159
TAG_GENRE
#define TAG_GENRE
Definition: Tags.h:65
ImportFileHandle::mFilename
FilePath mFilename
Definition: ImportPlugin.h:158
TAG_YEAR
#define TAG_YEAR
Definition: Tags.h:64
TAG_COPYRIGHT
#define TAG_COPYRIGHT
Definition: Tags.h:68
SampleBuffer
Definition: SampleFormat.h:69
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
PCMImportFileHandle::mFormat
sampleFormat mFormat
Definition: ImportPCM.cpp:111
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
TAG_COMMENTS
#define TAG_COMMENTS
Definition: Tags.h:66
TAG_ARTIST
#define TAG_ARTIST
Definition: Tags.h:61
NewChannelGroup
std::vector< std::shared_ptr< WaveTrack > > NewChannelGroup
Definition: Import.cpp:62
ArrayOf
Memory.h template class for making an array of float, bool, etc.
Definition: MemoryX.h:27
TAG_TITLE
#define TAG_TITLE
Definition: Tags.h:60
SampleBuffer::ptr
samplePtr ptr() const
Definition: SampleFormat.h:98
TAG_ALBUM
#define TAG_ALBUM
Definition: Tags.h:62