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) 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)=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 75 of file ImportPCM.cpp.

Constructor & Destructor Documentation

◆ PCMImportFileHandle()

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

Definition at line 180 of file ImportPCM.cpp.

183 mFile(std::move(file)),
184 mInfo(info)
185{
186 wxASSERT(info.channels >= 0);
187
188 //
189 // Figure out the format to use.
190 //
191 // In general, go with the user's preferences. However, if
192 // the file is higher-quality, go with a format which preserves
193 // the quality of the original file.
194 //
195
196 // Effective format
198 // But maybe different storage format
200}
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:103
const SF_INFO mInfo
Definition: ImportPCM.cpp:101
sampleFormat mEffectiveFormat
Definition: ImportPCM.cpp:102

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

586{
587}

Member Function Documentation

◆ GetFileDescription()

TranslatableString PCMImportFileHandle::GetFileDescription ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 202 of file ImportPCM.cpp.

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

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

References SAMPLE_SIZE.

◆ GetStreamCount()

wxInt32 PCMImportFileHandle::GetStreamCount ( )
inlineoverridevirtual

Implements ImportFileHandle.

Definition at line 88 of file ImportPCM.cpp.

88{ return 1; }

◆ GetStreamInfo()

const TranslatableStrings & PCMImportFileHandle::GetStreamInfo ( )
inlineoverridevirtual

Implements ImportFileHandle.

Definition at line 90 of file ImportPCM.cpp.

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

◆ Import()

void PCMImportFileHandle::Import ( ImportProgressListener progressListener,
WaveTrackFactory trackFactory,
TrackHolders outTracks,
Tags tags 
)
overridevirtual

Implements ImportFileHandle.

Definition at line 280 of file ImportPCM.cpp.

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

References SampleBuffer::Allocate(), ImportFileHandleEx::BeginImport(), ImportProgressListener::Cancelled, ImportProgressListener::Error, ImportUtils::FinalizeImport(), floatSample, ImportUtils::ForEachChannel(), 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 96 of file ImportPCM.cpp.

97 {}

Member Data Documentation

◆ mEffectiveFormat

sampleFormat PCMImportFileHandle::mEffectiveFormat
private

Definition at line 102 of file ImportPCM.cpp.

Referenced by Import(), and PCMImportFileHandle().

◆ mFile

SFFile PCMImportFileHandle::mFile
private

Definition at line 100 of file ImportPCM.cpp.

Referenced by Import().

◆ mFormat

sampleFormat PCMImportFileHandle::mFormat
private

Definition at line 103 of file ImportPCM.cpp.

Referenced by Import(), and PCMImportFileHandle().

◆ mInfo

const SF_INFO PCMImportFileHandle::mInfo
private

Definition at line 101 of file ImportPCM.cpp.

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


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