Audacity  3.0.3
ODDecodeFlacTask.cpp
Go to the documentation of this file.
1 /*
2  * ODDecodeFlacTask.cpp
3  * Audacity
4  *
5  * Created by apple on 8/10/08.
6  * Copyright 2008 __MyCompanyName__. All rights reserved.
7  *
8  */
9 
10 #include "../Audacity.h" // for USE_* macros
11 #include "ODDecodeFlacTask.h"
12 
13 #include "../Prefs.h"
14 #include <wx/string.h>
15 #include <wx/utils.h>
16 #include <wx/file.h>
17 #include <wx/ffile.h>
18 #include <wx/wx.h>
19 
20 #ifdef USE_LIBID3TAG
21 extern "C" {
22 #include <id3tag.h>
23 }
24 #endif
25 
26 #include "../Tags.h"
27 
28 #define FLAC_HEADER "fLaC"
29 
31 {
32 }
33 
34 
35 std::unique_ptr<ODTask> ODDecodeFlacTask::Clone() const
36 {
37  auto clone = std::make_unique<ODDecodeFlacTask>();
38  clone->mDemandSample = GetDemandSample();
39 
40  //the decoders and blockfiles should not be copied. They are created as the task runs.
41  // This std::move is needed to "upcast" the pointer type
42  return std::move(clone);
43 }
44 
45 
46 void ODFLACFile::metadata_callback(const FLAC__StreamMetadata *metadata)
47 {
48  switch (metadata->type)
49  {
50  case FLAC__METADATA_TYPE_VORBIS_COMMENT:
51  for (FLAC__uint32 i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
52  mComments.push_back(UTF8CTOWX((char *)metadata->data.vorbis_comment.comments[i].entry));
53  }
54  break;
55 
56  case FLAC__METADATA_TYPE_STREAMINFO:
57  mDecoder->mSampleRate=metadata->data.stream_info.sample_rate;
58  mDecoder->mNumChannels=metadata->data.stream_info.channels;
59  mDecoder->mBitsPerSample=metadata->data.stream_info.bits_per_sample;
60  mDecoder->mNumSamples=metadata->data.stream_info.total_samples;
61 
62  if (mDecoder->mBitsPerSample<=16) {
65  }
66  } else if (mDecoder->mBitsPerSample<=24) {
69  }
70  } else {
72  }
74  break;
75  // handle the other types we do nothing with to avoid a warning
76  case FLAC__METADATA_TYPE_PADDING: // do nothing with padding
77  case FLAC__METADATA_TYPE_APPLICATION: // no idea what to do with this
78  case FLAC__METADATA_TYPE_SEEKTABLE: // don't need a seektable here
79  case FLAC__METADATA_TYPE_CUESHEET: // convert this to labels?
80  case FLAC__METADATA_TYPE_PICTURE: // ignore pictures
81  case FLAC__METADATA_TYPE_UNDEFINED: // do nothing with this either
82 
83  // FIXME: not declared when compiling on Ubuntu.
84  //case FLAC__MAX_METADATA_TYPE: // quiet compiler warning with this line
85  default:
86  break;
87  }
88 }
89 
90 void ODFLACFile::error_callback(FLAC__StreamDecoderErrorStatus status)
91 {
92  mWasError = true;
93 
94 
95  switch (status)
96  {
97  case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
98  wxPrintf("Flac Error: Lost sync\n");
99  break;
100  case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
101  wxPrintf("Flac Error: Crc mismatch\n");
102  break;
103  case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
104  wxPrintf("Flac Error: Bad Header\n");
105  break;
106  default:
107  wxPrintf("Flac Error: Unknown error code\n");
108  break;
109  }
110 }
111 
112 
113 //the inside of the read loop.
114 FLAC__StreamDecoderWriteStatus ODFLACFile::write_callback(const FLAC__Frame *frame,
115  const FLAC__int32 * const buffer[])
116 {
117 
118  unsigned int bytesToCopy = frame->header.blocksize;
121 
122  //the decodeBuffer was allocated to be the same format as the flac buffer, so we can do a straight up memcpy.
124 
125  mDecoder->mDecodeBufferWritePosition+=bytesToCopy;
126 /*
127  ArrayOf<short> tmp{ frame->header.blocksize };
128 
129  for (unsigned int chn=0; chn<mDecoder->mNumChannels; chn++) {
130  if (frame->header.bits_per_sample == 16) {
131  for (unsigned int s=0; s<frame->header.blocksize; s++) {
132  tmp[s]=buffer[chn][s];
133  }
134 
135  mDecoder->mChannels[chn]->Append((samplePtr)tmp.get(),
136  int16Sample,
137  frame->header.blocksize);
138  }
139  else {
140  mDecoder->mChannels[chn]->Append((samplePtr)buffer[chn],
141  int24Sample,
142  frame->header.blocksize);
143  }
144  }
145 */
146 
147  mDecoder->mSamplesDone += frame->header.blocksize;
148 
149  return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
150 // return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
151 
152 // mDecoder->mUpdateResult = mDecoder->mProgress->Update((wxULongLong_t) mDecoder->mSamplesDone, mDecoder->mNumSamples != 0 ? (wxULongLong_t)mDecoder->mNumSamples : 1);
153 /*
154  if (mDecoder->mUpdateResult != ProgressResult::Success)
155  {
156  return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
157  }
158 
159  return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
160  */
161 }
162 
163 
164 //--Decoder stuff:
172 int ODFlacDecoder::Decode(SampleBuffer & data, sampleFormat & format, sampleCount start, size_t len, unsigned int channel)
173 {
174 
175  //we need to lock this so the target stays fixed over the seek/write callback.
176  mFlacFileLock.Lock();
177 
178  bool usingCache=mLastDecodeStartSample==start;
179  if(usingCache)
180  {
181  //we've just decoded this, so lets use a cache. (often so for
182  }
183 
184 
186  mDecodeBufferLen = len;
187 
188  data.Allocate(len, mFormat);
189  mDecodeBuffer = data.ptr();
190  format = mFormat;
191 
192  mTargetChannel=channel;
193 
194  // Third party library has its own type alias, check it
195  static_assert(sizeof(sampleCount::type) <=
196  sizeof(FLAC__int64),
197  "Type FLAC__int64 is too narrow to hold a sampleCount");
198  if(!mFile->seek_absolute(static_cast<FLAC__int64>( start.as_long_long() )))
199  {
200  mFlacFileLock.Unlock();
201  return -1;
202  }
203 
205  mFile->process_single();
206 
207  mFlacFileLock.Unlock();
208  if(!usingCache)
209  {
211  }
212  //insert into blockfile and
213  //calculate summary happen in ODDecodeBlockFile::WriteODDecodeBlockFile, where this method is also called.
214  return 1;
215 }
216 
220 
221 //Note:we are not using LEGACY_FLAC defs (see ImportFlac.cpp FlacImportFileHandle::Init()
222 //this code is based on that function.
224 {
225  mFormat = int16Sample;//start with the smallest and move up in the metadata_callback.
226  //we want to use the native flac type for quick conversion.
227  /* QualityPrefs::SampleFormatChoice(); */
228  mFile = std::make_unique<ODFLACFile>(this);
229 
230 
231  if (!mHandle.Open(mFName, wxT("rb"))) {
232  return false;
233  }
234 
235  // Even though there is an init() method that takes a filename, use the one that
236  // takes a file handle because wxWidgets can open a file with a Unicode name and
237  // libflac can't (under Windows).
238  //
239  // Responsibility for closing the file is passed to libflac.
240  // (it happens when mFile->finish() is called)
241  bool result = mFile->init(mHandle.fp())?true:false;
242  mHandle.Detach();
243 
244  if (result != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
245  return false;
246  }
247 
248  //this will call the metadata_callback when it is done
249  mFile->process_until_end_of_metadata();
250  // not necessary to check state, error callback will catch errors, but here's how:
251  if (mFile->get_state() > FLAC__STREAM_DECODER_READ_FRAME) {
252  return false;
253  }
254 
255  if (!mFile->is_valid() || mFile->get_was_error()) {
256  // This probably is not a FLAC file at all
257  return false;
258  }
259 
260  MarkInitialized();
261  return true;
262 
263 }
264 
266 {
267  return mFile.get();
268 }
269 
271  if(mFile)
272  mFile->finish();
273 }
274 
276 //
277 //compare to FLACImportPlugin::Open(wxString filename)
279 {
280  // First check if it really is a FLAC file
281 /*
282  int cnt;
283  wxFile binaryFile;
284  if (!binaryFile.Open(fileName)) {
285  return NULL; // File not found
286  }
287 
288 #ifdef USE_LIBID3TAG
289  // Skip any ID3 tags that might be present
290  id3_byte_t query[ID3_TAG_QUERYSIZE];
291  cnt = binaryFile.Read(query, sizeof(query));
292  cnt = id3_tag_query(query, cnt);
293  binaryFile.Seek(cnt);
294 #endif
295 
296  char buf[5];
297  cnt = binaryFile.Read(buf, 4);
298  binaryFile.Close();
299 
300  if (cnt == wxInvalidOffset || strncmp(buf, FLAC_HEADER, 4) != 0) {
301  // File is not a FLAC file
302  return NULL;
303  }
304 
305  // Open the file for import
306  auto decoder = std::std::make_unique<ODFlacDecoder>(fileName);
307 */
308 /*
309  bool success = decoder->Init();
310  if (!success) {
311  return NULL;
312  }
313 */
314  // Open the file for import
315  auto decoder = std::make_unique<ODFlacDecoder>(fileName);
316 
317  mDecoders.push_back(std::move(decoder));
318  return mDecoders.back().get();
319 
320 }
321 
SampleBuffer::Allocate
SampleBuffer & Allocate(size_t count, sampleFormat format)
Definition: SampleFormat.h:84
ODFlacDecoder::mDecodeBufferWritePosition
unsigned int mDecodeBufferWritePosition
Definition: ODDecodeFlacTask.h:137
ODFlacDecoder::GetFlacFile
ODFLACFile * GetFlacFile()
FLAC specific file (inherited from FLAC::Decoder::File)
Definition: ODDecodeFlacTask.cpp:265
ODFLACFile::write_callback
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__Frame *frame, const FLAC__int32 *const buffer[]) override
Definition: ODDecodeFlacTask.cpp:114
ODFlacDecoder::mFlacFileLock
ODLock mFlacFileLock
Definition: ODDecodeFlacTask.h:125
SAMPLE_SIZE
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:44
ODFLACFile::mWasError
bool mWasError
Definition: ODDecodeFlacTask.h:83
int24Sample
@ int24Sample
Definition: SampleFormat.h:33
ODDecodeFlacTask.h
ODDecodeFlacTask::~ODDecodeFlacTask
virtual ~ODDecodeFlacTask()
Definition: ODDecodeFlacTask.cpp:30
ODFlacDecoder::mFormat
sampleFormat mFormat
Definition: ODDecodeFlacTask.h:123
ODFLACFile
Definition: ODDecodeFlacTask.h:66
ODFlacDecoder::mNumChannels
unsigned long mNumChannels
Definition: ODDecodeFlacTask.h:128
ODFileDecoder::MarkInitialized
void MarkInitialized()
Derived classes should call this after they have parsed the header.
Definition: ODDecodeBlockFile.cpp:558
ODFlacDecoder::mSampleRate
unsigned long mSampleRate
Definition: ODDecodeFlacTask.h:127
floatSample
@ floatSample
Definition: SampleFormat.h:34
ODDecodeTask::mDecoders
std::vector< std::unique_ptr< ODFileDecoder > > mDecoders
Definition: ODDecodeTask.h:92
ODFlacDecoder::mTargetChannel
unsigned int mTargetChannel
Definition: ODDecodeFlacTask.h:136
ODDecodeFlacTask::Clone
std::unique_ptr< ODTask > Clone() const override
Definition: ODDecodeFlacTask.cpp:35
ODFlacDecoder::ReadHeader
bool ReadHeader() override
Definition: ODDecodeFlacTask.cpp:223
sampleCount::as_long_long
long long as_long_long() const
Definition: SampleCount.h:47
int16Sample
@ int16Sample
Definition: SampleFormat.h:32
UTF8CTOWX
#define UTF8CTOWX(X)
Definition: Internat.h:159
format
int format
Definition: ExportPCM.cpp:56
ODFlacDecoder::mStreamInfoDone
bool mStreamInfoDone
Definition: ODDecodeFlacTask.h:133
sampleCount::type
long long type
Definition: SampleCount.h:20
ODFLACFile::error_callback
void error_callback(FLAC__StreamDecoderErrorStatus status) override
Definition: ODDecodeFlacTask.cpp:90
ODFLACFile::metadata_callback
void metadata_callback(const FLAC__StreamMetadata *metadata) override
Definition: ODDecodeFlacTask.cpp:46
ODFlacDecoder::mBitsPerSample
unsigned long mBitsPerSample
Definition: ODDecodeFlacTask.h:129
ODFlacDecoder::mFile
std::unique_ptr< ODFLACFile > mFile
Definition: ODDecodeFlacTask.h:124
SampleBuffer
Definition: SampleFormat.h:69
sampleFormat
sampleFormat
Definition: SampleFormat.h:29
ODFlacDecoder::mHandle
wxFFile mHandle
Definition: ODDecodeFlacTask.h:126
ODFileDecoder
class to decode a particular file (one per file). Saves info such as filename and length (after the h...
Definition: ODDecodeBlockFile.h:194
ODFlacDecoder::mDecodeBufferLen
unsigned int mDecodeBufferLen
Definition: ODDecodeFlacTask.h:138
ODFlacDecoder::Decode
int Decode(SampleBuffer &data, sampleFormat &format, sampleCount start, size_t len, unsigned int channel) override
Definition: ODDecodeFlacTask.cpp:172
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
ODFlacDecoder::mSamplesDone
FLAC__uint64 mSamplesDone
Definition: ODDecodeFlacTask.h:131
ODFlacDecoder::mDecodeBuffer
samplePtr mDecodeBuffer
Definition: ODDecodeFlacTask.h:139
ODFLACFile::mComments
wxArrayString mComments
Definition: ODDecodeFlacTask.h:84
ODTask::GetDemandSample
virtual sampleCount GetDemandSample() const
Definition: ODTask.cpp:221
ODFlacDecoder::mNumSamples
FLAC__uint64 mNumSamples
Definition: ODDecodeFlacTask.h:130
ODFileDecoder::mFName
const wxString mFName
Definition: ODDecodeBlockFile.h:227
ODFlacDecoder::~ODFlacDecoder
virtual ~ODFlacDecoder()
Definition: ODDecodeFlacTask.cpp:270
ODFlacDecoder::mLastDecodeStartSample
sampleCount mLastDecodeStartSample
Definition: ODDecodeFlacTask.h:132
ODFLACFile::mDecoder
ODFlacDecoder * mDecoder
Definition: ODDecodeFlacTask.h:82
ODDecodeFlacTask::CreateFileDecoder
ODFileDecoder * CreateFileDecoder(const wxString &fileName) override
Creates an ODFileDecoder that decodes a file of filetype the subclass handles.
Definition: ODDecodeFlacTask.cpp:278
SampleBuffer::ptr
samplePtr ptr() const
Definition: SampleFormat.h:98