33#error Requires libsndfile 1.0 or higher
50 struct id3_frame *id3_frame_new(
char const *);
51 id3_length_t id3_latin1_length(id3_latin1_t
const *);
52 void id3_latin1_decode(id3_latin1_t
const *, id3_ucs4_t *);
56#define DESC XO("WAV, AIFF, and other uncompressed types")
70 std::unique_ptr<ImportFileHandle>
Open(
118 memset(&info, 0,
sizeof(info));
122 if (filename.Lower().EndsWith(
wxT(
"mp3"))) {
138 if (f.Open(filename)) {
142 file.reset(SFCall<SNDFILE*>(sf_open_fd, f.fd(), SFM_READ, &info, TRUE));
157 (info.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_OGG) {
173 return std::make_unique<PCMImportFileHandle>(filename, std::move(file), info);
177 std::make_unique< PCMImportPlugin >()
181 SFFile &&file, SF_INFO info)
183 mFile(
std::move(file)),
186 wxASSERT(info.channels >= 0);
208using Unevaluated =
decltype(
210 XO(
"AIFF (Apple/SGI)")
211 ,
XO(
"AU (Sun/NeXT)")
212 ,
XO(
"AVR (Audio Visual Research)")
213 ,
XO(
"CAF (Apple Core Audio File)")
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)")
238using Unevaluated2 =
decltype(
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")
250 ,
XO(
"Microsoft ADPCM")
252 ,
XO(
"32kbs G721 ADPCM")
253 ,
XO(
"24kbs G723 ADPCM")
270 return mInfo.frames * mInfo.channels *
SAMPLE_SIZE(mFormat);
274struct id3_tag_deleter {
275 void operator () (id3_tag *p)
const {
if (p) id3_tag_delete(p); }
277using id3_tag_holder = std::unique_ptr<id3_tag, id3_tag_deleter>;
289 wxASSERT(
mFile.get());
297 auto fileTotalFrames =
308 if (
mInfo.channels < 1)
314 std::numeric_limits<type>::max() /
324 wxASSERT(
mInfo.channels >= 0);
336 decltype(fileTotalFrames) framescompleted = 0;
343 block = SFCall<sf_count_t>(sf_readf_short,
mFile.get(), (
short *)srcbuffer.
ptr(), block);
346 block = SFCall<sf_count_t>(sf_readf_float,
mFile.get(), (
float *)srcbuffer.
ptr(), block);
348 if(block < 0 || block > (
long)maxBlock) {
358 for(
int j=0; j<block; j++)
359 ((
short *)buffer.
ptr())[j] =
360 ((
short *)srcbuffer.
ptr())[
mInfo.channels*j+c];
363 for(
int j=0; j<block; j++)
364 ((
float *)buffer.
ptr())[j] =
365 ((
float *)srcbuffer.
ptr())[
mInfo.channels*j+c];
368 channel.AppendBuffer(
375 framescompleted += block;
377 if(fileTotalFrames > 0)
378 progressListener.
OnImportProgress(framescompleted.as_double() / fileTotalFrames.as_double());
392 str = sf_get_string(
mFile.get(), SF_STR_TITLE);
397 str = sf_get_string(
mFile.get(), SF_STR_ALBUM);
402 str = sf_get_string(
mFile.get(), SF_STR_ARTIST);
407 str = sf_get_string(
mFile.get(), SF_STR_COMMENT);
412 str = sf_get_string(
mFile.get(), SF_STR_DATE);
417 str = sf_get_string(
mFile.get(), SF_STR_COPYRIGHT);
422 str = sf_get_string(
mFile.get(), SF_STR_SOFTWARE);
427 str = sf_get_string(
mFile.get(), SF_STR_TRACKNUMBER);
432 str = sf_get_string(
mFile.get(), SF_STR_GENRE);
437#if defined(USE_LIBID3TAG)
438 if (((
mInfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF) ||
439 ((
mInfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV)) {
455 if((
mInfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF)
456 len = wxUINT32_SWAP_ON_LE(len);
458 if (wxStricmp(
id,
"ID3 ") != 0) {
459 f.Seek(len + (len & 0x01), wxFromCurrent);
471 f.Read(buffer.get(), len);
472 tp.reset( id3_tag_parse(buffer.get(), len) );
480 bool have_year =
false;
481 for (
int i = 0; i < (int) tp->nframes; i++) {
482 struct id3_frame *frame = tp->frames[i];
498 if (strcmp(frame->id, ID3_FRAME_TITLE) == 0) {
501 else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0) {
504 else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0) {
507 else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0) {
510 else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0) {
523 else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0) {
526 else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0) {
533 n =
UTF8CTOWX(frame->description).BeforeFirst(
wxT(
'/'));
536 const id3_ucs4_t *ustr = NULL;
539 ustr = id3_field_getfullstring(&frame->fields[3]);
541 else if (frame->nfields == 3) {
542 ustr = id3_field_getstring(&frame->fields[1]);
549 ustr = id3_field_getstring(&frame->fields[2]);
551 else if (frame->nfields >= 2) {
552 ustr = id3_field_getstrings(&frame->fields[1], 0);
561 if (!n.empty() && !v.empty()) {
const TranslatableString name
static Importer::RegisteredImportPlugin registered
The interface that all file import "plugins" (if you want to call them that) must implement....
std::vector< std::shared_ptr< TrackList > > TrackHolders
std::unique_ptr< Character[], freer > MallocString
std::vector< TranslatableString > TranslatableStrings
This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better t...
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
bool IsStopped() const noexcept
FilePath GetFilename() const override
bool IsCancelled() const noexcept
unsigned long long ByteCount
Base class for FlacImportPlugin, LOFImportPlugin, MP3ImportPlugin, OggImportPlugin and PCMImportPlugi...
Interface used to report on import state and progress.
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)
static sampleFormat ChooseFormat(sampleFormat effectiveFormat)
Choose appropriate format, which will not be narrower than the specified one.
static void ForEachChannel(TrackList &trackList, const std::function< void(WaveChannel &)> &op)
Iterates over channels in each wave track from the list.
static void FinalizeImport(TrackHolders &outTracks, const std::vector< TrackListHolder > &importedStreams)
Flushes the given channels and moves them to outTracks.
An ImportFileHandle for PCM data.
const TranslatableStrings & GetStreamInfo() override
void SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override
wxInt32 GetStreamCount() override
TranslatableString GetFileDescription() override
void Import(ImportProgressListener &progressListener, WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags) override
ByteCount GetFileUncompressedBytes() override
PCMImportFileHandle(const FilePath &name, SFFile &&file, SF_INFO info)
sampleFormat mEffectiveFormat
An ImportPlugin for PCM data.
wxString GetPluginStringID() override
TranslatableString GetPluginFormatDescription() override
std::unique_ptr< ImportFileHandle > Open(const FilePath &Filename, AudacityProject *) override
SampleBuffer & Allocate(size_t count, sampleFormat format)
Holds a msgid for the translation catalog; may also bind format arguments.
Used to create or clone a WaveTrack, with appropriate context from the project that will own the trac...
A Track that contains audio waveform data.
Positions or offsets within audio files need a wide type.
constexpr auto maxBlockSize