Difference between revisions of "Reggae tutorial: Saving audio in user selected format"

From MorphOS Library

(Preparing Source Data)
(Creating Format Selection GUI)
Line 30: Line 30:
  
 
==Creating Format Selection GUI==
 
==Creating Format Selection GUI==
 +
Creating a MUI object containing format selector and GUIs for all encoders is very easy. It is just one call to ''MediaGetGuiTagList()'' function. As the name suggests, a [[Taglists|taglist]] can be used to control the GUI creation. Here is an example of it:
 +
 +
Object *FormatSelector;
 +
 +
FormatSelector = MediaGetGuiTags(
 +
  MGG_Type, MGG_Type_Muxers,
 +
  MGG_Media, MMT_SOUND,
 +
  MGG_Selector, MGG_Selector_List,
 +
  MUIA_Frame, MUIV_Frame_Group,
 +
TAG_END);
 +
 
==Building Reggae Processing Chain==
 
==Building Reggae Processing Chain==
 
==Saving Audio==
 
==Saving Audio==
 
==Cleanup==
 
==Cleanup==

Revision as of 18:47, 30 September 2012

Grzegorz Kraszewski

Introduction

Except of automatic media decoding, Reggae has also a feature on automatic encoding. There is one fundamental difference between these two however. In case of decoding, a format of decoded media, codec parameters, stream parameters, metadata, all this comes from the decoded datastream. When media are encoded, format, codec parameters and metadata have to be set by application.

Usually an application wants to offer all available formats to user. It means that application author has to maintain GUI for all codecs and their parameters. Also such a GUI would have to be updated with every new released codec. Reggae changes this and makes application programmer's life easier. The main rule is that multiplexer and encoder classes provide GUI. Reggae gathers those GUIs in a single object and returns it to application. Then application can embed this compound GUI object into its own interface. User can use this object to select encoder and its parameters. This is not all however.

After user selects output format and its parameters, Reggae can create encoder-muxer pair, read parameters and metadata from the GUI, and set them to proper objects. Then application connects the data source at input and output stream class at output. After triggering processing with MMM_Play() method on the output stream object, audio data is written.

Using Reggae media save API, application programmer need not to care about what formats Reggae supports. To say more, even if new codecs are released after the application release, the application will use them without a need for update.

Preparing Source Data

Source audio data may be prepared either as a static buffer, or generated on-demand. Static buffer technique is simplier and will be described here. Realtime generation may be accomplished by writing a custom Reggae class (see source code of U1Synth), or by using datapush.stream class. Source data also may come from Reggae, for example from some decoded audio file. This is the case for an audio converter Zormanita, which also is opensourced.

Data in a buffer should be in one of Reggae common formats. There are three common formats for audio: INT16, INT32 and FLOAT32. The choice depends on purpose and required processing quality. INT16 is the fastest format and is best suited for playback. FLOAT32 has more or less 24-bit resolution and may be handy for many synthesis algorithms, which are often easier to implement with floating point math. INT32 is the slowest one, but provides the best quality, usually better than further stages of processing. All three formats use signed numbers with host native byte order (which is big endian for PowerPC). Also floating point range is [−1.0; +1.0]. While it may be temporarilly exceeded, any Reggae class is allowed to clip data to this range. If audio is multichannel, channels are interleaved (for stereo the order is L, R).

Start address of the buffer must be AltiVec aligned. The easiest way to do it is to alloc the buffer with MediaAllocVec() function of multimedia.class. On the other hand buffer size need not to be aligned other than to the size of a single audio frame (set of samples of all the channels for one time point). Of course filling the buffer with data is up to application. In the example code below a buffer is created with 1 second of monophonic audio sampled at 44.1 kHz. It contains 44 100 INT16 audio samples, so the size of buffer is 88 200 bytes.

WORD *Buffer;

Buffer = (WORD*)MediaAllocVec(88200);

Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.

LONG i;

for (i = 0; i < 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);

The code is totally unoptimized, but has been left as such to be easy readable.

Creating Format Selection GUI

Creating a MUI object containing format selector and GUIs for all encoders is very easy. It is just one call to MediaGetGuiTagList() function. As the name suggests, a taglist can be used to control the GUI creation. Here is an example of it:

Object *FormatSelector;
FormatSelector = MediaGetGuiTags(
  MGG_Type, MGG_Type_Muxers,
  MGG_Media, MMT_SOUND,
  MGG_Selector, MGG_Selector_List,
  MUIA_Frame, MUIV_Frame_Group,
TAG_END);

Building Reggae Processing Chain

Saving Audio

Cleanup