Audacity 3.2.0
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
 
void Import (ImportProgressListener &progressListener, WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags, std::optional< LibFileFormats::AcidizerTags > &outAcidTags) override
 
wxInt32 GetStreamCount () override
 
const TranslatableStringsGetStreamInfo () override
 
void SetStreamUsage (wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override
 
- Public Member Functions inherited from ImportFileHandleEx
 ImportFileHandleEx (const FilePath &filename)
 
FilePath GetFilename () const override
 
void Cancel () override
 
void Stop () override
 
- Public Member Functions inherited from ImportFileHandle
virtual ~ImportFileHandle ()
 
virtual FilePath GetFilename () const =0
 
virtual TranslatableString GetErrorMessage () const
 
virtual TranslatableString GetFileDescription ()=0
 
virtual ByteCount GetFileUncompressedBytes ()=0
 
virtual wxInt32 GetStreamCount ()=0
 
virtual const TranslatableStringsGetStreamInfo ()=0
 
virtual void SetStreamUsage (wxInt32 StreamID, bool Use)=0
 
virtual void Import (ImportProgressListener &progressListener, WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags, std::optional< LibFileFormats::AcidizerTags > &acidTags)=0
 
virtual void Cancel ()=0
 
virtual void Stop ()=0
 

Private Attributes

SFFile mFile
 
const SF_INFO mInfo
 
sampleFormat mEffectiveFormat
 
sampleFormat mFormat
 

Additional Inherited Members

- Public Types inherited from ImportFileHandle
using ByteCount = unsigned long long
 
- Protected Member Functions inherited from ImportFileHandleEx
void BeginImport ()
 
bool IsCancelled () const noexcept
 
bool IsStopped () const noexcept
 

Detailed Description

An ImportFileHandle for PCM data.

Definition at line 76 of file ImportPCM.cpp.

Constructor & Destructor Documentation

◆ PCMImportFileHandle()

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

Definition at line 181 of file ImportPCM.cpp.

184 mFile(std::move(file)),
185 mInfo(info)
186{
187 wxASSERT(info.channels >= 0);
188
189 //
190 // Figure out the format to use.
191 //
192 // In general, go with the user's preferences. However, if
193 // the file is higher-quality, go with a format which preserves
194 // the quality of the original file.
195 //
196
197 // Effective format
199 // But maybe different storage format
201}
const TranslatableString name
Definition: Distortion.cpp:76
sampleFormat sf_subtype_to_effective_format(unsigned int format)
Choose the narrowest value in the sampleFormat enumeration for a given libsndfile format.
ImportFileHandleEx(const FilePath &filename)
static sampleFormat ChooseFormat(sampleFormat effectiveFormat)
Choose appropriate format, which will not be narrower than the specified one.
Definition: ImportUtils.cpp:19
sampleFormat mFormat
Definition: ImportPCM.cpp:104
const SF_INFO mInfo
Definition: ImportPCM.cpp:102
sampleFormat mEffectiveFormat
Definition: ImportPCM.cpp:103

References ImportUtils::ChooseFormat(), mEffectiveFormat, mFormat, mInfo, and sf_subtype_to_effective_format().

Here is the call graph for this function:

◆ ~PCMImportFileHandle()

PCMImportFileHandle::~PCMImportFileHandle ( )

Definition at line 592 of file ImportPCM.cpp.

593{
594}

Member Function Documentation

◆ GetFileDescription()

TranslatableString PCMImportFileHandle::GetFileDescription ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 203 of file ImportPCM.cpp.

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

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 269 of file ImportPCM.cpp.

270{
271 return mInfo.frames * mInfo.channels * SAMPLE_SIZE(mFormat);
272}
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:52

References SAMPLE_SIZE.

◆ GetStreamCount()

wxInt32 PCMImportFileHandle::GetStreamCount ( )
inlineoverridevirtual

Implements ImportFileHandle.

Definition at line 89 of file ImportPCM.cpp.

89{ return 1; }

◆ GetStreamInfo()

const TranslatableStrings & PCMImportFileHandle::GetStreamInfo ( )
inlineoverridevirtual

Implements ImportFileHandle.

Definition at line 91 of file ImportPCM.cpp.

92 {
93 static TranslatableStrings empty;
94 return empty;
95 }
std::vector< TranslatableString > TranslatableStrings

◆ Import()

void PCMImportFileHandle::Import ( ImportProgressListener progressListener,
WaveTrackFactory trackFactory,
TrackHolders outTracks,
Tags tags,
std::optional< LibFileFormats::AcidizerTags > &  outAcidTags 
)
overridevirtual

Implements ImportFileHandle.

Definition at line 281 of file ImportPCM.cpp.

285{
286 BeginImport();
287
288 outTracks.clear();
289
290 wxASSERT(mFile.get());
291
292 auto track = ImportUtils::NewWaveTrack(
293 *trackFactory,
294 mInfo.channels,
295 mFormat,
296 mInfo.samplerate);
297
298 auto fileTotalFrames =
299 (sampleCount)mInfo.frames; // convert from sf_count_t
300 auto maxBlockSize = track->GetMaxBlockSize();
301
302 {
303 // Otherwise, we're in the "copy" mode, where we read in the actual
304 // samples from the file and store our own local copy of the
305 // samples in the tracks.
306
307 // PRL: guard against excessive memory buffer allocation in case of many channels
308 using type = decltype(maxBlockSize);
309 if (mInfo.channels < 1)
310 {
312 return;
313 }
314 auto maxBlock = std::min(maxBlockSize,
315 std::numeric_limits<type>::max() /
316 (mInfo.channels * SAMPLE_SIZE(mFormat))
317 );
318 if (maxBlock < 1)
319 {
321 return;
322 }
323
324 SampleBuffer srcbuffer, buffer;
325 wxASSERT(mInfo.channels >= 0);
326 while (NULL == srcbuffer.Allocate(maxBlock * mInfo.channels, mFormat).ptr() ||
327 NULL == buffer.Allocate(maxBlock, mFormat).ptr())
328 {
329 maxBlock /= 2;
330 if (maxBlock < 1)
331 {
333 return;
334 }
335 }
336
337 decltype(fileTotalFrames) framescompleted = 0;
338
339 long block;
340 do {
341 block = maxBlock;
342
343 if (mFormat == int16Sample)
344 block = SFCall<sf_count_t>(sf_readf_short, mFile.get(), (short *)srcbuffer.ptr(), block);
345 //import 24 bit int as float and have the append function convert it. This is how PCMAliasBlockFile worked too.
346 else
347 block = SFCall<sf_count_t>(sf_readf_float, mFile.get(), (float *)srcbuffer.ptr(), block);
348
349 if(block < 0 || block > (long)maxBlock) {
350 wxASSERT(false);
351 block = maxBlock;
352 }
353
354 if (block) {
355 unsigned c = 0;
356 ImportUtils::ForEachChannel(*track, [&](auto& channel)
357 {
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 channel.AppendBuffer(
370 buffer.ptr(),
372 block, 1, mEffectiveFormat
373 );
374 ++c;
375 });
376 framescompleted += block;
377 }
378 if(fileTotalFrames > 0)
379 progressListener.OnImportProgress(framescompleted.as_double() / fileTotalFrames.as_double());
380 } while (block > 0 && !IsCancelled() && !IsStopped());
381 }
382
383 if(IsCancelled())
384 {
386 return;
387 }
388
389 ImportUtils::FinalizeImport(outTracks, *track);
390
391 const char *str;
392
393 str = sf_get_string(mFile.get(), SF_STR_TITLE);
394 if (str) {
395 tags->SetTag(TAG_TITLE, UTF8CTOWX(str));
396 }
397
398 str = sf_get_string(mFile.get(), SF_STR_ALBUM);
399 if (str) {
400 tags->SetTag(TAG_ALBUM, UTF8CTOWX(str));
401 }
402
403 str = sf_get_string(mFile.get(), SF_STR_ARTIST);
404 if (str) {
406 }
407
408 str = sf_get_string(mFile.get(), SF_STR_COMMENT);
409 if (str) {
411 }
412
413 str = sf_get_string(mFile.get(), SF_STR_DATE);
414 if (str) {
415 tags->SetTag(TAG_YEAR, UTF8CTOWX(str));
416 }
417
418 str = sf_get_string(mFile.get(), SF_STR_COPYRIGHT);
419 if (str) {
421 }
422
423 str = sf_get_string(mFile.get(), SF_STR_SOFTWARE);
424 if (str) {
426 }
427
428 str = sf_get_string(mFile.get(), SF_STR_TRACKNUMBER);
429 if (str) {
430 tags->SetTag(TAG_TRACK, UTF8CTOWX(str));
431 }
432
433 str = sf_get_string(mFile.get(), SF_STR_GENRE);
434 if (str) {
435 tags->SetTag(TAG_GENRE, UTF8CTOWX(str));
436 }
437
438 // To begin with, only trust the Muse Hub, with whom we collaborate and can
439 // ensure they comply. In the future we may extend this list.
440 const std::vector<std::string> trustedDistributors { "Muse Hub" };
441 if (const auto acidTags = LibImportExport::GetAcidizerTags(*mFile, trustedDistributors))
442 outAcidTags.emplace(*acidTags);
443
444#if defined(USE_LIBID3TAG)
445 if (((mInfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF) ||
446 ((mInfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV)) {
447 wxFFile f(GetFilename(), wxT("rb"));
448 if (f.IsOpened()) {
449 char id[5];
450 wxUint32 len;
451
452 id[4] = '\0';
453
454 f.Seek(12); // Skip filetype, length, and formtype
455
456 while (!f.Error()) {
457 f.Read(id, 4); // Get chunk type
458 if (f.Eof()) {
459 break;
460 }
461 f.Read(&len, 4);
462 if((mInfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF)
463 len = wxUINT32_SWAP_ON_LE(len);
464
465 if (wxStricmp(id, "ID3 ") != 0) { // must be case insensitive
466 f.Seek(len + (len & 0x01), wxFromCurrent);
467 continue;
468 }
469
470
471 id3_tag_holder tp;
472 {
473 ArrayOf<id3_byte_t> buffer{ len };
474 if (!buffer) {
475 break;
476 }
477
478 f.Read(buffer.get(), len);
479 tp.reset( id3_tag_parse(buffer.get(), len) );
480 }
481
482 if (!tp) {
483 break;
484 }
485
486 // Loop through all frames
487 bool have_year = false;
488 for (int i = 0; i < (int) tp->nframes; i++) {
489 struct id3_frame *frame = tp->frames[i];
490
491 // wxPrintf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id);
492 // wxPrintf("Desc: %s\n", frame->description);
493 // wxPrintf("Num fields: %d\n", frame->nfields);
494
495 // for (int j = 0; j < (int) frame->nfields; j++) {
496 // wxPrintf("field %d type %d\n", j, frame->fields[j].type );
497 // if (frame->fields[j].type == ID3_FIELD_TYPE_STRINGLIST) {
498 // wxPrintf("num strings %d\n", frame->fields[j].stringlist.nstrings);
499 // }
500 // }
501
502 wxString n, v;
503
504 // Determine the tag name
505 if (strcmp(frame->id, ID3_FRAME_TITLE) == 0) {
506 n = TAG_TITLE;
507 }
508 else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0) {
509 n = TAG_ARTIST;
510 }
511 else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0) {
512 n = TAG_ALBUM;
513 }
514 else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0) {
515 n = TAG_TRACK;
516 }
517 else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0) {
518 // LLL: When libid3tag encounters the "TYER" tag, it converts it to a
519 // "ZOBS" (obsolete) tag and adds a "TDRC" tag at the end of the
520 // list of tags using the first 4 characters of the "TYER" tag.
521 // Since we write both the "TDRC" and "TYER" tags, the "TDRC" tag
522 // will always be encountered first in the list. We want use it
523 // since the converted "TYER" tag may have been truncated.
524 if (have_year) {
525 continue;
526 }
527 n = TAG_YEAR;
528 have_year = true;
529 }
530 else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0) {
531 n = TAG_COMMENTS;
532 }
533 else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0) {
534 n = TAG_GENRE;
535 }
536 else {
537 // Use frame description as default tag name. The descriptions
538 // may include several "meanings" separated by "/" characters, so
539 // we just use the first meaning
540 n = UTF8CTOWX(frame->description).BeforeFirst(wxT('/'));
541 }
542
543 const id3_ucs4_t *ustr = NULL;
544
545 if (n == TAG_COMMENTS) {
546 ustr = id3_field_getfullstring(&frame->fields[3]);
547 }
548 else if (frame->nfields == 3) {
549 ustr = id3_field_getstring(&frame->fields[1]);
550 if (ustr) {
551 // Is this duplication really needed?
552 MallocString<> convStr{ (char *)id3_ucs4_utf8duplicate(ustr) };
553 n = UTF8CTOWX(convStr.get());
554 }
555
556 ustr = id3_field_getstring(&frame->fields[2]);
557 }
558 else if (frame->nfields >= 2) {
559 ustr = id3_field_getstrings(&frame->fields[1], 0);
560 }
561
562 if (ustr) {
563 // Is this duplication really needed?
564 MallocString<> convStr{ (char *)id3_ucs4_utf8duplicate(ustr) };
565 v = UTF8CTOWX(convStr.get());
566 }
567
568 if (!n.empty() && !v.empty()) {
569 tags->SetTag(n, v);
570 }
571 }
572
573 // Convert v1 genre to name
574 if (tags->HasTag(TAG_GENRE)) {
575 long g = -1;
576 if (tags->GetTag(TAG_GENRE).ToLong(&g)) {
577 tags->SetTag(TAG_GENRE, tags->GetGenre(g));
578 }
579 }
580
581 break;
582 }
583 }
584 }
585#endif
586
587 progressListener.OnImportResult(IsStopped()
590}
wxT("CloseDown"))
int min(int a, int b)
#define str(a)
#define UTF8CTOWX(X)
Definition: Internat.h:157
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:148
#define TAG_TRACK
Definition: Tags.h:61
#define TAG_COMMENTS
Definition: Tags.h:64
#define TAG_GENRE
Definition: Tags.h:63
#define TAG_SOFTWARE
Definition: Tags.h:65
#define TAG_COPYRIGHT
Definition: Tags.h:66
#define TAG_ALBUM
Definition: Tags.h:60
#define TAG_YEAR
Definition: Tags.h:62
#define TAG_TITLE
Definition: Tags.h:58
#define TAG_ARTIST
Definition: Tags.h:59
This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better t...
Definition: MemoryX.h:29
bool IsStopped() const noexcept
FilePath GetFilename() const override
bool IsCancelled() const noexcept
virtual void OnImportResult(ImportResult result)=0
Used to report on import result for file handle passed as argument to OnImportFileOpened.
virtual void OnImportProgress(double progress)=0
static std::shared_ptr< WaveTrack > NewWaveTrack(WaveTrackFactory &trackFactory, unsigned nChannels, sampleFormat effectiveFormat, double rate)
Definition: ImportUtils.cpp:35
static void ForEachChannel(TrackList &trackList, const std::function< void(WaveChannel &)> &op)
Iterates over channels in each wave track from the list.
Definition: ImportUtils.cpp:73
static void FinalizeImport(TrackHolders &outTracks, const std::vector< std::shared_ptr< WaveTrack > > &importedStreams)
Flushes the given channels and moves them to outTracks.
Definition: ImportUtils.cpp:49
SampleBuffer & Allocate(size_t count, sampleFormat format)
Definition: SampleFormat.h:151
samplePtr ptr() const
Definition: SampleFormat.h:165
bool HasTag(const wxString &name) const
Definition: Tags.cpp:397
wxString GetGenre(int value)
Definition: Tags.cpp:373
void SetTag(const wxString &name, const wxString &value, const bool bSpecialTag=false)
Definition: Tags.cpp:431
wxString GetTag(const wxString &name) const
Definition: Tags.cpp:406
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
std::optional< LibFileFormats::AcidizerTags > GetAcidizerTags(SNDFILE &file, const std::vector< std::string > &trustedDistributors)
Get the Acidizer tags from a file if from a trusted distributor.

References SampleBuffer::Allocate(), ImportFileHandleEx::BeginImport(), ImportProgressListener::Cancelled, ImportProgressListener::Error, ImportUtils::FinalizeImport(), floatSample, ImportUtils::ForEachChannel(), LibImportExport::GetAcidizerTags(), ImportFileHandleEx::GetFilename(), Tags::GetGenre(), Tags::GetTag(), Tags::HasTag(), int16Sample, ImportFileHandleEx::IsCancelled(), ImportFileHandleEx::IsStopped(), anonymous_namespace{StaffPadTimeAndPitch.cpp}::maxBlockSize, mEffectiveFormat, mFile, mFormat, min(), mInfo, ImportUtils::NewWaveTrack(), ImportProgressListener::OnImportProgress(), ImportProgressListener::OnImportResult(), SampleBuffer::ptr(), SAMPLE_SIZE, Tags::SetTag(), ImportProgressListener::Stopped, str, ImportProgressListener::Success, TAG_ALBUM, TAG_ARTIST, TAG_COMMENTS, TAG_COPYRIGHT, TAG_GENRE, TAG_SOFTWARE, TAG_TITLE, TAG_TRACK, TAG_YEAR, UTF8CTOWX, and wxT().

Here is the call graph for this function:

◆ SetStreamUsage()

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

Definition at line 97 of file ImportPCM.cpp.

98 {}

Member Data Documentation

◆ mEffectiveFormat

sampleFormat PCMImportFileHandle::mEffectiveFormat
private

Definition at line 103 of file ImportPCM.cpp.

Referenced by Import(), and PCMImportFileHandle().

◆ mFile

SFFile PCMImportFileHandle::mFile
private

Definition at line 101 of file ImportPCM.cpp.

Referenced by Import().

◆ mFormat

sampleFormat PCMImportFileHandle::mFormat
private

Definition at line 104 of file ImportPCM.cpp.

Referenced by Import(), and PCMImportFileHandle().

◆ mInfo

const SF_INFO PCMImportFileHandle::mInfo
private

Definition at line 102 of file ImportPCM.cpp.

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


The documentation for this class was generated from the following file: