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}
sampleFormat sf_subtype_to_effective_format(unsigned int format)
Choose the narrowest value in the sampleFormat enumeration for a given libsndfile format.
wxString name
Definition: TagsEditor.cpp:166
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 589 of file ImportPCM.cpp.

590{
591}

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
293 auto trackList = trackFactory->CreateMany(mInfo.channels, format, mInfo.samplerate);
294
295 auto fileTotalFrames =
296 (sampleCount)mInfo.frames; // convert from sf_count_t
297 auto maxBlockSize = (*trackList->Any<WaveTrack>().begin())->GetMaxBlockSize();
298
299 {
300 // Otherwise, we're in the "copy" mode, where we read in the actual
301 // samples from the file and store our own local copy of the
302 // samples in the tracks.
303
304 // PRL: guard against excessive memory buffer allocation in case of many channels
305 using type = decltype(maxBlockSize);
306 if (mInfo.channels < 1)
307 {
309 return;
310 }
311 auto maxBlock = std::min(maxBlockSize,
312 std::numeric_limits<type>::max() /
313 (mInfo.channels * SAMPLE_SIZE(mFormat))
314 );
315 if (maxBlock < 1)
316 {
318 return;
319 }
320
321 SampleBuffer srcbuffer, buffer;
322 wxASSERT(mInfo.channels >= 0);
323 while (NULL == srcbuffer.Allocate(maxBlock * mInfo.channels, mFormat).ptr() ||
324 NULL == buffer.Allocate(maxBlock, mFormat).ptr())
325 {
326 maxBlock /= 2;
327 if (maxBlock < 1)
328 {
330 return;
331 }
332 }
333
334 decltype(fileTotalFrames) framescompleted = 0;
335
336 long block;
337 do {
338 block = maxBlock;
339
340 if (mFormat == int16Sample)
341 block = SFCall<sf_count_t>(sf_readf_short, mFile.get(), (short *)srcbuffer.ptr(), block);
342 //import 24 bit int as float and have the append function convert it. This is how PCMAliasBlockFile worked too.
343 else
344 block = SFCall<sf_count_t>(sf_readf_float, mFile.get(), (float *)srcbuffer.ptr(), block);
345
346 if(block < 0 || block > (long)maxBlock) {
347 wxASSERT(false);
348 block = maxBlock;
349 }
350
351 if (block) {
352 unsigned c = 0;
353 ImportUtils::ForEachChannel(*trackList, [&](auto& channel)
354 {
355 if (mFormat==int16Sample) {
356 for(int j=0; j<block; j++)
357 ((short *)buffer.ptr())[j] =
358 ((short *)srcbuffer.ptr())[mInfo.channels*j+c];
359 }
360 else {
361 for(int j=0; j<block; j++)
362 ((float *)buffer.ptr())[j] =
363 ((float *)srcbuffer.ptr())[mInfo.channels*j+c];
364 }
365
366 channel.AppendBuffer(
367 buffer.ptr(),
369 block, 1, mEffectiveFormat
370 );
371 ++c;
372 });
373 framescompleted += block;
374 }
375 if(fileTotalFrames > 0)
376 progressListener.OnImportProgress(framescompleted.as_double() / fileTotalFrames.as_double());
377 } while (block > 0 && !IsCancelled() && !IsStopped());
378 }
379
380 if(IsCancelled())
381 {
383 return;
384 }
385
386 ImportUtils::FinalizeImport(outTracks, std::move(*trackList));
387
388 const char *str;
389
390 str = sf_get_string(mFile.get(), SF_STR_TITLE);
391 if (str) {
392 tags->SetTag(TAG_TITLE, UTF8CTOWX(str));
393 }
394
395 str = sf_get_string(mFile.get(), SF_STR_ALBUM);
396 if (str) {
397 tags->SetTag(TAG_ALBUM, UTF8CTOWX(str));
398 }
399
400 str = sf_get_string(mFile.get(), SF_STR_ARTIST);
401 if (str) {
403 }
404
405 str = sf_get_string(mFile.get(), SF_STR_COMMENT);
406 if (str) {
408 }
409
410 str = sf_get_string(mFile.get(), SF_STR_DATE);
411 if (str) {
412 tags->SetTag(TAG_YEAR, UTF8CTOWX(str));
413 }
414
415 str = sf_get_string(mFile.get(), SF_STR_COPYRIGHT);
416 if (str) {
418 }
419
420 str = sf_get_string(mFile.get(), SF_STR_SOFTWARE);
421 if (str) {
423 }
424
425 str = sf_get_string(mFile.get(), SF_STR_TRACKNUMBER);
426 if (str) {
427 tags->SetTag(TAG_TRACK, UTF8CTOWX(str));
428 }
429
430 str = sf_get_string(mFile.get(), SF_STR_GENRE);
431 if (str) {
432 tags->SetTag(TAG_GENRE, UTF8CTOWX(str));
433 }
434
435 // To begin with, only trust the Muse Hub, with whom we collaborate and can
436 // ensure they comply. In the future we may extend this list.
437 const std::vector<std::string> trustedDistributors { "Muse Hub" };
438 if (const auto acidTags = LibImportExport::GetAcidizerTags(*mFile, trustedDistributors))
439 outAcidTags.emplace(*acidTags);
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(GetFilename(), 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 progressListener.OnImportResult(IsStopped()
587}
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 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
TrackListHolder CreateMany(size_t nChannels)
Creates tracks with project's default rate and format and the given number of channels.
Definition: WaveTrack.cpp:423
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
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, ImportUtils::ChooseFormat(), WaveTrackFactory::CreateMany(), ImportProgressListener::Error, ImportUtils::FinalizeImport(), floatSample, ImportUtils::ForEachChannel(), anonymous_namespace{ExportPCM.cpp}::format, 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, 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: