Audacity 3.2.0
Classes | Enumerations | Functions
ImportRaw.cpp File Reference

Functions for guessing audio type and attempting to read from unknown sample audio data. Implements ImportRawDialog. More...

#include "ImportRaw.h"
#include "ImportPlugin.h"
#include "AudioIOBase.h"
#include "../FileFormats.h"
#include "Prefs.h"
#include "ProjectRate.h"
#include "SelectFile.h"
#include "ShuttleGui.h"
#include "UserException.h"
#include "WaveTrack.h"
#include "ProgressDialog.h"
#include <cmath>
#include <stdint.h>
#include <vector>
#include <wx/crt.h>
#include <wx/defs.h>
#include <wx/button.h>
#include <wx/choice.h>
#include <wx/combobox.h>
#include <wx/panel.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include "FormatClassifier.h"
#include "sndfile.h"
Include dependency graph for ImportRaw.cpp:

Go to the source code of this file.

Classes

class  ImportRawDialog
 ImportRawDialog prompts you with options such as endianness and sample size to help you importing data of an unknown format. More...
 

Enumerations

enum  { ChoiceID = 9000 , PlayID , DetectID }
 

Functions

void ImportRaw (const AudacityProject &project, wxWindow *parent, const wxString &fileName, WaveTrackFactory *trackFactory, TrackHolders &outTracks)
 
static int getEndianChoice (int sfFormat)
 

Detailed Description

Functions for guessing audio type and attempting to read from unknown sample audio data. Implements ImportRawDialog.

Definition in file ImportRaw.cpp.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
ChoiceID 
PlayID 
DetectID 

Definition at line 289 of file ImportRaw.cpp.

289 {
290 ChoiceID = 9000,
291 PlayID,
292 DetectID,
293};
@ PlayID
Definition: ImportRaw.cpp:291
@ DetectID
Definition: ImportRaw.cpp:292
@ ChoiceID
Definition: ImportRaw.cpp:290

Function Documentation

◆ getEndianChoice()

static int getEndianChoice ( int  sfFormat)
static

Definition at line 269 of file ImportRaw.cpp.

269 {
270 switch (sfFormat & SF_FORMAT_ENDMASK)
271 {
272 default:
273 case SF_ENDIAN_FILE:
274 return 0;
275 case SF_ENDIAN_LITTLE:
276 return 1;
277 case SF_ENDIAN_BIG:
278 return 2;
279 case SF_ENDIAN_CPU:
280 return 3;
281 }
282}

Referenced by ImportRawDialog::ImportRawDialog(), and ImportRawDialog::OnDetect().

Here is the caller graph for this function:

◆ ImportRaw()

void ImportRaw ( const AudacityProject project,
wxWindow *  parent,
const wxString &  fileName,
WaveTrackFactory trackFactory,
TrackHolders outTracks 
)

Definition at line 105 of file ImportRaw.cpp.

107{
108 outTracks.clear();
109
110 TrackHolders results;
111 auto updateResult = ProgressResult::Success;
112
113 {
114 // On first run, set default sample rate from project rate
115 if (ImportRawDialog::mRate < 100.)
117
118 ImportRawDialog dlog(parent, fileName);
119 dlog.ShowModal();
120 if (!dlog.GetReturnCode())
121 return;
122
123 const int encoding = dlog.mEncoding;
124 unsigned numChannels = dlog.mChannels;
125 double rate = dlog.mRate;
126 sf_count_t offset = (sf_count_t)dlog.mOffset;
127 double percent = dlog.mPercent;
128
129 SF_INFO sndInfo = { 0 };
130 sndInfo.samplerate = (int)rate;
131 sndInfo.channels = (int)numChannels;
132 sndInfo.format = encoding | SF_FORMAT_RAW;
133
134 wxFile f; // will be closed when it goes out of scope
135 SFFile sndFile;
136
137 if (f.Open(fileName)) {
138 // Even though there is an sf_open() that takes a filename, use the one that
139 // takes a file descriptor since wxWidgets can open a file with a Unicode name and
140 // libsndfile can't (under Windows).
141 sndFile.reset(SFCall<SNDFILE*>(sf_open_fd, f.fd(), SFM_READ, &sndInfo, FALSE));
142 }
143
144 if (!sndFile){
145 char str[1000];
146 sf_error_str((SNDFILE *)NULL, str, 1000);
147 wxPrintf("%s\n", str);
148
149 throw FileException{ FileException::Cause::Open, fileName };
150 }
151
152
153 {
154 int result = sf_command(sndFile.get(), SFC_SET_RAW_START_OFFSET, &offset, sizeof(offset));
155 if (result != 0) {
156 char str[1000];
157 sf_error_str(sndFile.get(), str, 1000);
158 wxPrintf("%s\n", str);
159
160 throw FileException{ FileException::Cause::Read, fileName };
161 }
162 }
163 SFCall<sf_count_t>(sf_seek, sndFile.get(), 0, SEEK_SET);
164
165 auto totalFrames =
166 // fraction of a sf_count_t value
167 (sampleCount)(sndInfo.frames * percent / 100.0);
168
169 //
170 // Sample format:
171 //
172 // In general, go with the user's preferences. However, if
173 // the file is higher-quality, go with a format which preserves
174 // the quality of the original file.
175 //
176
179
180 results.resize(1);
181 auto &channels = results[0];
182 channels.resize(numChannels);
183
184 {
185 // iter not used outside this scope.
186 auto iter = channels.begin();
187 for (decltype(numChannels) c = 0; c < numChannels; ++iter, ++c)
188 *iter = trackFactory->Create(format, rate);
189 }
190 const auto firstChannel = channels.begin()->get();
191 auto maxBlockSize = firstChannel->GetMaxBlockSize();
192
193 SampleBuffer srcbuffer(maxBlockSize * numChannels, format);
194 SampleBuffer buffer(maxBlockSize, format);
195
196 decltype(totalFrames) framescompleted = 0;
197 if (totalFrames < 0) {
198 wxASSERT(false);
199 totalFrames = 0;
200 }
201
202 auto msg = XO("Importing %s").Format( wxFileName::FileName(fileName).GetFullName() );
203
204 /* i18n-hint: 'Raw' means 'unprocessed' here and should usually be translated.*/
205 ProgressDialog progress(XO("Import Raw"), msg);
206
207 size_t block;
208 do {
209 block =
210 limitSampleBufferSize( maxBlockSize, totalFrames - framescompleted );
211
212 sf_count_t sf_result;
213 if (format == int16Sample)
214 sf_result = SFCall<sf_count_t>(sf_readf_short, sndFile.get(), (short *)srcbuffer.ptr(), block);
215 else
216 sf_result = SFCall<sf_count_t>(sf_readf_float, sndFile.get(), (float *)srcbuffer.ptr(), block);
217
218 if (sf_result >= 0) {
219 block = sf_result;
220 }
221 else {
222 // This is not supposed to happen, sndfile.h says result is always
223 // a count, not an invalid value for error
224 throw FileException{ FileException::Cause::Read, fileName };
225 }
226
227 if (block) {
228 auto iter = channels.begin();
229 for(decltype(numChannels) c = 0; c < numChannels; ++iter, ++c) {
230 if (format==int16Sample) {
231 for(decltype(block) j=0; j<block; j++)
232 ((short *)buffer.ptr())[j] =
233 ((short *)srcbuffer.ptr())[numChannels*j+c];
234 }
235 else {
236 for(decltype(block) j=0; j<block; j++)
237 ((float *)buffer.ptr())[j] =
238 ((float *)srcbuffer.ptr())[numChannels*j+c];
239 }
240
241 iter->get()->Append(buffer.ptr(), (format == int16Sample)?int16Sample:floatSample, block,
242 1, sf_subtype_to_effective_format(encoding));
243 }
244 framescompleted += block;
245 }
246
247 updateResult = progress.Update(
248 framescompleted.as_long_long(),
249 totalFrames.as_long_long()
250 );
251 if (updateResult != ProgressResult::Success)
252 break;
253
254 } while (block > 0 && framescompleted < totalFrames);
255 }
256
257 if (updateResult == ProgressResult::Failed || updateResult == ProgressResult::Cancelled)
258 throw UserException{};
259
260 if (!results.empty() && !results[0].empty()) {
261 for (const auto &channel : results[0])
262 channel->Flush();
263 outTracks.swap(results);
264 }
265}
#define str(a)
int format
Definition: ExportPCM.cpp:53
sampleFormat sf_subtype_to_effective_format(unsigned int format)
Choose the narrowest value in the sampleFormat enumeration for a given libsndfile format.
XO("Cut/Copy/Paste")
std::vector< std::vector< std::shared_ptr< WaveTrack > > > TrackHolders
Definition: Import.h:39
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
constexpr sampleFormat int16Sample
Definition: SampleFormat.h:41
constexpr sampleFormat floatSample
Definition: SampleFormat.h:43
Thrown for failure of file or database operations in deeply nested places.
Definition: FileException.h:19
static sampleFormat ChooseFormat(sampleFormat effectiveFormat)
Choose appropriate format, which will not be narrower than the specified one.
ImportRawDialog prompts you with options such as endianness and sample size to help you importing dat...
Definition: ImportRaw.cpp:57
static double mRate
Definition: ImportRaw.cpp:74
ProgressDialog Class.
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
double GetRate() const
Definition: ProjectRate.cpp:53
Can be thrown when user cancels operations, as with a progress dialog. Delayed handler does nothing.
Definition: UserException.h:17
std::shared_ptr< WaveTrack > Create()
Creates an unnamed empty WaveTrack with default sample format and default rate.
Definition: WaveTrack.cpp:182
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19

References ImportFileHandle::ChooseFormat(), WaveTrackFactory::Create(), floatSample, format, ProjectRate::Get(), ProjectRate::GetRate(), int16Sample, limitSampleBufferSize(), ImportRawDialog::mChannels, ImportRawDialog::mEncoding, ImportRawDialog::mOffset, ImportRawDialog::mPercent, ImportRawDialog::mRate, FileException::Open, SampleBuffer::ptr(), FileException::Read, sf_subtype_to_effective_format(), str, BasicUI::Success, ProgressDialog::Update(), and XO().

Referenced by anonymous_namespace{FileMenus.cpp}::DoImport().

Here is the call graph for this function:
Here is the caller graph for this function: