Audacity 3.2.0
Public Member Functions | Static Private Member Functions | Private Attributes | List of all members
OGGExportProcessor Class Referencefinal
Inheritance diagram for OGGExportProcessor:
[legend]
Collaboration diagram for OGGExportProcessor:
[legend]

Public Member Functions

 ~OGGExportProcessor () override
 
bool Initialize (AudacityProject &project, const Parameters &parameters, const wxFileNameWrapper &filename, double t0, double t1, bool selectedOnly, double sampleRate, unsigned channels, MixerOptions::Downmix *mixerSpec, const Tags *tags) override
 Called before start processing. More...
 
ExportResult Process (ExportProcessorDelegate &delegate) override
 
- Public Member Functions inherited from ExportProcessor
 ExportProcessor (const ExportProcessor &)=delete
 
ExportProcessoroperator= (const ExportProcessor &)=delete
 
 ExportProcessor ()=default
 
virtual ~ExportProcessor ()
 
virtual bool Initialize (AudacityProject &project, const Parameters &parameters, const wxFileNameWrapper &filename, double t0, double t1, bool selectedOnly, double rate, unsigned channels, MixerOptions::Downmix *mixerSpec=nullptr, const Tags *tags=nullptr)=0
 Called before start processing. More...
 
virtual ExportResult Process (ExportProcessorDelegate &delegate)=0
 

Static Private Member Functions

static void FillComment (AudacityProject *project, vorbis_comment *comment, const Tags *metadata)
 

Private Attributes

struct {
   TranslatableString   status
 
   double   t0
 
   double   t1
 
   unsigned   numChannels
 
   std::unique_ptr< Mixer >   mixer
 
   std::unique_ptr< FileIO >   outFile
 
   wxFileNameWrapper   fName
 
   ogg_stream_state   stream
 
   ogg_page   page
 
   ogg_packet   packet
 
   vorbis_info   info
 
   vorbis_comment   comment
 
   vorbis_dsp_state   dsp
 
   vorbis_block   block
 
   bool   stream_ok {false}
 
   bool   analysis_state_ok {false}
 
context
 

Additional Inherited Members

- Public Types inherited from ExportProcessor
using Parameters = std::vector< std::tuple< ExportOptionID, ExportValue > >
 

Detailed Description

Definition at line 102 of file ExportOGG.cpp.

Constructor & Destructor Documentation

◆ ~OGGExportProcessor()

OGGExportProcessor::~OGGExportProcessor ( )
override

Definition at line 172 of file ExportOGG.cpp.

173{
174 if(context.stream_ok)
175 ogg_stream_clear(&context.stream);
176
177 if(context.analysis_state_ok)
178 {
179 vorbis_comment_clear(&context.comment);
180 vorbis_block_clear(&context.block);
181 vorbis_dsp_clear(&context.dsp);
182 }
183
184 vorbis_info_clear(&context.info);
185}
struct OGGExportProcessor::@178 context

References context.

Member Function Documentation

◆ FillComment()

void OGGExportProcessor::FillComment ( AudacityProject project,
vorbis_comment *  comment,
const Tags metadata 
)
staticprivate

Definition at line 381 of file ExportOGG.cpp.

382{
383 // Retrieve tags from project if not over-ridden
384 if (metadata == NULL)
385 metadata = &Tags::Get( *project );
386
387 vorbis_comment_init(comment);
388
389 wxString n;
390 for (const auto &pair : metadata->GetRange()) {
391 n = pair.first;
392 const auto &v = pair.second;
393 if (n == TAG_YEAR) {
394 n = wxT("DATE");
395 }
396 vorbis_comment_add_tag(comment,
397 (char *) (const char *) n.mb_str(wxConvUTF8),
398 (char *) (const char *) v.mb_str(wxConvUTF8));
399 }
400}
wxT("CloseDown"))
#define TAG_YEAR
Definition: Tags.h:62
const auto project
vorbis_comment comment
Definition: ExportOGG.cpp:120
Iterators GetRange() const
Definition: Tags.cpp:426
static Tags & Get(AudacityProject &project)
Definition: Tags.cpp:214

References comment, Tags::Get(), Tags::GetRange(), project, TAG_YEAR, and wxT().

Referenced by Initialize().

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

◆ Initialize()

bool OGGExportProcessor::Initialize ( AudacityProject project,
const Parameters parameters,
const wxFileNameWrapper filename,
double  t0,
double  t1,
bool  selectedOnly,
double  rate,
unsigned  channels,
MixerOptions::Downmix mixerSpec,
const Tags tags 
)
overridevirtual

Called before start processing.

Parameters
projectProcessor may access project data, take care to exclude any data race
parametersA format-dependent set of parameters used in exporting
selectedOnlySet to true if all tracks should be mixed, to false if only the selected tracks should be mixed and exported.
tagsA Tags object that will over-ride the one in *project and be used to tag the file that is exported. @retern Implementations may simply return false without any error reporting. This is to temporarily preserve old behavior, which is to be removed in the nearest future.

Implements ExportProcessor.

Definition at line 188 of file ExportOGG.cpp.

195{
196 context.t0 = t0;
197 context.t1 = t1;
198 context.numChannels = numChannels;
199
200 const auto &tracks = TrackList::Get( project );
201 double quality = ExportPluginHelpers::GetParameterValue(parameters, 0, 5) / 10.0;
202
203 wxLogNull logNo; // temporarily disable wxWidgets error messages
204
205 // Many of the library functions called below return 0 for success and
206 // various nonzero codes for failure.
207
208 // Encoding setup
209
210 vorbis_info_init(&context.info);
211
212 if (vorbis_encode_init_vbr(&context.info, numChannels, (int)(sampleRate + 0.5), quality)) {
213 // TODO: more precise message
214 throw ExportException(_("Unable to export - rate or quality problem"));
215 }
216
217 context.outFile = std::make_unique<FileIO>(fName, FileIO::Output);
218
219 if (!context.outFile->IsOpened()) {
220 throw ExportException(_("Unable to open target file for writing"));
221 }
222
223 context.analysis_state_ok = vorbis_analysis_init(&context.dsp, &context.info) == 0 &&
224 vorbis_block_init(&context.dsp, &context.block) == 0;
225 // Set up analysis state and auxiliary encoding storage
226 if (!context.analysis_state_ok) {
227 throw ExportException(_("Unable to export - problem initialising"));
228 }
229
230 // Retrieve tags
231 FillComment(&project, &context.comment, metadata);
232
233 // Set up packet->stream encoder. According to encoder example,
234 // a random serial number makes it more likely that you can make
235 // chained streams with concatenation.
236 srand(time(NULL));
237 context.stream_ok = ogg_stream_init(&context.stream, rand()) == 0;
238 if (!context.stream_ok) {
239 throw ExportException(_("Unable to export - problem creating stream"));
240 }
241
242 // First we need to write the required headers:
243 // 1. The Ogg bitstream header, which contains codec setup params
244 // 2. The Vorbis comment header
245 // 3. The bitstream codebook.
246 //
247 // After we create those our responsibility is complete, libvorbis will
248 // take care of any other ogg bitstream constraints (again, according
249 // to the example encoder source)
250 ogg_packet bitstream_header;
251 ogg_packet comment_header;
252 ogg_packet codebook_header;
253
254 if(vorbis_analysis_headerout(&context.dsp, &context.comment, &bitstream_header, &comment_header,
255 &codebook_header) ||
256 // Place these headers into the stream
257 ogg_stream_packetin(&context.stream, &bitstream_header) ||
258 ogg_stream_packetin(&context.stream, &comment_header) ||
259 ogg_stream_packetin(&context.stream, &codebook_header)) {
260 throw ExportException(_("Unable to export - problem with packets"));
261 }
262
263 // Flushing these headers now guarantees that audio data will
264 // start on a NEW page, which apparently makes streaming easier
265 while (ogg_stream_flush(&context.stream, &context.page)) {
266 if ( context.outFile->Write(context.page.header, context.page.header_len).GetLastError() ||
267 context.outFile->Write(context.page.body, context.page.body_len).GetLastError()) {
268 throw ExportException(_("Unable to export - problem with file"));
269 }
270 }
271
272 context.mixer = ExportPluginHelpers::CreateMixer(tracks, selectionOnly,
273 t0, t1,
275 sampleRate, floatSample, mixerSpec);
276
277 context.status = selectionOnly
278 ? XO("Exporting the selected audio as Ogg Vorbis")
279 : XO("Exporting the audio as Ogg Vorbis");
280
281 return true;
282}
#define SAMPLES_PER_RUN
Definition: ExportOGG.cpp:100
XO("Cut/Copy/Paste")
#define _(s)
Definition: Internat.h:73
const auto tracks
static T GetParameterValue(const ExportProcessor::Parameters &parameters, int id, T defaultValue=T())
static std::unique_ptr< Mixer > CreateMixer(const TrackList &tracks, bool selectionOnly, double startTime, double stopTime, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, double outRate, sampleFormat outFormat, MixerOptions::Downmix *mixerSpec)
@ Output
Definition: FileIO.h:27
static void FillComment(AudacityProject *project, vorbis_comment *comment, const Tags *metadata)
Definition: ExportOGG.cpp:381
unsigned numChannels
Definition: ExportOGG.cpp:109
wxFileNameWrapper fName
Definition: ExportOGG.cpp:112
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314

References _, context, ExportPluginHelpers::CreateMixer(), FillComment(), floatSample, fName, TrackList::Get(), ExportPluginHelpers::GetParameterValue(), numChannels, FileIO::Output, project, anonymous_namespace{ClipSegmentTest.cpp}::sampleRate, SAMPLES_PER_RUN, t0, t1, tracks, and XO().

Here is the call graph for this function:

◆ Process()

ExportResult OGGExportProcessor::Process ( ExportProcessorDelegate delegate)
overridevirtual

Implements ExportProcessor.

Definition at line 284 of file ExportOGG.cpp.

285{
286 delegate.SetStatusString(context.status);
287 auto exportResult = ExportResult::Success;
288 {
289 int err;
290 int eos = 0;
291 while (exportResult == ExportResult::Success && !eos) {
292 float **vorbis_buffer = vorbis_analysis_buffer(&context.dsp, SAMPLES_PER_RUN);
293 auto samplesThisRun = context.mixer->Process();
294
295 if (samplesThisRun == 0) {
296 // Tell the library that we wrote 0 bytes - signalling the end.
297 err = vorbis_analysis_wrote(&context.dsp, 0);
298 }
299 else {
300
301 for (size_t i = 0; i < context.numChannels; i++) {
302 float *temp = (float *)context.mixer->GetBuffer(i);
303 memcpy(vorbis_buffer[i], temp, sizeof(float)*SAMPLES_PER_RUN);
304 }
305
306 // tell the encoder how many samples we have
307 err = vorbis_analysis_wrote(&context.dsp, samplesThisRun);
308 }
309
310 // I don't understand what this call does, so here is the comment
311 // from the example, verbatim:
312 //
313 // vorbis does some data preanalysis, then divvies up blocks
314 // for more involved (potentially parallel) processing. Get
315 // a single block for encoding now
316 while (!err && vorbis_analysis_blockout(&context.dsp, &context.block) == 1) {
317
318 // analysis, assume we want to use bitrate management
319 err = vorbis_analysis(&context.block, NULL);
320 if (!err)
321 err = vorbis_bitrate_addblock(&context.block);
322
323 while (!err && vorbis_bitrate_flushpacket(&context.dsp, &context.packet)) {
324
325 // add the packet to the bitstream
326 err = ogg_stream_packetin(&context.stream, &context.packet);
327
328 // From vorbis-tools-1.0/oggenc/encode.c:
329 // If we've gone over a page boundary, we can do actual output,
330 // so do so (for however many pages are available).
331
332 while (!err && !eos) {
333 int result = ogg_stream_pageout(&context.stream, &context.page);
334 if (!result) {
335 break;
336 }
337
338 if ( context.outFile->Write(context.page.header, context.page.header_len).GetLastError() ||
339 context.outFile->Write(context.page.body, context.page.body_len).GetLastError()) {
340 // TODO: more precise message
341 throw ExportDiskFullError(context.fName);
342 }
343
344 if (ogg_page_eos(&context.page)) {
345 eos = 1;
346 }
347 }
348 }
349 }
350
351 if (err) {
352 // TODO: more precise message
353 throw ExportErrorException("OGG:355");
354 }
356 delegate, *context.mixer, context.t0, context.t1);
357 }
358 }
359
360 if ( !context.outFile->Close() ) {
361 // TODO: more precise message
362 throw ExportErrorException("OGG:366");
363 }
364
365 return exportResult;
366}
static ExportResult UpdateProgress(ExportProcessorDelegate &delegate, Mixer &mixer, double t0, double t1)
Sends progress update to delegate and retrieves state update from it. Typically used inside each expo...
virtual void SetStatusString(const TranslatableString &str)=0

References context, SAMPLES_PER_RUN, ExportProcessorDelegate::SetStatusString(), Success, and ExportPluginHelpers::UpdateProgress().

Here is the call graph for this function:

Member Data Documentation

◆ analysis_state_ok

bool OGGExportProcessor::analysis_state_ok {false}

Definition at line 124 of file ExportOGG.cpp.

◆ block

vorbis_block OGGExportProcessor::block

Definition at line 122 of file ExportOGG.cpp.

◆ comment

vorbis_comment OGGExportProcessor::comment

Definition at line 120 of file ExportOGG.cpp.

Referenced by FillComment().

◆ 

struct { ... } OGGExportProcessor::context

◆ dsp

vorbis_dsp_state OGGExportProcessor::dsp

Definition at line 121 of file ExportOGG.cpp.

◆ fName

wxFileNameWrapper OGGExportProcessor::fName

Definition at line 112 of file ExportOGG.cpp.

Referenced by Initialize().

◆ info

vorbis_info OGGExportProcessor::info

Definition at line 119 of file ExportOGG.cpp.

◆ mixer

std::unique_ptr<Mixer> OGGExportProcessor::mixer

Definition at line 110 of file ExportOGG.cpp.

◆ numChannels

unsigned OGGExportProcessor::numChannels

Definition at line 109 of file ExportOGG.cpp.

Referenced by Initialize().

◆ outFile

std::unique_ptr<FileIO> OGGExportProcessor::outFile

Definition at line 111 of file ExportOGG.cpp.

◆ packet

ogg_packet OGGExportProcessor::packet

Definition at line 117 of file ExportOGG.cpp.

◆ page

ogg_page OGGExportProcessor::page

Definition at line 116 of file ExportOGG.cpp.

◆ status

TranslatableString OGGExportProcessor::status

Definition at line 106 of file ExportOGG.cpp.

◆ stream

ogg_stream_state OGGExportProcessor::stream

Definition at line 115 of file ExportOGG.cpp.

◆ stream_ok

bool OGGExportProcessor::stream_ok {false}

Definition at line 123 of file ExportOGG.cpp.

◆ t0

double OGGExportProcessor::t0

Definition at line 107 of file ExportOGG.cpp.

Referenced by Initialize().

◆ t1

double OGGExportProcessor::t1

Definition at line 108 of file ExportOGG.cpp.

Referenced by Initialize().


The documentation for this class was generated from the following file: