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 "ImportUtils.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 280 of file ImportRaw.cpp.

280 {
281 ChoiceID = 9000,
282 PlayID,
283 DetectID,
284};
@ PlayID
Definition: ImportRaw.cpp:282
@ DetectID
Definition: ImportRaw.cpp:283
@ ChoiceID
Definition: ImportRaw.cpp:281

Function Documentation

◆ getEndianChoice()

static int getEndianChoice ( int  sfFormat)
static

Definition at line 260 of file ImportRaw.cpp.

260 {
261 switch (sfFormat & SF_FORMAT_ENDMASK)
262 {
263 default:
264 case SF_ENDIAN_FILE:
265 return 0;
266 case SF_ENDIAN_LITTLE:
267 return 1;
268 case SF_ENDIAN_BIG:
269 return 2;
270 case SF_ENDIAN_CPU:
271 return 3;
272 }
273}

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 106 of file ImportRaw.cpp.

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

References details::begin(), ImportUtils::ChooseFormat(), WaveTrackFactory::CreateMany(), floatSample, ImportUtils::ForEachChannel(), anonymous_namespace{ExportPCM.cpp}::format, ProjectRate::Get(), ProjectRate::GetRate(), int16Sample, limitSampleBufferSize(), anonymous_namespace{StaffPadTimeAndPitch.cpp}::maxBlockSize, ImportRawDialog::mChannels, ImportRawDialog::mEncoding, ImportRawDialog::mOffset, ImportRawDialog::mPercent, ImportRawDialog::mRate, FileException::Open, project, 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: