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::@176 context

References context.

Member Function Documentation

◆ FillComment()

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

Definition at line 379 of file ExportOGG.cpp.

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

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

Here is the call graph for this function:

◆ Process()

ExportResult OGGExportProcessor::Process ( ExportProcessorDelegate delegate)
overridevirtual

Implements ExportProcessor.

Definition at line 282 of file ExportOGG.cpp.

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