Audacity  2.2.2
Typedefs | Functions
ImportRaw.h File Reference
#include "../MemoryX.h"
#include <vector>

Go to the source code of this file.

Typedefs

using TrackHolders = std::vector< std::unique_ptr< WaveTrack >>
 

Functions

void ImportRaw (wxWindow *parent, const wxString &fileName, TrackFactory *trackFactory, TrackHolders &outTracks)
 

Typedef Documentation

using TrackHolders = std::vector<std::unique_ptr<WaveTrack>>

Definition at line 42 of file ImportRaw.h.

Function Documentation

void ImportRaw ( wxWindow *  parent,
const wxString &  fileName,
TrackFactory trackFactory,
TrackHolders outTracks 
)

Definition at line 100 of file ImportRaw.cpp.

References _(), Cancelled, Failed, format, FormatClassifier::GetResultFormatLibSndfile(), gPrefs, Track::LeftChannel, ImportRawDialog::mChannels, ImportRawDialog::mEncoding, ImportRawDialog::mOffset, Track::MonoChannel, ImportRawDialog::mPercent, ImportRawDialog::mRate, TrackFactory::NewWaveTrack(), FileException::Open, SampleBuffer::ptr(), FileException::Read, Track::RightChannel, sf_subtype_more_than_16_bits(), Success, and ProgressDialog::Update().

Referenced by AudacityProject::OnImportRaw().

102 {
103  outTracks.clear();
104  int encoding = 0; // Guess Format
105  sampleFormat format;
106  sf_count_t offset = 0;
107  double rate = 44100.0;
108  double percent = 100.0;
109  TrackHolders channels;
110  auto updateResult = ProgressResult::Success;
111 
112  {
113  SF_INFO sndInfo;
114  int result;
115 
116  unsigned numChannels = 0;
117 
118  try {
119  // Yes, FormatClassifier currently handles filenames in UTF8 format only, that's
120  // a TODO ...
121  FormatClassifier theClassifier(fileName.utf8_str());
122  encoding = theClassifier.GetResultFormatLibSndfile();
123  numChannels = theClassifier.GetResultChannels();
124  offset = 0;
125  } catch (...) {
126  // Something went wrong in FormatClassifier, use defaults instead.
127  encoding = 0;
128  }
129 
130  if (encoding <= 0) {
131  // Unable to guess. Use mono, 16-bit samples with CPU endianness
132  // as the default.
133  encoding = SF_FORMAT_RAW | SF_ENDIAN_CPU | SF_FORMAT_PCM_16;
134  numChannels = 1;
135  offset = 0;
136  }
137 
138  numChannels = std::max(1u, numChannels);
139  ImportRawDialog dlog(parent, encoding, numChannels, (int)offset, rate);
140  dlog.ShowModal();
141  if (!dlog.GetReturnCode())
142  return;
143 
144  encoding = dlog.mEncoding;
145  numChannels = dlog.mChannels;
146  rate = dlog.mRate;
147  offset = (sf_count_t)dlog.mOffset;
148  percent = dlog.mPercent;
149 
150  memset(&sndInfo, 0, sizeof(SF_INFO));
151  sndInfo.samplerate = (int)rate;
152  sndInfo.channels = (int)numChannels;
153  sndInfo.format = encoding | SF_FORMAT_RAW;
154 
155  wxFile f; // will be closed when it goes out of scope
156  SFFile sndFile;
157 
158  if (f.Open(fileName)) {
159  // Even though there is an sf_open() that takes a filename, use the one that
160  // takes a file descriptor since wxWidgets can open a file with a Unicode name and
161  // libsndfile can't (under Windows).
162  sndFile.reset(SFCall<SNDFILE*>(sf_open_fd, f.fd(), SFM_READ, &sndInfo, FALSE));
163  }
164 
165  if (!sndFile){
166  char str[1000];
167  sf_error_str((SNDFILE *)NULL, str, 1000);
168  wxPrintf("%s\n", str);
169 
170  throw FileException{ FileException::Cause::Open, fileName };
171  }
172 
173  result = sf_command(sndFile.get(), SFC_SET_RAW_START_OFFSET, &offset, sizeof(offset));
174  if (result != 0) {
175  char str[1000];
176  sf_error_str(sndFile.get(), str, 1000);
177  wxPrintf("%s\n", str);
178 
179  throw FileException{ FileException::Cause::Read, fileName };
180  }
181 
182  SFCall<sf_count_t>(sf_seek, sndFile.get(), 0, SEEK_SET);
183 
184  auto totalFrames =
185  // fraction of a sf_count_t value
186  (sampleCount)(sndInfo.frames * percent / 100.0);
187 
188  //
189  // Sample format:
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  format = (sampleFormat)
197  gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
198 
199  if (format != floatSample &&
201  format = floatSample;
202 
203  channels.resize(numChannels);
204 
205  auto iter = channels.begin();
206  for (decltype(numChannels) c = 0; c < numChannels; ++iter, ++c) {
207  const auto channel =
208  (*iter = trackFactory->NewWaveTrack(format, rate)).get();
209 
210  if (numChannels > 1)
211  switch (c) {
212  case 0:
213  channel->SetChannel(Track::LeftChannel);
214  break;
215  case 1:
216  channel->SetChannel(Track::RightChannel);
217  break;
218  default:
219  channel->SetChannel(Track::MonoChannel);
220  }
221  }
222 
223  const auto firstChannel = channels.begin()->get();
224  if (numChannels == 2) {
225  firstChannel->SetLinked(true);
226  }
227 
228  auto maxBlockSize = firstChannel->GetMaxBlockSize();
229 
230  SampleBuffer srcbuffer(maxBlockSize * numChannels, format);
231  SampleBuffer buffer(maxBlockSize, format);
232 
233  decltype(totalFrames) framescompleted = 0;
234  if (totalFrames < 0) {
235  wxASSERT(false);
236  totalFrames = 0;
237  }
238 
239  wxString msg;
240 
241  msg.Printf(_("Importing %s"), wxFileName::FileName(fileName).GetFullName());
242 
243  /* i18n-hint: 'Raw' means 'unprocessed' here and should usually be tanslated.*/
244  ProgressDialog progress(_("Import Raw"), msg);
245 
246  size_t block;
247  do {
248  block =
249  limitSampleBufferSize( maxBlockSize, totalFrames - framescompleted );
250 
251  sf_count_t result;
252  if (format == int16Sample)
253  result = SFCall<sf_count_t>(sf_readf_short, sndFile.get(), (short *)srcbuffer.ptr(), block);
254  else
255  result = SFCall<sf_count_t>(sf_readf_float, sndFile.get(), (float *)srcbuffer.ptr(), block);
256 
257  if (result >= 0) {
258  block = result;
259  }
260  else {
261  // This is not supposed to happen, sndfile.h says result is always
262  // a count, not an invalid value for error
263  throw FileException{ FileException::Cause::Read, fileName };
264  }
265 
266  if (block) {
267  auto iter = channels.begin();
268  for(decltype(numChannels) c = 0; c < numChannels; ++iter, ++c) {
269  if (format==int16Sample) {
270  for(decltype(block) j=0; j<block; j++)
271  ((short *)buffer.ptr())[j] =
272  ((short *)srcbuffer.ptr())[numChannels*j+c];
273  }
274  else {
275  for(decltype(block) j=0; j<block; j++)
276  ((float *)buffer.ptr())[j] =
277  ((float *)srcbuffer.ptr())[numChannels*j+c];
278  }
279 
280  iter->get()->Append(buffer.ptr(), (format == int16Sample)?int16Sample:floatSample, block);
281  }
282  framescompleted += block;
283  }
284 
285  updateResult = progress.Update(
286  framescompleted.as_long_long(),
287  totalFrames.as_long_long()
288  );
289  if (updateResult != ProgressResult::Success)
290  break;
291 
292  } while (block > 0 && framescompleted < totalFrames);
293  }
294 
295  if (updateResult == ProgressResult::Failed || updateResult == ProgressResult::Cancelled)
296  throw UserException{};
297 
298  for (const auto &channel : channels)
299  channel->Flush();
300  outTracks.swap(channels);
301 }
ProgressDialog Class.
bool sf_subtype_more_than_16_bits(unsigned int format)
FormatClassifier classifies the sample format and endianness of raw audio files.
ImportRawDialog prompts you with options such as endianness and sample size to help you importing dat...
Definition: ImportRaw.cpp:61
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
int format
Definition: ExportPCM.cpp:56
if(pTrack &&pTrack->GetDisplay()!=WaveTrack::Spectrum)
std::unique_ptr< WaveTrack > NewWaveTrack(sampleFormat format=(sampleFormat) 0, double rate=0)
Definition: WaveTrack.cpp:78
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
std::vector< std::unique_ptr< WaveTrack >> TrackHolders
Definition: ImportRaw.h:42