<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://library.morph.zone/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Krashan</id>
		<title>MorphOS Library - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://library.morph.zone/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Krashan"/>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/Special:Contributions/Krashan"/>
		<updated>2026-04-19T22:56:25Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>https://library.morph.zone/index.php?title=Exec_Lists&amp;diff=1750</id>
		<title>Exec Lists</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Exec_Lists&amp;diff=1750"/>
				<updated>2013-01-12T20:26:40Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* List Iterator */ Fixed bugs in ForEachNode() macro iterator.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
A list is the simplest dynamic data structure. An array is even simplier, but it is not dynamic. Adding a single item to an array requires reallocation of memory and copying the whole old contents, similarly for removing. Inserting and removing elements to a list is very fast operation and its computational costs do not increase with number of items. Because of this, list is the basic structure used in ''exec.library'', the MorphOS kernel. One could say the Exec is built on lists. Lists are also used through all the system to manage processes, windows, screens, devices, DOS volumes, fonts, libraries and more. Of course lists are also used by applications to manage dynamic data. Many more sophisticated data structures are built on lists. For all these reasons understanding lists and their MorphOS flavour is essential for every programmer.&lt;br /&gt;
&lt;br /&gt;
Lists may be divided to intrusive and nonintrusive ones. An intrusive list is one requiring that every list item contains a part called a node. The node is then used for linking items into list. A nonintrusive list creates nodes itself. Both kinds have their advantages. Exec lists are intrusive. Why? For a nonintrusive list adding an item means allocating memory for its node. Exec lists are often used at really low levels of the system, like interrupt handling, process scheduler or input/output hardware devices. Calling memory allocator from there is unacceptable. Also error handling would become a nightmare (every memory allocation can fail...). In some parts of the system lists also have to be extremely fast. Memory allocation is a complex operation and can't be expected to finish in a few processor cycles. Of course on higher levels of the system, intrusiveness has more disadvantages than advantages. For example an item of intrusive list cannot be added to more than one list. Then high level components (for example MUI List class) may be nonintrusive ones.&lt;br /&gt;
&lt;br /&gt;
=From a Plain List to Exec List=&lt;br /&gt;
The simplest form of list is a unidirectional one. Node of every item consists only of pointer to the next element. The list is identified by keeping a pointer to its first item. Unidirectional lists however are used only in special cases. While inserting an element at list start is easy, inserting at end requires traversing the whole list. Time of this operation increases linearly with number of items. It is also not possible to traverse the list in the backward direction. Then bidirectional lists are much more common. Exec lists are bidirectional. Every node contains two pointers: one to the next element and one to the previous element. For the first element pointer to the previous one is ''NULL''. For the last one, pointer to the next one is ''NULL''. If a list user keeps pointers to both the first and the last element, she has symmetrical access to the start and the end of the list.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:execlists1.png|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;''A plain, bidirectional list. A node consists of &amp;quot;prev&amp;quot; and &amp;quot;next&amp;quot; pointers.''&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
While the idea is still simple, we have to complicate it a bit. As mentioned before, the list user keeps track of it by maintaining two pointers: to the first and the last item. These pointers will be modified every time an item is added or removed at the start or end of the list respectively. But what if a list has multiple users not knowing about each other? Adding an item at the start or at the end would require pointer update for '''all''' the users. To solve the problem, two artificial items are introduced: a '''list head''' and a '''list tail'''. Those two elements do not carry payload, only consist of a node. Their location does not change during the list lifetime so they work as anchors. Inserting an element at list start is in fact inserting it between the list head and the former first element. Similarly element inserted at end is in fact inserted between the former last element and the list tail. As pointers to the head and the tail are constant, they may be shared between multiple users.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:execlists2.png|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;''Bidirectional list with head and tail pseudoitems.''&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Exec lists combine the list head and the list tail into one structure, named '''list header'''. As the Exec was designed in the days when computer memory was counted in kilobytes rather than gigabytes, designers saw a way to save a few bytes. The &amp;quot;previous&amp;quot; field of list head node always contains ''NULL''. Similarly the &amp;quot;next&amp;quot; field of the list tail always contains ''NULL''. Then they can be merged into one. That is why the list header contains only three pointers instead of four. For the C language the list header is defined as ''struct List'' and lists are commonly referenced by a pointer to it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:execlists3.png|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;''The Exec list. Head and tail pseudoelements are merged into the list header.''&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Exec List Elements: Node and Header=&lt;br /&gt;
Exec defines two kinds of nodes: a full one and a minimal one. The minimal node consists only of pointers to the next and the previous item and is defined in C in ''&amp;amp;lt;exec/nodes.h&amp;amp;gt;'' header file as follows:&lt;br /&gt;
&lt;br /&gt;
 struct MinNode&lt;br /&gt;
 {&lt;br /&gt;
   struct MinNode *mln_Succ;     // successor, the next item&lt;br /&gt;
   struct MinNode *mln_Pred;     // predecessor, the previous item&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
The full node has additional fields used in many system lists. These fields are: item '''name''', item '''type''' and item '''priority'''.&lt;br /&gt;
&lt;br /&gt;
 struct Node&lt;br /&gt;
 {&lt;br /&gt;
   struct Node* ln_Succ;     // successor&lt;br /&gt;
   struct Node* ln_Pred;     // predecessor&lt;br /&gt;
   UBYTE        ln_Type;     // item type&lt;br /&gt;
   BYTE         ln_Pri;      // item priority&lt;br /&gt;
   char*        ln_Name;     // item name&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Additional node fields have meaning only for system lists and may be considered as part of payload. If we ignore C types, a ''Node'' is just a ''MinNode'' with three fields added at the end. Node priority may be used to implement ordered lists or queues. ''Exec.library'' provides functions for ordered item insertion.&lt;br /&gt;
&lt;br /&gt;
As there are two kinds of nodes, there are also two types of list headers. Both are defined in ''&amp;amp;lt;exec/lists.h&amp;amp;gt;'':&lt;br /&gt;
&lt;br /&gt;
 struct MinList&lt;br /&gt;
 {&lt;br /&gt;
   struct MinNode* mlh_Head;      // pointer to the first real item&lt;br /&gt;
   struct MinNode* mlh_Tail;      // merged head &amp;quot;previous&amp;quot; and tail &amp;quot;next&amp;quot;&lt;br /&gt;
   struct MinNode* mlh_TailPred;  // pointer to the last real item&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Header for full nodes has additional '''type''' field (used for system lists) and one byte padding to make the structure size even.&lt;br /&gt;
&lt;br /&gt;
 struct List&lt;br /&gt;
 {&lt;br /&gt;
   struct Node* lh_Head;      // pointer to the first real item&lt;br /&gt;
   struct Node* lh_Tail;      // merged head &amp;quot;previous&amp;quot; and tail &amp;quot;next&amp;quot;&lt;br /&gt;
   struct Node* lh_TailPred;  // pointer to the last real item&lt;br /&gt;
   UBYTE        lh_Type;&lt;br /&gt;
   UBYTE        lh_pad;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Again, when one ignores C types, the ''List'' structure is ''MinList'' with two extra fields. &lt;br /&gt;
&lt;br /&gt;
As Exec lists are intrusive, a custom item structure must contain ''MinNode'' (or ''Node'' if needed) as the first field. It must be a complete structure, not a pointer. Here is an example:&lt;br /&gt;
&lt;br /&gt;
 struct MyNode&lt;br /&gt;
 {&lt;br /&gt;
   struct MinNode   Node;        // must be the first&lt;br /&gt;
   struct Whatever  Foobar;      // example payload fields&lt;br /&gt;
   ULONG            Something;&lt;br /&gt;
   char             MoreData[10];&lt;br /&gt;
   /* ... */&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There is no limit on custom item size. As items are not copied, big items are manipulated with exactly the same speed as small ones.&lt;br /&gt;
&lt;br /&gt;
=List Initialization, Empty List Check=&lt;br /&gt;
The list header, which is either ''List'' or ''MinList'' structure must be initialized before use. Please note well:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;'''Clearing ''List'' to all zeros is NOT a proper Exec list initialization!'''&amp;lt;/center&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Looking at the diagrams above, we know how an empty list should look like:&lt;br /&gt;
&lt;br /&gt;
[[File:Execlists4.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An empty list contains only its head and tail, both merged into the header. When one splits them back in mind, initialization becomes obvious:&lt;br /&gt;
* The &amp;quot;next&amp;quot; field of the head points to the tail.&lt;br /&gt;
* The &amp;quot;prev&amp;quot; field of the head is ''NULL''.&lt;br /&gt;
* The &amp;quot;next&amp;quot; field of the tail is ''NULL''.&lt;br /&gt;
* The &amp;quot;prev&amp;quot; field of the tail points to the head.&lt;br /&gt;
Then the second and the third operation merge into one, as fields are merged. Following code performs proper Exec list initialization. Note the address operators '''&amp;amp;''', forgetting them is a common mistake:&lt;br /&gt;
&lt;br /&gt;
 struct MinList mylist;&lt;br /&gt;
 &lt;br /&gt;
 mylist.mlh_Head = (struct MinNode*)'''&amp;amp;'''mylist.mlh_Tail;&lt;br /&gt;
 mylist.mlh_Tail = NULL;&lt;br /&gt;
 mylist.mlh_TailPred = (struct MinNode*)'''&amp;amp;'''mylist.mlh_Head;&lt;br /&gt;
&lt;br /&gt;
In case of full ''List'', initialization is the same, just typecasts have ''Node'' instead of ''MinNode''. List initialization is a common operation, so ''&amp;amp;lt;exec/lists.h&amp;amp;gt;'' defines a  ''NEWLIST'' macro for it. The macro takes a pointer to ''List'' or ''MinList'', so for the above example it would be called as follows:&lt;br /&gt;
&lt;br /&gt;
 NEWLIST(&amp;amp;mylist);&lt;br /&gt;
&lt;br /&gt;
Empty list check is another common operation. It may be derived from the diagram above. One can check if a list is empty using four equivalent conditions:&lt;br /&gt;
&lt;br /&gt;
 if (mylist.mlh_Head-&amp;gt;mln_Succ == NULL)                         /* list is empty */&lt;br /&gt;
 if (mylist.mlh_Head == (struct MinNode*)&amp;amp;mylist.mlh_Tail)      /* list is empty */&lt;br /&gt;
 if (mylist.mlh_TailPred-&amp;gt;mln_Pred == NULL)                     /* list is empty */&lt;br /&gt;
 if (mylist.mlh_TailPred == (struct MinNode*)&amp;amp;mylist.mlh_Head)  /* list is empty */&lt;br /&gt;
&lt;br /&gt;
A ''IsListEmpty()'' macro defined in ''&amp;amp;lt;exec/lists.h&amp;amp;gt;'' uses the last condition, simplified by the fact that address of ''mlh_Head'' is the same as address of the whole ''MinList'' (a good compiler will optimize field reference out anyway).&lt;br /&gt;
&lt;br /&gt;
=List Iterator=&lt;br /&gt;
&lt;br /&gt;
A list iterator is a fragment of code (usually a loop) used for traversing the list and performing operations on its elements. The simplest, browsing iterator is usually implemented as a ''for'' loop:&lt;br /&gt;
&lt;br /&gt;
 struct MyNode *n;&lt;br /&gt;
 struct MinList *list;    // let's assume it is initialized already&lt;br /&gt;
 &lt;br /&gt;
 for (n = (struct MyNode*)list-&amp;gt;mlh_Head; n-&amp;gt;Node.mln_Succ; n = (struct MyNode*)n-&amp;gt;Node.mln_Succ)&lt;br /&gt;
 {&lt;br /&gt;
   /* do something with node 'n' */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The first part of the ''for'' statement initializes the pointer ''n'' to the first real item of the list (the successor of the head item). The second part is the loop end condition. Loop ends when successor of the current element is ''NULL'', which happens when the current element is the list tail. Then the loop contents is not executed for the tail, as the tail is not a &amp;quot;real&amp;quot; item, as said above. Finally the third part of ''for'' statement moves the pointer to the next list item. A symmetric iterator may be written for browsing a list from the end in backward direction:&lt;br /&gt;
&lt;br /&gt;
 for (n = (struct MyNode*)list-&amp;gt;mlh_TailPred; n-&amp;gt;Node.mln_Pred; n = (struct MyNode*)n-&amp;gt;&lt;br /&gt;
  Node.mln_Pred)&lt;br /&gt;
 {&lt;br /&gt;
   /* do something with node 'n' */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This time the pointer ''n'' is initialized to the last real item (predecessor of the list tail), pointer is moved to the previous item in each loop turn. The loop finishes, when the predecessor of the current item is ''NULL'', which is the case for the list head. Again, the loop is not executed for the list head itself.&lt;br /&gt;
&lt;br /&gt;
The ''&amp;amp;lt;exec/lists.h&amp;amp;gt;'' header file provides ''ForeachNode()'' macro for building a ''for'' based iterator. The macro is a bit dangerous however, because it blindly typecasts the node pointer to ''struct Node*'' and the list pointer to ''struct List*''. It effectively bypasses the static C language type control and can lead to bugs in code. It is much safer to cast the node pointer to the real type of the list item, as shown in the above example iterators. Then a safer iterator macro should take the type name as one of arguments:&lt;br /&gt;
&lt;br /&gt;
 #define ForEachNode(n, T, list) for (n = (T)(list)-&amp;gt;mlh_Head; n-&amp;gt;Node.mln_Succ; \&lt;br /&gt;
  n = (T)n-&amp;gt;Node.mln_Succ)&lt;br /&gt;
&lt;br /&gt;
The macro may be used as follows:&lt;br /&gt;
&lt;br /&gt;
 ForEachNode(n, struct MyNode*, list)&lt;br /&gt;
 {&lt;br /&gt;
   /* do something with node 'n' */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This macro is not so universal, as it assumes ''MinList'' list and also assumes that the ''MinNode'' field placed at the start of ''MyNode'' structure is named ''Node''. On the other hand it puts static type control in good use. A similar macro may be defined for a backward iterator. In C++ language Exec lists iterators may be defined as templates.&lt;br /&gt;
&lt;br /&gt;
===Removing List Items From Inside of an Iterator===&lt;br /&gt;
&lt;br /&gt;
Some attention has to be put to a case when iterator is used for selective removal of items. Someone may try to do it as follows:&lt;br /&gt;
&lt;br /&gt;
 '''/* BAD CODE EXAMPLE */'''&lt;br /&gt;
 &lt;br /&gt;
 ForEachNode(n, MyNode, list)&lt;br /&gt;
 {&lt;br /&gt;
   if (/*some condition*/)&lt;br /&gt;
   {&lt;br /&gt;
     Remove((struct Node*)n);&lt;br /&gt;
     FreeVec(n);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Why the code above is buggy? If the item ''n'' is being removed and its memory freed, reference to ''n'' in the next loop turn is in fact a reference to free memory. In most cases the memory contents will stay unchanged. That is why such a bug is so popular, it may go unnoticed if the code is not tested enough. Nothing stops the process scheduler to switch our process out, then the memory may be allocated by another process and its contents overwritten. Then, when control will be returned to our process, ''n'' points to undefined data and the loop crashes. A solution of this problem is to read the successor from an item '''before''' the item is freed. It requires a second pointer to be defined:&lt;br /&gt;
&lt;br /&gt;
 struct MyNode *n, *n2;&lt;br /&gt;
 &lt;br /&gt;
 for (n = (struct MyNode*)list-&amp;gt;mlh_Head; n2 = (struct MyNode*)n-&amp;gt;Node.mln_Succ; n = n2)&lt;br /&gt;
 {&lt;br /&gt;
   if (/* some condition */)&lt;br /&gt;
   {&lt;br /&gt;
     Remove((struct Node*)n);&lt;br /&gt;
     FreeVec(n);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now a pointer to the successor of item ''n'' is stored in ''n2'' before the item ''n'' is freed. At the next loop turn, the iterator moves&lt;br /&gt;
to the next item and checks for the list end using valid ''n2'' pointer instead of a reference to free memory.&lt;br /&gt;
&lt;br /&gt;
Things are easier when all items on the list are to be removed unconditionally, so the list is made empty and all the items are disposed. Of course one can still use the safe loop above, but there is a bit faster alternative:&lt;br /&gt;
&lt;br /&gt;
 while (n = (struct MyNode*)RemHead((struct List*)list)) FreeVec(n);&lt;br /&gt;
&lt;br /&gt;
''RemTail()'' function may be used in this loop as well, because when one removes all the items, the order does not matter usually.&lt;br /&gt;
&lt;br /&gt;
=Adding and Removing Items=&lt;br /&gt;
Adding an item in arbitrary position of a list requires only updating 4 pointers, regardless of the item size. The diagram below explains the operation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Execlists5.png]]&amp;lt;br&amp;gt;&lt;br /&gt;
''Inserting an item into an Exec list.''&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The diagam corresponds to the following code:&lt;br /&gt;
&lt;br /&gt;
 struct MyNode *n;    /* insert after this item */&lt;br /&gt;
 struct MyNode *a;    /* insert this */&lt;br /&gt;
 &lt;br /&gt;
 n-&amp;gt;Node.mln_Succ-&amp;gt;mln_Pred = &amp;amp;a.Node;   /* 1 */&lt;br /&gt;
 a-&amp;gt;Node.mln_Succ = n-&amp;gt;Node.mln_Succ;    /* 2 */&lt;br /&gt;
 a-&amp;gt;Node.mln_Pred = &amp;amp;n.Node;             /* 3 */&lt;br /&gt;
 n-&amp;gt;Node.mln_Succ = &amp;amp;a.Node;             /* 4 */&lt;br /&gt;
&lt;br /&gt;
Observe the order of operations. It is important. If one starts from operation 4 for example,  he would loose the only link to the rest of the list after the insert position.&lt;br /&gt;
&lt;br /&gt;
Removing link is even faster, as it only requires modifying two pointers: one in the predecessor of removed item and one in its successor. Let's assume element ''n'' is to be removed:&lt;br /&gt;
&lt;br /&gt;
 n-&amp;gt;Node.mln_Pred-&amp;gt;mln_Succ = n-&amp;gt;Node.mln_Succ;&lt;br /&gt;
 n-&amp;gt;Node.mln_Succ-&amp;gt;mln_Pred = n-&amp;gt;Node.mln_Pred;&lt;br /&gt;
&lt;br /&gt;
Insert and remove operations have been standarizded in MorphOS in two ways: as ''exec.library'' API calls and as macros. The library functions are ''Insert()'' and ''Remove()'', their macro counterparts are named ''INSERT()'' and ''REMOVE()''. Both ''Insert()'' function and ''INSERT()'' macro take also a pointer to list header. While it is not neccesary in general case, it allows to handle the case when an item is inserted as the first one by passing ''NULL'' as the insert position. Inserting as the first element can be also done by passing the list header address as the insert position.&lt;br /&gt;
&lt;br /&gt;
It should be noted, that both ''Remove()'' function and ''REMOVE()'' macro '''do not verify''' if the removed node is really in any list. Any attempt to &amp;quot;remove&amp;quot; a node not being in a list may result in random memory trashing and horrible crash.&lt;br /&gt;
&lt;br /&gt;
==Head and Tail==&lt;br /&gt;
&lt;br /&gt;
The most common operations of inserting and removing elements are performed on both the ends of a list. For example common data structures like stack or queue may be implemented using list. For stack, items are added at the list head and also removed from the head. For queue items are added at the tail and removed at the head.&lt;br /&gt;
&lt;br /&gt;
Having a list head and tail pseudoitems gives an advantage, that operations at both list ends are not different than the general case. One just replaces &amp;amp;ndash; on the diagram in the previous subchapter &amp;amp;ndash; either the element before the insert position with the list head, or the element after the insert position with the list tail. The only difference comes from the fact that head and tail operations usually take just the address of the list header as their argument. The complete set of four operations is provided:&lt;br /&gt;
* ''AddHead()'' function and ''ADDHEAD()'' macro add a node as the first one.&lt;br /&gt;
* ''RemHead()'' function and ''REMHEAD()'' macro remove the first node and return its address.&lt;br /&gt;
* ''AddTail()'' function and ''ADDTAIL()'' macro add a node as the last one.&lt;br /&gt;
* ''RemTail()'' function and ''REMTAIL()'' macro remove the last node and return its address.&lt;br /&gt;
All these operations require only an address of the list header. Remove operations return the address of removed node, or ''NULL'' if the list is empty.&lt;br /&gt;
&lt;br /&gt;
==Functions or Macros?==&lt;br /&gt;
&lt;br /&gt;
After reading all the sections above it is clear, that most of the list operations is very simple and compiles to a few processor instructions. That is why they are also defined as macros. What to to use then? In general macros are faster, but some of them may be a few bytes longer than calls to library functions (especially ''INSERT()''). On the other hand even a few kilobytes of additional code is usually not a problem nowadays, while gain in speed is often valuable. Then in places where speed is critical, macros are a better choice.&lt;br /&gt;
&lt;br /&gt;
==Enqueueing==&lt;br /&gt;
&lt;br /&gt;
Full list nodes have a '''priority''' field, named ''ln_Pri''. The field is often used by the system to maintain prioritized lists or queues. To keep the list ordered by priority, a special insert operation is required. It is provided as an ''exec.library'' call named ''Enqueue()''. The function takes a node (it must be full ''Node'', not ''MinNode''), reads its priority and finds a place for insert comparing priorities of nodes. If there are any nodes in the list with the same priority as the inserted one, it is inserted '''before''' already existing ones. Of course ''Enqueue()'' may be used also for implementing custom queues. One has to take into account however that the priority field is limited to signed 8-bit number and the function does not scale well for very long lists, as the insert position search is linear.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Installation_of_Software_Development_Kit_and_its_basic_usage&amp;diff=1749</id>
		<title>Installation of Software Development Kit and its basic usage</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Installation_of_Software_Development_Kit_and_its_basic_usage&amp;diff=1749"/>
				<updated>2013-01-09T17:47:40Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Installing the SDK */ Note about Scribble in SDK 3.2 and later.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;small&amp;gt;This page in other languages: [[Instalacja SDK (Software Development Kit) i podstawy jego używania|polski]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Installing the SDK==&lt;br /&gt;
&lt;br /&gt;
The official MorphOS SDK provides a complete environment for creating programs&lt;br /&gt;
for MorphOS. It contains the following components:&lt;br /&gt;
&lt;br /&gt;
* MorphOS includes (for the MorphOS native API).&lt;br /&gt;
* Standard C and C++ library includes.&lt;br /&gt;
* MorphOS API documentation and example code.&lt;br /&gt;
* Two GCC compilers, 2.95.3 and 4.4.5.&lt;br /&gt;
* GCC toolchains (one for each compiler), sets of developer utility programs.&lt;br /&gt;
* ''Scribble'', an advanced programmer's editor with syntax highlighting and powerful autocomplete and code analyser/hinter feature (starting from SDK 3.2 ''Scribble'' has been moved to the base system).&lt;br /&gt;
* Perl scripting language (used by some SDK tools).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The first step of installation is to download the SDK archive from the [http://www.morphos.net morphos.net] site, or by clicking this [http://www.morphos-team.net/files/sdk-20110916.lha direct link]. The SDK is delivered as a LhA archive, which must be depacked before proceeding. The easiest way is to open a context menu for the archive (with the right mouse button in an Ambient window) and choose ''Extract''. After depacking a directory named ''morphossdk'' is created with an ''Installer'' application and a big file named ''sdk.pack'' inside. Installation is started by running ''Installer''. The only user choice that is needed here is to choose an installation directory. Then there is some time spent watching the progress bar...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After the installation a system reboot may be needed to update system assigns and paths.&lt;br /&gt;
&lt;br /&gt;
==Choosing a Compiler==&lt;br /&gt;
&lt;br /&gt;
As mentioned above, the SDK delivers two GCC compilers: an old but trusty 2.95.3 one, and the modern 4.4.5. There is a tool named ''GCCSelect'' in the SDK, which allows for fast switching between compilers. Just type in a shell window&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;GCCSelect 2.95.3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;GCCSelect 4.4.5&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to change the current compiler. ''GCCSelect'' works by making symbolic links to the proper version of GCC and its tools, so the compiler is always called as ''gcc'' or ''g++'', regardless of the version chosen currently.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Which one to choose? It depends on the code compiled and other constrains. Here is some guidance:&lt;br /&gt;
&lt;br /&gt;
* 2.95.3 compiles faster and consumes less memory.&lt;br /&gt;
* For old code 2.95.3 would be better, as GCC 4 will produce tons of warnings or even errors on code being flawlessly compiled by the old GCC.&lt;br /&gt;
* For new projects, especially written in C++, GCC 4 is recommended, as the old one simply does not keep up with modern standards.&lt;br /&gt;
* GCC 4 usually produces faster code (but sometimes also bigger, depending on optimizer options).&lt;br /&gt;
* GCC 4 is a relatively new and complex compiler, may contain more bugs than 2.95.3.&lt;br /&gt;
&lt;br /&gt;
My general advice is to use GCC 4 and only switch to GCC 2 if needed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
One can check which compiler is currently active using the '''&amp;amp;minus;v''' compiler option, which displays the compiler version and build options:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;gcc -v&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line of output shows the GCC version.&lt;br /&gt;
&lt;br /&gt;
==Standard C and C++ Libraries==&lt;br /&gt;
&lt;br /&gt;
These standard libraries are parts of the C and C++ language specifications respectively. They mainly deliver file and console input/output functions, mathematic functions and string operations. The C++ library also provides a set of basic container classes.&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/C_standard_library C standard library on Wikipedia]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/C%2B%2B_Standard_Library C++ standard library on Wikipedia]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are two ways to access these libraries on MorphOS. The first (and default) one is by using a MorphOS [[MorphOS_API_and_Its_Organization|shared library]]; ''ixemul.library''. As the name suggests, this library tries to provide some Unix environment emulation on MorphOS, which, other than the standard libraries, includes large part of [http://en.wikipedia.org/wiki/Posix POSIX] standard and some other commonly used functions. ''ixemul.library'' is usually used for porting big projects from the Unix/Linux world, for example it is used by GCC itself and many other tools in the SDK.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The second way is to use ''libnix'' (as in; '''''lib''' '''n'''o '''ix'''emul''). In contrast to ''ixemul.library'', ''libnix'' is statically linked with the application. This is the preferred way for providing standard libraries for MorphOS native applications. It is achieved by passing the '''&amp;amp;minus;noixemul''' flag to the compiler and the linker. ''libnix'' delivers full C and C++ standard libraries, but its POSIX implementation is less complete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Another alternative is to not use standard libraries at all. It may sound crazy at first, but the MorphOS native API provides complete file and console I/O as well as some string manipulation functions and many mathematic functions. Using the native API makes applications faster and smaller in size. On the other hand code using the MorphOS API directly is not portable to non-Amiga(like) systems. A '''&amp;amp;minus;nostdlib''' compiler option instructs the compiler to not link the code with the standard library. Note that this requires also writing your own [[Writing Custom Startup Code|custom startup code]].&amp;lt;/small&amp;gt;&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Installation_of_Software_Development_Kit_and_its_basic_usage&amp;diff=1748</id>
		<title>Installation of Software Development Kit and its basic usage</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Installation_of_Software_Development_Kit_and_its_basic_usage&amp;diff=1748"/>
				<updated>2013-01-09T17:46:09Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Standard C and C++ Libraries */ Linked to &amp;quot;Writing Custom Startup Code&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;small&amp;gt;This page in other languages: [[Instalacja SDK (Software Development Kit) i podstawy jego używania|polski]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Installing the SDK==&lt;br /&gt;
&lt;br /&gt;
The official MorphOS SDK provides a complete environment for creating programs&lt;br /&gt;
for MorphOS. It contains the following components:&lt;br /&gt;
&lt;br /&gt;
* MorphOS includes (for the MorphOS native API).&lt;br /&gt;
* Standard C and C++ library includes.&lt;br /&gt;
* MorphOS API documentation and example code.&lt;br /&gt;
* Two GCC compilers, 2.95.3 and 4.4.5.&lt;br /&gt;
* GCC toolchains (one for each compiler), sets of developer utility programs.&lt;br /&gt;
* ''Scribble'', an advanced programmer's editor with syntax highlighting and powerful autocomplete and code analyser/hinter feature.&lt;br /&gt;
* Perl scripting language (used by some SDK tools).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The first step of installation is to download the SDK archive from the [http://www.morphos.net morphos.net] site, or by clicking this [http://www.morphos-team.net/files/sdk-20110916.lha direct link]. The SDK is delivered as a LhA archive, which must be depacked before proceeding. The easiest way is to open a context menu for the archive (with the right mouse button in an Ambient window) and choose ''Extract''. After depacking a directory named ''morphossdk'' is created with an ''Installer'' application and a big file named ''sdk.pack'' inside. Installation is started by running ''Installer''. The only user choice that is needed here is to choose an installation directory. Then there is some time spent watching the progress bar...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After the installation a system reboot may be needed to update system assigns and paths.&lt;br /&gt;
&lt;br /&gt;
==Choosing a Compiler==&lt;br /&gt;
&lt;br /&gt;
As mentioned above, the SDK delivers two GCC compilers: an old but trusty 2.95.3 one, and the modern 4.4.5. There is a tool named ''GCCSelect'' in the SDK, which allows for fast switching between compilers. Just type in a shell window&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;GCCSelect 2.95.3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;GCCSelect 4.4.5&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to change the current compiler. ''GCCSelect'' works by making symbolic links to the proper version of GCC and its tools, so the compiler is always called as ''gcc'' or ''g++'', regardless of the version chosen currently.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Which one to choose? It depends on the code compiled and other constrains. Here is some guidance:&lt;br /&gt;
&lt;br /&gt;
* 2.95.3 compiles faster and consumes less memory.&lt;br /&gt;
* For old code 2.95.3 would be better, as GCC 4 will produce tons of warnings or even errors on code being flawlessly compiled by the old GCC.&lt;br /&gt;
* For new projects, especially written in C++, GCC 4 is recommended, as the old one simply does not keep up with modern standards.&lt;br /&gt;
* GCC 4 usually produces faster code (but sometimes also bigger, depending on optimizer options).&lt;br /&gt;
* GCC 4 is a relatively new and complex compiler, may contain more bugs than 2.95.3.&lt;br /&gt;
&lt;br /&gt;
My general advice is to use GCC 4 and only switch to GCC 2 if needed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
One can check which compiler is currently active using the '''&amp;amp;minus;v''' compiler option, which displays the compiler version and build options:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;gcc -v&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line of output shows the GCC version.&lt;br /&gt;
&lt;br /&gt;
==Standard C and C++ Libraries==&lt;br /&gt;
&lt;br /&gt;
These standard libraries are parts of the C and C++ language specifications respectively. They mainly deliver file and console input/output functions, mathematic functions and string operations. The C++ library also provides a set of basic container classes.&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/C_standard_library C standard library on Wikipedia]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/C%2B%2B_Standard_Library C++ standard library on Wikipedia]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are two ways to access these libraries on MorphOS. The first (and default) one is by using a MorphOS [[MorphOS_API_and_Its_Organization|shared library]]; ''ixemul.library''. As the name suggests, this library tries to provide some Unix environment emulation on MorphOS, which, other than the standard libraries, includes large part of [http://en.wikipedia.org/wiki/Posix POSIX] standard and some other commonly used functions. ''ixemul.library'' is usually used for porting big projects from the Unix/Linux world, for example it is used by GCC itself and many other tools in the SDK.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The second way is to use ''libnix'' (as in; '''''lib''' '''n'''o '''ix'''emul''). In contrast to ''ixemul.library'', ''libnix'' is statically linked with the application. This is the preferred way for providing standard libraries for MorphOS native applications. It is achieved by passing the '''&amp;amp;minus;noixemul''' flag to the compiler and the linker. ''libnix'' delivers full C and C++ standard libraries, but its POSIX implementation is less complete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Another alternative is to not use standard libraries at all. It may sound crazy at first, but the MorphOS native API provides complete file and console I/O as well as some string manipulation functions and many mathematic functions. Using the native API makes applications faster and smaller in size. On the other hand code using the MorphOS API directly is not portable to non-Amiga(like) systems. A '''&amp;amp;minus;nostdlib''' compiler option instructs the compiler to not link the code with the standard library. Note that this requires also writing your own [[Writing Custom Startup Code|custom startup code]].&amp;lt;/small&amp;gt;&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1747</id>
		<title>Writing Custom Startup Code</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1747"/>
				<updated>2012-12-29T15:43:34Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Reasons for Writing Own Startup */ small bug&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
One can find in every C programming handboook, that program execution starts from ''main()'' function. In fact we have such an impression, when we write a program. There is no evidence to disprove it. In fact however, this is not true. There are at least a few, and sometimes even a few teens of kilobytes of code between the start of program execution and the first line of ''main()''. Most of this code is not really needed in most cases.&lt;br /&gt;
&lt;br /&gt;
What is being done by this code? Let's say for the start, it is perfectly possible to have a program without any startup code at all. The system can jump into ''main()'' right away. Unfortunately such a program would run only from commandline window. It would crash, when started from Ambient. It is because Ambient sends a special message to a message port of a freshly created process. This message serves two purposes. Firstly, it contains Ambient launch parameters, namely program icon descriptor and optionally descriptors of other icons, which have been shift-clicked, or dropped onto a panel. Secondly, a reply for the message is a signal for Ambient that the program finished its execution. Sending a reply is obligatory. This is the minimal set of things to be done by startup code. In practice it also should open required shared libraries. When one wants to use the C standard library, either with ''libnix'' or ''ixemul.library'', the startup code also creates a &amp;quot;standard environment&amp;quot; for the C standard library and POSIX functions ([[Installation of Software Development Kit and its basic usage#Standard C and C++ Libraries|more on this]]). Because of this, startup code linked when using one of these libraries is quite complex, so also long.&lt;br /&gt;
&lt;br /&gt;
=Reasons for Writing Own Startup=&lt;br /&gt;
&lt;br /&gt;
The main advantage of an own startup is its shortness. Reducing program startup time is negligible. Very short startup is good for very short programs (for example shell commands), a few kB in size. In this case the standard startup may be easily longer than the program code itself. One can also use own startup just for satisfaction of making the program shorter by those few kilobytes. Custom startup code cannot be used, when the program uses ''ixemul.library''. When the program is linked with ''libnix'', the possibility of using own startup depends on the standard C library functions used. Most of them do not need any preparations and will work with any startup. Some more complex functions however require constructors to be executed in startup. If we use such functions, we will get linker errors of unresolved symbols. In such a case there is a simple choice &amp;amp;ndash; one either must replace these functions with something else, or just use the standard startup code. Own startup is then useful mostly when standard C library is not used at all (in favour of the native MorphOS API), or only simple functions from it are used.&lt;br /&gt;
&lt;br /&gt;
If we are still determined to use own startup, it is the time to tell the compiler about it. Skipping standard startup is done with '''&amp;amp;minus;nostartfiles''' argument. Then when we try to use our startup with ''libnix'', we use '''&amp;amp;minus;nostartfiles''' together with '''&amp;amp;minus;noixemul'''. Programmers wanting to go the pure MorphOS API way (without the C library), should use '''&amp;amp;minus;nostdlib''' option, which also implies '''&amp;amp;minus;nostartfiles'''.&lt;br /&gt;
&lt;br /&gt;
=Let's Write It=&lt;br /&gt;
&lt;br /&gt;
Before we start to write the code, note that except things executed before calling the ''main()'' function, some code must be also called '''after''' it returns. Then we also have &amp;quot;cleanup code&amp;quot;. As this code is usually placed in the same function (the one that calls ''main()''), both the parts are commonly called just startup code.&lt;br /&gt;
&lt;br /&gt;
As mentioned before, program execution does not really start from the ''main()'' function. Where does it start then? When an ELF executable is loaded from disk, a section named &amp;quot;.text&amp;quot; is found and operating system jumps to the start of its contents. When a program is written in C, it means start of the first function in code, as in C there is no way to write code outside of a function. It must be noted, that C compiler may reorder functions in a single object file. The GCC 2.95.3 compiler never does it, but aggressive optimizer of GCC 4 can change order of functions. Fortunately it is done only inside a single source file. To make sure that our startup function will be the first, it must be placed in a separate file. Then resulting object file must be linked as the first one, as linking order is always preserved. After this important note it is time for the code:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;amp;lt;proto/exec.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;proto/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;workbench/startup.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
The thing starts with including needed header files. We will need two basic system libraries: ''exec.library'' and ''dos.library''. It explains why standard startup code, be it ''libnix'' or ''ixemul.library'', opens these two libraries &amp;amp;ndash; it simply needs them for itself.&lt;br /&gt;
&lt;br /&gt;
 struct Library *SysBase;&lt;br /&gt;
 struct Library *DOSBase;&lt;br /&gt;
&lt;br /&gt;
As our code will use these two libaries, we need to define their bases.&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(struct WBStartup *wbmessage);&lt;br /&gt;
&lt;br /&gt;
This is a declaration of the main function of our program. As the object file containing startup code should contain only one function (the entry one), the rest of code has to be moved to other object files, for reasons explained above. That is why the main function has to be declared here, as we call it from the startup code. Alternatively its declaration may be placed in some header file and included here. The name ''Main()'' is arbitrary, it can be anything. I've just called it typically, capitalizing the first letter to avoid possible name confilct with the standard library. The argument of ''Main()'' is startup message (mentioned above) being sent by Ambient. If we do not plan to use it inside ''Main()'', we can just declare it this way:&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(void);&lt;br /&gt;
&lt;br /&gt;
The next important thing is to define a mysterious global symbol ''__abox__''.&lt;br /&gt;
&lt;br /&gt;
 ULONG __abox__ = 1;&lt;br /&gt;
&lt;br /&gt;
While not needed in the code, this symbol is used by the system executable loader to differentiate between MorphOS ELF executables and other possible PowerPC ELF binaries. If there is no ''__abox__'' defined, the executable will be recognized as PowerUP one and executed through ''ppc.library'', with unpredictable results.&lt;br /&gt;
&lt;br /&gt;
 ULONG Start(void)&lt;br /&gt;
 {&lt;br /&gt;
   struct Process *myproc = 0;&lt;br /&gt;
   struct Message *wbmessage = 0;&lt;br /&gt;
   BOOL have_shell = FALSE; &lt;br /&gt;
   ULONG return_code = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
''Start()'' is the code entry point. Again, name of this function is not important, it may be anything. It just has to be the first function in the linked executable. Some local variables are declared here, which will be needed later. ''myproc'' will contain a pointer to our process, ''wbmessage'' will hold the Ambient startup message pointer. Variable ''have_shell'' will be used to detect if the program has been started from shell console or from Ambient. Finally ''return_code'' is just the return code of the program, it will be returned to the system. The return value is usually 0 when the program executed succesfully and ''RETURN_OK'' constant is just 0.&lt;br /&gt;
&lt;br /&gt;
   SysBase = *(struct Library**)4L;&lt;br /&gt;
&lt;br /&gt;
Time for initialization of the ''SysBase'', the base of ''exec.library''. The library is always open. For historical and backward compatibility reasons the base pointer is always placed by the system at address $00000004, so we just take it from there. Having ''exec.library'' available, our code can check whether it has been started from shell or from Ambient:&lt;br /&gt;
&lt;br /&gt;
   myproc = (struct Process*)FindTask(0);&lt;br /&gt;
   if (myproc-&amp;gt;pr_CLI) have_shell = TRUE;&lt;br /&gt;
&lt;br /&gt;
This information is taken from the ''Process'' structure being just system process descriptor. The ''exec.library'' call ''FindTask()'' returns the calling task's own descriptor if 0 is passed as its argument. In case we are started from Ambient, receiving its message is compulsory:&lt;br /&gt;
&lt;br /&gt;
   if (!have_shell)&lt;br /&gt;
   {&lt;br /&gt;
     WaitPort(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
     wbmessage = GetMsg(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The startup message is being sent to process system port, so we receive it there. The message may be then passed to our ''Main()'' function, if we plan to make some use of it, like handling additional icon arguments.&lt;br /&gt;
&lt;br /&gt;
   if (DOSBase = OpenLibrary((STRPTR)&amp;quot;dos.library&amp;quot;, 0))&lt;br /&gt;
   {&lt;br /&gt;
&lt;br /&gt;
The next step is opening ''dos.library'', this library is opened in a pretty standard way. In fact this minimal startup code does not need it. There are two reasons to open it anyway. First, it is hard to imagine a program, which does not need ''dos.library'' &amp;amp;ndash; even &amp;quot;Hello world!&amp;quot; needs it. Secondly, all standard startup codes open it, so usually main code takes it for granted. Then my startup behaves conventionally and opens ''dos.library'' as well.&lt;br /&gt;
&lt;br /&gt;
     return_code = Main((struct WBStartup*)wbmessage);&lt;br /&gt;
&lt;br /&gt;
Yes, after these few lines we are ready to call the main code. As stated above, passing the startup message from Ambient is optional. On the other hand, receiving the result and passing it back to the system later is obligatory.&lt;br /&gt;
&lt;br /&gt;
     CloseLibrary(DOSBase);&lt;br /&gt;
   }&lt;br /&gt;
   else return_code = RETURN_FAIL;&lt;br /&gt;
&lt;br /&gt;
From this point the startup code becomes cleanup one. Note also that proper error handling must be done. ''dos.library'' is being closed, but if its opening failed before, the result of execution is changed to ''RETURN_FAIL''. This is the hardest fail and means total inability to execute. In practice MorphOS can't boot if ''dos.library'' is not present in the system. But ''OpenLibrary()'' may fail for other reasons, for example simple lack of free memory. Then the startup code has to handle it in some reasonable way.&lt;br /&gt;
&lt;br /&gt;
   if (wbmessage)&lt;br /&gt;
   {&lt;br /&gt;
     Forbid();&lt;br /&gt;
     ReplyMsg(wbmessage);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This snippet of code handles the Ambient startup message. Even if we make no use of it, it '''must''' be replied at exit. But what does ''Forbid()'' do here? This function halts system multitasking, specifically it prevents the system process scheduler to switch our process away. Usually it may be done for a very short period of time only and followed by a matching ''Permit()''. At the first glance this code makes no sense then, a process stops process switching and... exits. We have to know one important thing however: process switching is automatically reenabled when the process which called ''Forbid()'' ends. Then here is what happens:&lt;br /&gt;
* Our task calls ''Forbid()'', so no other process can interrupt it.&lt;br /&gt;
* It replies the Ambient startup message. As multitasking is stopped, Ambient is unable to receive yet. The message just waits at its message port.&lt;br /&gt;
* Our task exits. Then the system restores multitasking.&lt;br /&gt;
* Ambient gets CPU time and receives the message. Note that at this point it is absolutely certain, that our task does not exist anymore. Possibility of a race condition is eliminated. Without ''Forbid()'' it could be possible that our process is removed from the system while it still executes.&lt;br /&gt;
Of course multitasking halt period is extremely short, because our cleanup code ends immediately after replying to Ambient:&lt;br /&gt;
&lt;br /&gt;
   return return_code;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=$VER: &amp;amp;ndash; program identification string=&lt;br /&gt;
&lt;br /&gt;
This topic is not strictly related to startup code, but the version string is usually placed in it, so I've decided to write a few words about it. The version string is a short text in some defined format. This string contains the program name, version and revision number, compilation date and optionally copyrigth or author info. The version string is decoded by many applications including Ambient, the system command ''version'', the Installer program and more. The text starts with '''$VER:''', so it can be easily found in the program executable. As version tools search for the version string from the start of the executable file, it is best if version string is placed as close to the beginning of the file as possible. If the version string is declared as a simple string constant, it is unfortunately placed in one of the ELF data sections. These sections are placed after the code section by the linker. However we can force the version string to be placed in the code section:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;#95;_attribute__ ((section(&amp;quot;.text&amp;quot;))) UBYTE VString[] =&lt;br /&gt;
   &amp;quot;$VER: program 1.0 (21.6.2011) &amp;amp;copy; 2011 morphos.pl\r\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Using a GCC specific extension ''__attribute__'' we can push the string into the ELF section named ''.text'', which is the code section. As the startup code object is linked as the first object, the version string will appear at the beginning of the executable, just after the code of the ''Start()'' function. Why after? It is simple, if we place it before the real code, the operating system will jump &amp;quot;into&amp;quot; the string, trying to execute it, and then of course it will crash.&lt;br /&gt;
&lt;br /&gt;
=A Complete Example=&lt;br /&gt;
&lt;br /&gt;
A complete &amp;quot;Hello world!&amp;quot; [http://krashan.ppa.pl/mph/files/helloworld.lha example] with custom startup code shows the described ideas at work. It only uses the MorphOS API, so is compiled with '''&amp;amp;minus;nostdlib''' option. Executable size is 1&amp;amp;nbsp;592 bytes. For comparision, ''libnix'' startup and ''printf()'' gives 30&amp;amp;nbsp;964 bytes, when one replaces ''printf()'' with MorphOS ''Printf()'' from ''dos.library'' it is still 13&amp;amp;nbsp;500 bytes.&lt;br /&gt;
&lt;br /&gt;
As the project consists of two *.c files, a simple makefile is added to it. Example may be compiled just by entering ''make'' in a console.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1746</id>
		<title>Writing Custom Startup Code</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1746"/>
				<updated>2012-12-29T13:48:58Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Let's Write It */ __abox__ proper explanation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
One can find in every C programming handboook, that program execution starts from ''main()'' function. In fact we have such an impression, when we write a program. There is no evidence to disprove it. In fact however, this is not true. There are at least a few, and sometimes even a few teens of kilobytes of code between the start of program execution and the first line of ''main()''. Most of this code is not really needed in most cases.&lt;br /&gt;
&lt;br /&gt;
What is being done by this code? Let's say for the start, it is perfectly possible to have a program without any startup code at all. The system can jump into ''main()'' right away. Unfortunately such a program would run only from commandline window. It would crash, when started from Ambient. It is because Ambient sends a special message to a message port of a freshly created process. This message serves two purposes. Firstly, it contains Ambient launch parameters, namely program icon descriptor and optionally descriptors of other icons, which have been shift-clicked, or dropped onto a panel. Secondly, a reply for the message is a signal for Ambient that the program finished its execution. Sending a reply is obligatory. This is the minimal set of things to be done by startup code. In practice it also should open required shared libraries. When one wants to use the C standard library, either with ''libnix'' or ''ixemul.library'', the startup code also creates a &amp;quot;standard environment&amp;quot; for the C standard library and POSIX functions ([[Installation of Software Development Kit and its basic usage#Standard C and C++ Libraries|more on this]]). Because of this, startup code linked when using one of these libraries is quite complex, so also long.&lt;br /&gt;
&lt;br /&gt;
=Reasons for Writing Own Startup=&lt;br /&gt;
&lt;br /&gt;
The main advantage of an own startup is its shortness. Reducing program startup time is negligible. Very short startup is good for very short programs (for example shell commands), a few kB in size. In this case the standard startup may be easily longer than the program code itself. One can also use own startup just for satisfaction of making the program shorter by those few kilobytes. Custom startup code cannot be used, when the program uses ''ixemul.library''. When the program is linked with ''libnix'', the possibility of using own startup depends on the standard C library functions used. Most of them do not need any preparations and will work with any startup. Some more complex functions however require constructors to be executed in startup. If we use such functions, we will get linker errors of unresolved symbols. In such a case there is a simple choice &amp;amp;ndash; one either must replace these functions with something else, or just use the standard startup code. Own startup is then useful mostly when standard C library is not used at all (in favour of the native MorphOS API), or only simple functions from it are used.&lt;br /&gt;
&lt;br /&gt;
If we are still determined to use own startup, it is the time to tell the compiler about it. Skipping standard startup is done with '''&amp;amp;minus;nostartfiles''' argument. Then when we try to use our startup with ''libnix'', we use '''&amp;amp;minus;nostartfiles''' together with '''&amp;amp;minus;noixemul'''. Programmers wanting to go the pure MorphOS API way (without the C library), should use '''&amp;amp;minus;nostdlib''' option, which also implies '''&amp;amp;minus;nostdlib'''.&lt;br /&gt;
&lt;br /&gt;
=Let's Write It=&lt;br /&gt;
&lt;br /&gt;
Before we start to write the code, note that except things executed before calling the ''main()'' function, some code must be also called '''after''' it returns. Then we also have &amp;quot;cleanup code&amp;quot;. As this code is usually placed in the same function (the one that calls ''main()''), both the parts are commonly called just startup code.&lt;br /&gt;
&lt;br /&gt;
As mentioned before, program execution does not really start from the ''main()'' function. Where does it start then? When an ELF executable is loaded from disk, a section named &amp;quot;.text&amp;quot; is found and operating system jumps to the start of its contents. When a program is written in C, it means start of the first function in code, as in C there is no way to write code outside of a function. It must be noted, that C compiler may reorder functions in a single object file. The GCC 2.95.3 compiler never does it, but aggressive optimizer of GCC 4 can change order of functions. Fortunately it is done only inside a single source file. To make sure that our startup function will be the first, it must be placed in a separate file. Then resulting object file must be linked as the first one, as linking order is always preserved. After this important note it is time for the code:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;amp;lt;proto/exec.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;proto/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;workbench/startup.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
The thing starts with including needed header files. We will need two basic system libraries: ''exec.library'' and ''dos.library''. It explains why standard startup code, be it ''libnix'' or ''ixemul.library'', opens these two libraries &amp;amp;ndash; it simply needs them for itself.&lt;br /&gt;
&lt;br /&gt;
 struct Library *SysBase;&lt;br /&gt;
 struct Library *DOSBase;&lt;br /&gt;
&lt;br /&gt;
As our code will use these two libaries, we need to define their bases.&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(struct WBStartup *wbmessage);&lt;br /&gt;
&lt;br /&gt;
This is a declaration of the main function of our program. As the object file containing startup code should contain only one function (the entry one), the rest of code has to be moved to other object files, for reasons explained above. That is why the main function has to be declared here, as we call it from the startup code. Alternatively its declaration may be placed in some header file and included here. The name ''Main()'' is arbitrary, it can be anything. I've just called it typically, capitalizing the first letter to avoid possible name confilct with the standard library. The argument of ''Main()'' is startup message (mentioned above) being sent by Ambient. If we do not plan to use it inside ''Main()'', we can just declare it this way:&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(void);&lt;br /&gt;
&lt;br /&gt;
The next important thing is to define a mysterious global symbol ''__abox__''.&lt;br /&gt;
&lt;br /&gt;
 ULONG __abox__ = 1;&lt;br /&gt;
&lt;br /&gt;
While not needed in the code, this symbol is used by the system executable loader to differentiate between MorphOS ELF executables and other possible PowerPC ELF binaries. If there is no ''__abox__'' defined, the executable will be recognized as PowerUP one and executed through ''ppc.library'', with unpredictable results.&lt;br /&gt;
&lt;br /&gt;
 ULONG Start(void)&lt;br /&gt;
 {&lt;br /&gt;
   struct Process *myproc = 0;&lt;br /&gt;
   struct Message *wbmessage = 0;&lt;br /&gt;
   BOOL have_shell = FALSE; &lt;br /&gt;
   ULONG return_code = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
''Start()'' is the code entry point. Again, name of this function is not important, it may be anything. It just has to be the first function in the linked executable. Some local variables are declared here, which will be needed later. ''myproc'' will contain a pointer to our process, ''wbmessage'' will hold the Ambient startup message pointer. Variable ''have_shell'' will be used to detect if the program has been started from shell console or from Ambient. Finally ''return_code'' is just the return code of the program, it will be returned to the system. The return value is usually 0 when the program executed succesfully and ''RETURN_OK'' constant is just 0.&lt;br /&gt;
&lt;br /&gt;
   SysBase = *(struct Library**)4L;&lt;br /&gt;
&lt;br /&gt;
Time for initialization of the ''SysBase'', the base of ''exec.library''. The library is always open. For historical and backward compatibility reasons the base pointer is always placed by the system at address $00000004, so we just take it from there. Having ''exec.library'' available, our code can check whether it has been started from shell or from Ambient:&lt;br /&gt;
&lt;br /&gt;
   myproc = (struct Process*)FindTask(0);&lt;br /&gt;
   if (myproc-&amp;gt;pr_CLI) have_shell = TRUE;&lt;br /&gt;
&lt;br /&gt;
This information is taken from the ''Process'' structure being just system process descriptor. The ''exec.library'' call ''FindTask()'' returns the calling task's own descriptor if 0 is passed as its argument. In case we are started from Ambient, receiving its message is compulsory:&lt;br /&gt;
&lt;br /&gt;
   if (!have_shell)&lt;br /&gt;
   {&lt;br /&gt;
     WaitPort(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
     wbmessage = GetMsg(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The startup message is being sent to process system port, so we receive it there. The message may be then passed to our ''Main()'' function, if we plan to make some use of it, like handling additional icon arguments.&lt;br /&gt;
&lt;br /&gt;
   if (DOSBase = OpenLibrary((STRPTR)&amp;quot;dos.library&amp;quot;, 0))&lt;br /&gt;
   {&lt;br /&gt;
&lt;br /&gt;
The next step is opening ''dos.library'', this library is opened in a pretty standard way. In fact this minimal startup code does not need it. There are two reasons to open it anyway. First, it is hard to imagine a program, which does not need ''dos.library'' &amp;amp;ndash; even &amp;quot;Hello world!&amp;quot; needs it. Secondly, all standard startup codes open it, so usually main code takes it for granted. Then my startup behaves conventionally and opens ''dos.library'' as well.&lt;br /&gt;
&lt;br /&gt;
     return_code = Main((struct WBStartup*)wbmessage);&lt;br /&gt;
&lt;br /&gt;
Yes, after these few lines we are ready to call the main code. As stated above, passing the startup message from Ambient is optional. On the other hand, receiving the result and passing it back to the system later is obligatory.&lt;br /&gt;
&lt;br /&gt;
     CloseLibrary(DOSBase);&lt;br /&gt;
   }&lt;br /&gt;
   else return_code = RETURN_FAIL;&lt;br /&gt;
&lt;br /&gt;
From this point the startup code becomes cleanup one. Note also that proper error handling must be done. ''dos.library'' is being closed, but if its opening failed before, the result of execution is changed to ''RETURN_FAIL''. This is the hardest fail and means total inability to execute. In practice MorphOS can't boot if ''dos.library'' is not present in the system. But ''OpenLibrary()'' may fail for other reasons, for example simple lack of free memory. Then the startup code has to handle it in some reasonable way.&lt;br /&gt;
&lt;br /&gt;
   if (wbmessage)&lt;br /&gt;
   {&lt;br /&gt;
     Forbid();&lt;br /&gt;
     ReplyMsg(wbmessage);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This snippet of code handles the Ambient startup message. Even if we make no use of it, it '''must''' be replied at exit. But what does ''Forbid()'' do here? This function halts system multitasking, specifically it prevents the system process scheduler to switch our process away. Usually it may be done for a very short period of time only and followed by a matching ''Permit()''. At the first glance this code makes no sense then, a process stops process switching and... exits. We have to know one important thing however: process switching is automatically reenabled when the process which called ''Forbid()'' ends. Then here is what happens:&lt;br /&gt;
* Our task calls ''Forbid()'', so no other process can interrupt it.&lt;br /&gt;
* It replies the Ambient startup message. As multitasking is stopped, Ambient is unable to receive yet. The message just waits at its message port.&lt;br /&gt;
* Our task exits. Then the system restores multitasking.&lt;br /&gt;
* Ambient gets CPU time and receives the message. Note that at this point it is absolutely certain, that our task does not exist anymore. Possibility of a race condition is eliminated. Without ''Forbid()'' it could be possible that our process is removed from the system while it still executes.&lt;br /&gt;
Of course multitasking halt period is extremely short, because our cleanup code ends immediately after replying to Ambient:&lt;br /&gt;
&lt;br /&gt;
   return return_code;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=$VER: &amp;amp;ndash; program identification string=&lt;br /&gt;
&lt;br /&gt;
This topic is not strictly related to startup code, but the version string is usually placed in it, so I've decided to write a few words about it. The version string is a short text in some defined format. This string contains the program name, version and revision number, compilation date and optionally copyrigth or author info. The version string is decoded by many applications including Ambient, the system command ''version'', the Installer program and more. The text starts with '''$VER:''', so it can be easily found in the program executable. As version tools search for the version string from the start of the executable file, it is best if version string is placed as close to the beginning of the file as possible. If the version string is declared as a simple string constant, it is unfortunately placed in one of the ELF data sections. These sections are placed after the code section by the linker. However we can force the version string to be placed in the code section:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;#95;_attribute__ ((section(&amp;quot;.text&amp;quot;))) UBYTE VString[] =&lt;br /&gt;
   &amp;quot;$VER: program 1.0 (21.6.2011) &amp;amp;copy; 2011 morphos.pl\r\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Using a GCC specific extension ''__attribute__'' we can push the string into the ELF section named ''.text'', which is the code section. As the startup code object is linked as the first object, the version string will appear at the beginning of the executable, just after the code of the ''Start()'' function. Why after? It is simple, if we place it before the real code, the operating system will jump &amp;quot;into&amp;quot; the string, trying to execute it, and then of course it will crash.&lt;br /&gt;
&lt;br /&gt;
=A Complete Example=&lt;br /&gt;
&lt;br /&gt;
A complete &amp;quot;Hello world!&amp;quot; [http://krashan.ppa.pl/mph/files/helloworld.lha example] with custom startup code shows the described ideas at work. It only uses the MorphOS API, so is compiled with '''&amp;amp;minus;nostdlib''' option. Executable size is 1&amp;amp;nbsp;592 bytes. For comparision, ''libnix'' startup and ''printf()'' gives 30&amp;amp;nbsp;964 bytes, when one replaces ''printf()'' with MorphOS ''Printf()'' from ''dos.library'' it is still 13&amp;amp;nbsp;500 bytes.&lt;br /&gt;
&lt;br /&gt;
As the project consists of two *.c files, a simple makefile is added to it. Example may be compiled just by entering ''make'' in a console.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1745</id>
		<title>Writing Custom Startup Code</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1745"/>
				<updated>2012-12-29T13:39:24Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: even more fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
One can find in every C programming handboook, that program execution starts from ''main()'' function. In fact we have such an impression, when we write a program. There is no evidence to disprove it. In fact however, this is not true. There are at least a few, and sometimes even a few teens of kilobytes of code between the start of program execution and the first line of ''main()''. Most of this code is not really needed in most cases.&lt;br /&gt;
&lt;br /&gt;
What is being done by this code? Let's say for the start, it is perfectly possible to have a program without any startup code at all. The system can jump into ''main()'' right away. Unfortunately such a program would run only from commandline window. It would crash, when started from Ambient. It is because Ambient sends a special message to a message port of a freshly created process. This message serves two purposes. Firstly, it contains Ambient launch parameters, namely program icon descriptor and optionally descriptors of other icons, which have been shift-clicked, or dropped onto a panel. Secondly, a reply for the message is a signal for Ambient that the program finished its execution. Sending a reply is obligatory. This is the minimal set of things to be done by startup code. In practice it also should open required shared libraries. When one wants to use the C standard library, either with ''libnix'' or ''ixemul.library'', the startup code also creates a &amp;quot;standard environment&amp;quot; for the C standard library and POSIX functions ([[Installation of Software Development Kit and its basic usage#Standard C and C++ Libraries|more on this]]). Because of this, startup code linked when using one of these libraries is quite complex, so also long.&lt;br /&gt;
&lt;br /&gt;
=Reasons for Writing Own Startup=&lt;br /&gt;
&lt;br /&gt;
The main advantage of an own startup is its shortness. Reducing program startup time is negligible. Very short startup is good for very short programs (for example shell commands), a few kB in size. In this case the standard startup may be easily longer than the program code itself. One can also use own startup just for satisfaction of making the program shorter by those few kilobytes. Custom startup code cannot be used, when the program uses ''ixemul.library''. When the program is linked with ''libnix'', the possibility of using own startup depends on the standard C library functions used. Most of them do not need any preparations and will work with any startup. Some more complex functions however require constructors to be executed in startup. If we use such functions, we will get linker errors of unresolved symbols. In such a case there is a simple choice &amp;amp;ndash; one either must replace these functions with something else, or just use the standard startup code. Own startup is then useful mostly when standard C library is not used at all (in favour of the native MorphOS API), or only simple functions from it are used.&lt;br /&gt;
&lt;br /&gt;
If we are still determined to use own startup, it is the time to tell the compiler about it. Skipping standard startup is done with '''&amp;amp;minus;nostartfiles''' argument. Then when we try to use our startup with ''libnix'', we use '''&amp;amp;minus;nostartfiles''' together with '''&amp;amp;minus;noixemul'''. Programmers wanting to go the pure MorphOS API way (without the C library), should use '''&amp;amp;minus;nostdlib''' option, which also implies '''&amp;amp;minus;nostdlib'''.&lt;br /&gt;
&lt;br /&gt;
=Let's Write It=&lt;br /&gt;
&lt;br /&gt;
Before we start to write the code, note that except things executed before calling the ''main()'' function, some code must be also called '''after''' it returns. Then we also have &amp;quot;cleanup code&amp;quot;. As this code is usually placed in the same function (the one that calls ''main()''), both the parts are commonly called just startup code.&lt;br /&gt;
&lt;br /&gt;
As mentioned before, program execution does not really start from the ''main()'' function. Where does it start then? When an ELF executable is loaded from disk, a section named &amp;quot;.text&amp;quot; is found and operating system jumps to the start of its contents. When a program is written in C, it means start of the first function in code, as in C there is no way to write code outside of a function. It must be noted, that C compiler may reorder functions in a single object file. The GCC 2.95.3 compiler never does it, but aggressive optimizer of GCC 4 can change order of functions. Fortunately it is done only inside a single source file. To make sure that our startup function will be the first, it must be placed in a separate file. Then resulting object file must be linked as the first one, as linking order is always preserved. After this important note it is time for the code:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;amp;lt;proto/exec.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;proto/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;workbench/startup.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
The thing starts with including needed header files. We will need two basic system libraries: ''exec.library'' and ''dos.library''. It explains why standard startup code, be it ''libnix'' or ''ixemul.library'', opens these two libraries &amp;amp;ndash; it simply needs them for itself.&lt;br /&gt;
&lt;br /&gt;
 struct Library *SysBase;&lt;br /&gt;
 struct Library *DOSBase;&lt;br /&gt;
&lt;br /&gt;
As our code will use these two libaries, we need to define their bases.&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(struct WBStartup *wbmessage);&lt;br /&gt;
&lt;br /&gt;
This is a declaration of the main function of our program. As the object file containing startup code should contain only one function (the entry one), the rest of code has to be moved to other object files, for reasons explained above. That is why the main function has to be declared here, as we call it from the startup code. Alternatively its declaration may be placed in some header file and included here. The name ''Main()'' is arbitrary, it can be anything. I've just called it typically, capitalizing the first letter to avoid possible name confilct with the standard library. The argument of ''Main()'' is startup message (mentioned above) being sent by Ambient. If we do not plan to use it inside ''Main()'', we can just declare it this way:&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(void);&lt;br /&gt;
&lt;br /&gt;
The next important thing is to define a mysterious global symbol ''__abox__''.&lt;br /&gt;
&lt;br /&gt;
 ULONG __abox__ = 1;&lt;br /&gt;
&lt;br /&gt;
While not needed in the code, this symbol is used by the system executable loader to differentiate between MorphOS ELF executables and other possible PowerPC ELF binaries. If there is no ''__abox__'' defined, our code won't run.&lt;br /&gt;
&lt;br /&gt;
 ULONG Start(void)&lt;br /&gt;
 {&lt;br /&gt;
   struct Process *myproc = 0;&lt;br /&gt;
   struct Message *wbmessage = 0;&lt;br /&gt;
   BOOL have_shell = FALSE; &lt;br /&gt;
   ULONG return_code = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
''Start()'' is the code entry point. Again, name of this function is not important, it may be anything. It just has to be the first function in the linked executable. Some local variables are declared here, which will be needed later. ''myproc'' will contain a pointer to our process, ''wbmessage'' will hold the Ambient startup message pointer. Variable ''have_shell'' will be used to detect if the program has been started from shell console or from Ambient. Finally ''return_code'' is just the return code of the program, it will be returned to the system. The return value is usually 0 when the program executed succesfully and ''RETURN_OK'' constant is just 0.&lt;br /&gt;
&lt;br /&gt;
   SysBase = *(struct Library**)4L;&lt;br /&gt;
&lt;br /&gt;
Time for initialization of the ''SysBase'', the base of ''exec.library''. The library is always open. For historical and backward compatibility reasons the base pointer is always placed by the system at address $00000004, so we just take it from there. Having ''exec.library'' available, our code can check whether it has been started from shell or from Ambient:&lt;br /&gt;
&lt;br /&gt;
   myproc = (struct Process*)FindTask(0);&lt;br /&gt;
   if (myproc-&amp;gt;pr_CLI) have_shell = TRUE;&lt;br /&gt;
&lt;br /&gt;
This information is taken from the ''Process'' structure being just system process descriptor. The ''exec.library'' call ''FindTask()'' returns the calling task's own descriptor if 0 is passed as its argument. In case we are started from Ambient, receiving its message is compulsory:&lt;br /&gt;
&lt;br /&gt;
   if (!have_shell)&lt;br /&gt;
   {&lt;br /&gt;
     WaitPort(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
     wbmessage = GetMsg(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The startup message is being sent to process system port, so we receive it there. The message may be then passed to our ''Main()'' function, if we plan to make some use of it, like handling additional icon arguments.&lt;br /&gt;
&lt;br /&gt;
   if (DOSBase = OpenLibrary((STRPTR)&amp;quot;dos.library&amp;quot;, 0))&lt;br /&gt;
   {&lt;br /&gt;
&lt;br /&gt;
The next step is opening ''dos.library'', this library is opened in a pretty standard way. In fact this minimal startup code does not need it. There are two reasons to open it anyway. First, it is hard to imagine a program, which does not need ''dos.library'' &amp;amp;ndash; even &amp;quot;Hello world!&amp;quot; needs it. Secondly, all standard startup codes open it, so usually main code takes it for granted. Then my startup behaves conventionally and opens ''dos.library'' as well.&lt;br /&gt;
&lt;br /&gt;
     return_code = Main((struct WBStartup*)wbmessage);&lt;br /&gt;
&lt;br /&gt;
Yes, after these few lines we are ready to call the main code. As stated above, passing the startup message from Ambient is optional. On the other hand, receiving the result and passing it back to the system later is obligatory.&lt;br /&gt;
&lt;br /&gt;
     CloseLibrary(DOSBase);&lt;br /&gt;
   }&lt;br /&gt;
   else return_code = RETURN_FAIL;&lt;br /&gt;
&lt;br /&gt;
From this point the startup code becomes cleanup one. Note also that proper error handling must be done. ''dos.library'' is being closed, but if its opening failed before, the result of execution is changed to ''RETURN_FAIL''. This is the hardest fail and means total inability to execute. In practice MorphOS can't boot if ''dos.library'' is not present in the system. But ''OpenLibrary()'' may fail for other reasons, for example simple lack of free memory. Then the startup code has to handle it in some reasonable way.&lt;br /&gt;
&lt;br /&gt;
   if (wbmessage)&lt;br /&gt;
   {&lt;br /&gt;
     Forbid();&lt;br /&gt;
     ReplyMsg(wbmessage);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This snippet of code handles the Ambient startup message. Even if we make no use of it, it '''must''' be replied at exit. But what does ''Forbid()'' do here? This function halts system multitasking, specifically it prevents the system process scheduler to switch our process away. Usually it may be done for a very short period of time only and followed by a matching ''Permit()''. At the first glance this code makes no sense then, a process stops process switching and... exits. We have to know one important thing however: process switching is automatically reenabled when the process which called ''Forbid()'' ends. Then here is what happens:&lt;br /&gt;
* Our task calls ''Forbid()'', so no other process can interrupt it.&lt;br /&gt;
* It replies the Ambient startup message. As multitasking is stopped, Ambient is unable to receive yet. The message just waits at its message port.&lt;br /&gt;
* Our task exits. Then the system restores multitasking.&lt;br /&gt;
* Ambient gets CPU time and receives the message. Note that at this point it is absolutely certain, that our task does not exist anymore. Possibility of a race condition is eliminated. Without ''Forbid()'' it could be possible that our process is removed from the system while it still executes.&lt;br /&gt;
Of course multitasking halt period is extremely short, because our cleanup code ends immediately after replying to Ambient:&lt;br /&gt;
&lt;br /&gt;
   return return_code;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=$VER: &amp;amp;ndash; program identification string=&lt;br /&gt;
&lt;br /&gt;
This topic is not strictly related to startup code, but the version string is usually placed in it, so I've decided to write a few words about it. The version string is a short text in some defined format. This string contains the program name, version and revision number, compilation date and optionally copyrigth or author info. The version string is decoded by many applications including Ambient, the system command ''version'', the Installer program and more. The text starts with '''$VER:''', so it can be easily found in the program executable. As version tools search for the version string from the start of the executable file, it is best if version string is placed as close to the beginning of the file as possible. If the version string is declared as a simple string constant, it is unfortunately placed in one of the ELF data sections. These sections are placed after the code section by the linker. However we can force the version string to be placed in the code section:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;#95;_attribute__ ((section(&amp;quot;.text&amp;quot;))) UBYTE VString[] =&lt;br /&gt;
   &amp;quot;$VER: program 1.0 (21.6.2011) &amp;amp;copy; 2011 morphos.pl\r\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Using a GCC specific extension ''__attribute__'' we can push the string into the ELF section named ''.text'', which is the code section. As the startup code object is linked as the first object, the version string will appear at the beginning of the executable, just after the code of the ''Start()'' function. Why after? It is simple, if we place it before the real code, the operating system will jump &amp;quot;into&amp;quot; the string, trying to execute it, and then of course it will crash.&lt;br /&gt;
&lt;br /&gt;
=A Complete Example=&lt;br /&gt;
&lt;br /&gt;
A complete &amp;quot;Hello world!&amp;quot; [http://krashan.ppa.pl/mph/files/helloworld.lha example] with custom startup code shows the described ideas at work. It only uses the MorphOS API, so is compiled with '''&amp;amp;minus;nostdlib''' option. Executable size is 1&amp;amp;nbsp;592 bytes. For comparision, ''libnix'' startup and ''printf()'' gives 30&amp;amp;nbsp;964 bytes, when one replaces ''printf()'' with MorphOS ''Printf()'' from ''dos.library'' it is still 13&amp;amp;nbsp;500 bytes.&lt;br /&gt;
&lt;br /&gt;
As the project consists of two *.c files, a simple makefile is added to it. Example may be compiled just by entering ''make'' in a console.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1744</id>
		<title>Writing Custom Startup Code</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1744"/>
				<updated>2012-12-29T13:37:52Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: More fixes.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
One can find in every C programming handboook, that program execution starts from ''main()'' function. In fact we have such an impression, when we write a program. There is no evidence to disprove it. In fact however, this is not true. There are at least a few, and sometimes even a few teens of kilobytes of code between the start of program execution and the first line of ''main()''. Most of this code is not really needed in most cases.&lt;br /&gt;
&lt;br /&gt;
What is being done by this code? Let's say for the start, it is perfectly possible to have a program without any startup code at all. The system can jump into ''main()'' right away. Unfortunately such a program would run only from commandline window. It would crash, when started from Ambient. It is because Ambient sends a special message to a message port of a freshly created process. This message serves two purposes. Firstly, it contains Ambient launch parameters, namely program icon descriptor and optionally descriptors of other icons, which have been shift-clicked, or dropped onto a panel. Secondly, a reply for the message is a signal for Ambient that the program finished its execution. Sending a reply is obligatory. This is the minimal set of things to be done by startup code. In practice it also should open required shared libraries. When one wants to use the C standard library, either with ''libnix'' or ''ixemul.library'', the startup code also creates a &amp;quot;standard environment&amp;quot; for the C standard library and POSIX functions ([[Installation of Software Development Kit and its basic usage#Standard C and C++ Libraries|more on this]]). Because of this, startup code linked when using one of these libraries is quite complex, so also long.&lt;br /&gt;
&lt;br /&gt;
=Reasons for Writing Own Startup=&lt;br /&gt;
&lt;br /&gt;
The main advantage of an own startup is its shortness. Reducing program startup time is negligible. Very short startup is good for very short programs (for example shell commands), a few kB in size. In this case the standard startup may be easily longer than the program code itself. One can also use own startup just for satisfaction of making the program shorter by those few kilobytes. Custom startup code cannot be used, when the program uses ''ixemul.library''. When the program is linked with ''libnix'', the possibility of using own startup depends on the standard C library functions used. Most of them do not need any preparations and will work with any startup. Some more complex functions however require constructors to be executed in startup. If we use such functions, we will get linker errors of unresolved symbols. In such a case there is a simple choice &amp;amp;ndash; one either must replace these functions with something else, or just use the standard startup code. Own startup is then useful mostly when standard C library is not used at all (in favour of the native MorphOS API), or only simple functions from it are used.&lt;br /&gt;
&lt;br /&gt;
If we are still determined to use own startup, it is the time to tell the compiler about it. Skipping standard startup is done with '''&amp;amp;minus;nostartfiles''' argument. Then when we try to use our startup with ''libnix'', we use '''&amp;amp;minus;nostartfiles''' together with '''&amp;amp;minus;noixemul'''. Programmers wanting to go the pure MorphOS API way (without the C library), should use '''&amp;amp;minus;nostdlib''' option, which also implies '''&amp;amp;minus;nostdlib'''.&lt;br /&gt;
&lt;br /&gt;
=Let's Write It=&lt;br /&gt;
&lt;br /&gt;
Before we start to write the code, note that except things executed before calling the ''main()'' function, some code must be also called '''after''' it returns. Then we also have &amp;quot;cleanup code&amp;quot;. As this code is usually placed in the same function (the one that calls ''main()''), both the parts are commonly called just startup code.&lt;br /&gt;
&lt;br /&gt;
As mentioned before, program execution does not really start from the ''main()'' function. Where does it start then? When an ELF executable is loaded from disk, a section named &amp;quot;.text&amp;quot; is found and operating system jumps to the start of its contents. When a program is written in C, it means start of the first function in code, as in C there is no way to write code outside of a function. It must be noted, that C compiler may reorder functions in a single object file. The GCC 2.95.3 compiler never does it, but aggressive optimizer of GCC 4 can change order of functions. Fortunately it is done only inside a single source file. To make sure that our startup function will be the first, it must be placed in a separate file. Then resulting object file must be linked as the first one, as linking order is always preserved. After this important note it is time for the code:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;amp;lt;proto/exec.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;proto/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;workbench/startup.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
The thing starts with including needed header files. We will need two basic system libraries: ''exec.library'' and ''dos.library''. It explains why standard startup code, be it ''libnix'' or ''ixemul.library'', opens these two libraries &amp;amp;ndash; it simply needs them for itself.&lt;br /&gt;
&lt;br /&gt;
 struct Library *SysBase;&lt;br /&gt;
 struct Library *DOSBase;&lt;br /&gt;
&lt;br /&gt;
As our code will use these two libaries, we need to define their bases.&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(struct WBStartup *wbmessage);&lt;br /&gt;
&lt;br /&gt;
This is a declaration of the main function of our program. As the object file containing startup code should contain only one function (the entry one), the rest of code has to be moved to other object files, for reasons explained above. That is why the main function has to be declared here, as we call it from the startup code. Alternatively its declaration may be placed in some header file and included here. The name ''Main()'' is arbitrary, it can be anything. I've just called it typically, capitalizing the first letter to avoid possible name confilct with the standard library. The argument of ''Main()'' is startup message (mentioned above) being sent by Ambient. If we do not plan to use it inside ''Main()'', we can just declare it this way:&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(void);&lt;br /&gt;
&lt;br /&gt;
The next important thing is to define a mysterious global symbol ''__abox__''.&lt;br /&gt;
&lt;br /&gt;
 ULONG __abox__ = 1;&lt;br /&gt;
&lt;br /&gt;
While not needed in the code, this symbol is used by the system executable loader to differentiate between MorphOS ELF executables and other possible PowerPC ELF binaries. If there is no ''__abox__'' defined, our code won't run.&lt;br /&gt;
&lt;br /&gt;
 ULONG Start(void)&lt;br /&gt;
 {&lt;br /&gt;
   struct Process *myproc = 0;&lt;br /&gt;
   struct Message *wbmessage = 0;&lt;br /&gt;
   BOOL have_shell = FALSE; &lt;br /&gt;
   ULONG return_code = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
''Start()'' is the code entry point. Again, name of this function is not important, it may be anything. It just has to be the first function in the linked executable. Some local variables are declared here, which will be needed later. ''myproc'' will contain a pointer to our process, ''wbmessage'' will hold the Ambient startup message pointer. Variable ''have_shell'' will be used to detect if the program has been started from shell console or from Ambient. Finally ''return_code'' is just the return code of the program, it will be returned to the system. The return value is usually 0 when the program executed succesfully and ''RETURN_OK'' constant is just 0.&lt;br /&gt;
&lt;br /&gt;
   SysBase = *(struct Library**)4L;&lt;br /&gt;
&lt;br /&gt;
Time for initialization of the ''SysBase'', the base of ''exec.library''. The library is always open. For historical and backward compatibility reasons the base pointer is always placed by the system at address $00000004, so we just take it from there. Having ''exec.library'' available, our code can check whether it has been started from shell or from Ambient:&lt;br /&gt;
&lt;br /&gt;
   myproc = (struct Process*)FindTask(0);&lt;br /&gt;
   if (myproc-&amp;gt;pr_CLI) have_shell = TRUE;&lt;br /&gt;
&lt;br /&gt;
This information is taken from the ''Process'' structure being just system process descriptor. The ''exec.library'' call ''FindTask()'' returns own descriptor of the caller if 0 is passed as its argument. In case we are started from Ambient, receiving its message is compulsory:&lt;br /&gt;
&lt;br /&gt;
   if (!have_shell)&lt;br /&gt;
   {&lt;br /&gt;
     WaitPort(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
     wbmessage = GetMsg(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The startup message is being sent to process system port, so we receive it there. The message may be then passed to our ''Main()'' function, if we plan to make some use of it, like handling additional icon arguments.&lt;br /&gt;
&lt;br /&gt;
   if (DOSBase = OpenLibrary((STRPTR)&amp;quot;dos.library&amp;quot;, 0))&lt;br /&gt;
   {&lt;br /&gt;
&lt;br /&gt;
The next step is opening ''dos.library'', this library is opened in a pretty standard way. In fact this minimal startup code does not need it. There are two reasons to open it anyway. First, it is hard to imagine a program, which does not need ''dos.library'' &amp;amp;ndash; even &amp;quot;Hello world!&amp;quot; needs it. Secondly, all standard startup codes open it, so usually main code takes it for granted. Then my startup behaves conventionally and opens ''dos.library'' as well.&lt;br /&gt;
&lt;br /&gt;
     return_code = Main((struct WBStartup*)wbmessage);&lt;br /&gt;
&lt;br /&gt;
Yes, after these few lines we are ready to call the main code. As stated above, passing the startup message from Ambient is optional. On the other hand, receiving the result and passing it back to the system later is obligatory.&lt;br /&gt;
&lt;br /&gt;
     CloseLibrary(DOSBase);&lt;br /&gt;
   }&lt;br /&gt;
   else return_code = RETURN_FAIL;&lt;br /&gt;
&lt;br /&gt;
From this point the startup code becomes cleanup one. Note also that proper error handling must be done. ''dos.library'' is being closed, but if its opening failed before, the result of execution is changed to ''RETURN_FAIL''. This is the hardest fail and means total inability to execute. In practice MorphOS can't boot if ''dos.library'' is not present in the system. But ''OpenLibrary()'' may fail for other reasons, for example simple lack of free memory. Then the startup code has to handle it in some reasonable way.&lt;br /&gt;
&lt;br /&gt;
   if (wbmessage)&lt;br /&gt;
   {&lt;br /&gt;
     Forbid();&lt;br /&gt;
     ReplyMsg(wbmessage);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This snippet of code handles the Ambient startup message. Even if we make no use of it, it '''must''' be replied at exit. But what does ''Forbid()'' do here? This function halts system multitasking, specifically it prevents the system process scheduler to switch our process away. Usually it may be done for a very short period of time only and followed by a matching ''Permit()''. At the first glance this code makes no sense then, a process stops process switching and... exits. We have to know one important thing however: process switching is automatically reenabled when the process which called ''Forbid()'' ends. Then here is what happens:&lt;br /&gt;
* Our task calls ''Forbid()'', so no other process can interrupt it.&lt;br /&gt;
* It replies the Ambient startup message. As multitasking is stopped, Ambient is unable to receive yet. The message just waits at its message port.&lt;br /&gt;
* Our task exits. Then the system restores multitasking.&lt;br /&gt;
* Ambient gets CPU time and receives the message. Note that at this point it is absolutely certain, that our task does not exist anymore. Possibility of a race condition is eliminated. Without ''Forbid()'' it could be possible that our process is removed from the system while it still executes.&lt;br /&gt;
Of course multitasking halt period is extremely short, because our cleanup code ends immediately after replying to Ambient:&lt;br /&gt;
&lt;br /&gt;
   return return_code;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=$VER: &amp;amp;ndash; program identification string=&lt;br /&gt;
&lt;br /&gt;
This topic is not strictly related to startup code, but the version string is usually placed in it, so I've decided to write a few words about it. The version string is a short text in some defined format. This string contains the program name, version and revision number, compilation date and optionally copyrigth or author info. The version string is decoded by many applications including Ambient, the system command ''version'', the Installer program and more. The text starts with '''$VER:''', so it can be easily found in the program executable. As version tools search for the version string from the start of the executable file, it is best if version string is placed as close to the beginning of the file as possible. If the version string is declared as a simple string constant, it is unfortunately placed in one of the ELF data sections. These sections are placed after the code section by the linker. However we can force the version string to be placed in the code section:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;#95;_attribute__ ((section(&amp;quot;.text&amp;quot;))) UBYTE VString[] =&lt;br /&gt;
   &amp;quot;$VER: program 1.0 (21.6.2011) &amp;amp;copy; 2011 morphos.pl\r\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Using a GCC specific extension ''__attribute__'' we can push the string into the ELF section named ''.text'', which is the code section. As the startup code object is linked as the first object, the version string will appear at the beginning of the executable, just after the code of the ''Start()'' function. Why after? It is simple, if we place it before the real code, the operating system will jump &amp;quot;into&amp;quot; the string, trying to execute it, and then of course it will crash.&lt;br /&gt;
&lt;br /&gt;
=A Complete Example=&lt;br /&gt;
&lt;br /&gt;
A complete &amp;quot;Hello world!&amp;quot; [http://krashan.ppa.pl/mph/files/helloworld.lha example] with custom startup code shows the described ideas at work. It only uses the MorphOS API, so is compiled with '''&amp;amp;minus;nostdlib''' option. Executable size is 1&amp;amp;nbsp;592 bytes. For comparision, ''libnix'' startup and ''printf()'' gives 30&amp;amp;nbsp;964 bytes, when one replaces ''printf()'' with MorphOS ''Printf()'' from ''dos.library'' it is still 13&amp;amp;nbsp;500 bytes.&lt;br /&gt;
&lt;br /&gt;
As the project consists of two *.c files, a simple makefile is added to it. Example may be compiled just by entering ''make'' in a console.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1743</id>
		<title>Writing Custom Startup Code</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1743"/>
				<updated>2012-12-29T13:24:37Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: Fixes.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
One can find in every C programming handboook, that program execution starts from ''main()'' function. In fact we have such an impression, when we write a program. There is no evidence to disprove it. In fact however, this is not true. There are at least a few, and sometimes even a few teens of kilobytes of code between the start of program execution and the first line of ''main()''. Most of this code is not really needed in most cases.&lt;br /&gt;
&lt;br /&gt;
What is being done by this code? Let's say for the start, it is perfectly possible to have a program without any startup code at all. The system can jump into ''main()'' right away. Unfortunately such a program would run only from commandline window. It would crash, when started from Ambient. It is because Ambient sends a special message to a message port of a freshly created process. This message serves two purposes. Firstly, it contains Ambient launch parameters, namely program icon descriptor and optionally descriptors of other icons, which have been shift-clicked, or dropped onto a panel. Secondly, a reply for the message is a signal for Ambient that the program finished its execution. Sending a reply is obligatory. This is the minimal set of things to be done by startup code. In practice it also should open required shared libraries. When one wants to use the C standard library, either with ''libnix'' or ''ixemul.library'', the startup code also creates a &amp;quot;standard environment&amp;quot; for the C standard library and POSIX functions ([[Installation of Software Development Kit and its basic usage#Standard C and C++ Libraries|more on this]]). Because of this, startup code linked when using one of these libraries is quite complex, so also long.&lt;br /&gt;
&lt;br /&gt;
=Reasons for Writing Own Startup=&lt;br /&gt;
&lt;br /&gt;
The main advantage of an own startup is its shortness. Reducing program startup time is negligible. Very short startup is good for very short programs (for example shell commands), a few kB in size. In this case the standard startup may be easily longer than the program code itself. One can also use own startup just for satisfaction of making the program shorter by those few kilobytes. Custom startup code cannot be used, when the program uses ''ixemul.library''. When the program is linked with ''libnix'', the possibility of using own startup depends on the standard C library functions used. Most of them do not need any preparations and will work with any startup. Some more complex functions however require constructors to be executed in startup. If we use such functions, we will get linker errors of unresolved symbols. In such a case there is a simple choice &amp;amp;ndash; one either must replace these functions with something else, or just use the standard startup code. Own startup is then useful mostly when standard C library is not used at all (in favour of the native MorphOS API), or only simple functions from it are used.&lt;br /&gt;
&lt;br /&gt;
If we are still determined to use own startup, it is the time to tell the compiler about it. Skipping standard startup is done with '''&amp;amp;minus;nostartfiles''' argument. Then when we try to use our startup with ''libnix'', we use '''&amp;amp;minus;nostartfiles''' together with '''&amp;amp;minus;noixemul'''. Programmers wanting to go the pure MorphOS API way (without the C library), should use '''&amp;amp;minus;nostdlib''' option, which also implies '''&amp;amp;minus;nostdlib'''.&lt;br /&gt;
&lt;br /&gt;
=Let's Write It=&lt;br /&gt;
&lt;br /&gt;
Before we start to write the code, note that except things executed before calling the ''main()'' function, some code must be also called '''after''' it returns. Then we also have &amp;quot;cleanup code&amp;quot;. As this code is usually placed in the same function (the one that calls ''main()''), both the parts are commonly called just startup code.&lt;br /&gt;
&lt;br /&gt;
As mentioned before, program execution does not really start from the ''main()'' function. Where does it start then? When an ELF executable is loaded from disk, a section named &amp;quot;.text&amp;quot; is found and operating system jumps to the start of its contents. When a program is written in C, it means start of the first function in code, as in C there is no way to write code outside of a function. It must be noted, that C compiler may reorder functions in a single object file. The GCC 2.95.3 compiler never does it, but aggressive optimizer of GCC 4 can change order of functions. Fortunately it is done only inside a single source file. To make sure that our startup function will be the first, it must be placed in a separate file. Then resulting object file must be linked as the first one, as linking order is always preserved. After this important note it is time for the code:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;amp;lt;proto/exec.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;proto/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;workbench/startup.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
The thing starts with including needed header files. We will need two basic system libraries: ''exec.library'' and ''dos.library''. It explains why standard startup code, be it ''libnix'' or ''ixemul.library'', opens these two libraries &amp;amp;ndash; it simply needs them for itself.&lt;br /&gt;
&lt;br /&gt;
 struct Library *SysBase = 0;&lt;br /&gt;
 struct Library *DOSBase = 0;&lt;br /&gt;
&lt;br /&gt;
As our code will use these two libaries, we need to define their bases. In fact global variables are zeroed automatically, but I've written it explicitly just in case. It also increases code readability a bit.&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(struct WBStartup *wbmessage);&lt;br /&gt;
&lt;br /&gt;
This is a declaration of the main function of our program. As the object file containing startup code should contain only one function (the entry one), the rest of code has to be moved to other object files, for reasons explained above. That is why the main function has to be declared here, as we call it from the startup code. Alternatively its declaration may be placed in some header file and included here. The name ''Main()'' is arbitrary, it can be anything. I've just called it typically, capitalizing the first letter to avoid possible name confilct with the standard library. The argument of ''Main()'' is startup message (mentioned above) being sent by Ambient. If we do not plan to use it inside ''Main()'', we can just declare it this way:&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(void);&lt;br /&gt;
&lt;br /&gt;
The next important thing is to define a mysterious global symbol ''__abox__''.&lt;br /&gt;
&lt;br /&gt;
 ULONG __abox__ = 1;&lt;br /&gt;
&lt;br /&gt;
While not needed in the code, this symbol is used by the system executable loader to differentiate between MorphOS ELF executables and other possible PowerPC ELF binaries. If there is no ''__abox__'' defined, our code won't run.&lt;br /&gt;
&lt;br /&gt;
 ULONG Start(void)&lt;br /&gt;
 {&lt;br /&gt;
   struct Process *myproc = 0;&lt;br /&gt;
   struct Message *wbmessage = 0;&lt;br /&gt;
   BOOL have_shell = FALSE; &lt;br /&gt;
   ULONG return_code = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
''Start()'' is the code entry point. Again, name of this function is not important, it may be anything. It just has to be the first function in the linked executable. Some local variables are declared here, which will be needed later. ''myproc'' will contain a pointer to our process, ''wbmessage'' will hold the Ambient startup message pointer. Variable ''have_shell'' will be used to detect if the program has been started from shell console or from Ambient. Finally ''return_code'' is just the return code of the program, it will be returned to the system. The return value is usually 0 when the program executed succesfully and ''RETURN_OK'' constant is just 0.&lt;br /&gt;
&lt;br /&gt;
   SysBase = *(struct Library**)4L;&lt;br /&gt;
&lt;br /&gt;
Time for initialization of the ''SysBase'', the base of ''exec.library''. The library is always open. For historical and backward compatibility reasons the base pointer is always placed by the system at address $00000004, so we just take it from there. Having ''exec.library'' available, our code can check whether it has been started from shell or from Ambient:&lt;br /&gt;
&lt;br /&gt;
   myproc = (struct Process*)FindTask(0);&lt;br /&gt;
   if (myproc-&amp;gt;pr_CLI) have_shell = TRUE;&lt;br /&gt;
&lt;br /&gt;
This information is taken from the ''Process'' structure being just system process descriptor. The ''exec.library'' call ''FindTask()'' returns own descriptor of the caller if 0 is passed as its argument. In case we are started from Ambient, receiving its message is compulsory:&lt;br /&gt;
&lt;br /&gt;
   if (!have_shell)&lt;br /&gt;
   {&lt;br /&gt;
     WaitPort(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
     wbmessage = GetMsg(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The startup message is being sent to process system port, so we receive it there. The message may be then passed to our ''Main()'' function, if we plan to make some use of it, like handling additional icon arguments.&lt;br /&gt;
&lt;br /&gt;
   if (DOSBase = OpenLibrary((STRPTR)&amp;quot;dos.library&amp;quot;, 0))&lt;br /&gt;
   {&lt;br /&gt;
&lt;br /&gt;
The next step is opening ''dos.library'', this library is opened in a pretty standard way. In fact this minimal startup code does not need it. There are two reasons to open it anyway. First, it is hard to imagine a program, which does not need ''dos.library'' &amp;amp;ndash; even &amp;quot;Hello world!&amp;quot; needs it. Secondly, all standard startup codes open it, so usually main code takes it for granted. Then my startup behaves conventionally and opens ''dos.library'' as well.&lt;br /&gt;
&lt;br /&gt;
     return_code = Main((struct WBStartup*)wbmessage);&lt;br /&gt;
&lt;br /&gt;
Yes, after these few lines we are ready to call the main code. As stated above, passing the startup message from Ambient is optional. On the other hand, receiving the result and passing it back to the system later is obligatory.&lt;br /&gt;
&lt;br /&gt;
     CloseLibrary(DOSBase);&lt;br /&gt;
   }&lt;br /&gt;
   else return_code = RETURN_FAIL;&lt;br /&gt;
&lt;br /&gt;
From this point the startup code becomes cleanup one. Note also that proper error handling must be done. ''dos.library'' is being closed, but if its opening failed before, the result of execution is changed to ''RETURN_FAIL''. This is the hardest fail and means total inability to execute. In practice MorphOS can't boot if ''dos.library'' is not present in the system. But ''OpenLibrary()'' may fail for other reasons, for example simple lack of free memory. Then the startup code has to handle it in some reasonable way.&lt;br /&gt;
&lt;br /&gt;
   if (wbmessage)&lt;br /&gt;
   {&lt;br /&gt;
     Forbid();&lt;br /&gt;
     ReplyMsg(wbmessage);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This snippet of code handles the Ambient startup message. Even if we make no use of it, it '''must''' be replied at exit. But what does ''Forbid()'' do here? This function halts system multitasking, specifically it prevents the system process scheduler to switch our process away. Usually it may be done for a very short period of time only and followed by a matching ''Permit()''. At the first glance this code makes no sense then, a process stops process switching and... exits. We have to know one important thing however: process switching is automatically reenabled when the process which called ''Forbid()'' ends. Then here is what happens:&lt;br /&gt;
* Our task calls ''Forbid()'', so no other process can interrupt it.&lt;br /&gt;
* It replies the Ambient startup message. As multitasking is stopped, Ambient is unable to receive yet. The message just waits at its message port.&lt;br /&gt;
* Our task exits. Then the system restores multitasking.&lt;br /&gt;
* Ambient gets CPU time and receives the message. Note that at this point it is absolutely certain, that our task does not exist anymore. Possibility of a race condition is eliminated. Without ''Forbid()'' it could be possible that our process is removed from the system while it still executes.&lt;br /&gt;
Of course multitasking halt period is extremely short, because our cleanup code ends immediately after replying to Ambient:&lt;br /&gt;
&lt;br /&gt;
   return return_code;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=$VER: &amp;amp;ndash; program identification string=&lt;br /&gt;
&lt;br /&gt;
This topic is not strictly related to startup code, but the version string is usually placed in it, so I've decided to write a few words about it. The version string is a short text in some defined format. This string contains the program name, version and revision number, compilation date and optionally copyrigth string, or author info. Version string is decoded by many applications including Ambient, system command ''version'', Installer program and more. The text starts from '''$VER:''', so it can be easily found in the program executable. As version tools search for version string from the start of executable file, it is best if version string is placed as near to the start as possible. If version string is declared as a simple string constant, it is unfortunately placed in one of ELF data sections. These sections are placed by compiler after the code section. However we can force the version string to be placed in the code section:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;#95;_attribute__ ((section(&amp;quot;.text&amp;quot;))) UBYTE VString[] =&lt;br /&gt;
   &amp;quot;$VER: program 1.0 (21.6.2011) &amp;amp;copy; 2011 morphos.pl\r\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Using a GCC specific extension ''__attribute__'' we can push the string into ELF section named ''.text'', which is the code section. As the startup code object is linked as the first, version string will appear at the beginning of the executable, just after code of ''Start()'' function. Why after? It is simple, if we place it before the real code, operating system will jump &amp;quot;into&amp;quot; the string, trying to execute it, and then of course will crash.&lt;br /&gt;
&lt;br /&gt;
=A Complete Example=&lt;br /&gt;
&lt;br /&gt;
A complete &amp;quot;Hello world!&amp;quot; [http://krashan.ppa.pl/mph/files/helloworld.lha example] with custom startup code shows described ideas at work. It uses only MorphOS API, so is compiled with '''&amp;amp;minus;nostdlib''' option. Executable size is 1&amp;amp;nbsp;592 bytes. For comparision, ''libnix'' startup and ''printf()'' gives 30&amp;amp;nbsp;964 bytes, when one replaces ''printf()'' with MorphOS ''Printf()'' from ''dos.library'' it is still 13&amp;amp;nbsp;500 bytes.&lt;br /&gt;
&lt;br /&gt;
As the project consists of two *.c files, a simple makefile is added to it. Example may be compiled just by entering ''make'' in a console.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1742</id>
		<title>Writing Custom Startup Code</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1742"/>
				<updated>2012-12-29T12:31:06Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: Fixed internal link.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
One can find in every C programming handboook, that program execution starts from ''main()'' function. In fact we have such an impression, when we write a program. There is no evidence to disprove it. In fact however, this is not true. There are at least a few, and sometimes even a few teens of kilobytes of code between the start of program execution and the first line of ''main()''. Most of this code is not really needed in most cases.&lt;br /&gt;
&lt;br /&gt;
What is being done by this code? Let's say for the start, it is perfectly possible to have a program without any startup code at all. The system can jump into ''main()'' right away. Unfortunately such a program would run only from commandline window. It would crash, when started from Ambient. It is because Ambient sends a special message to a message port of a freshly created process. This message serves two purposes. Firstly, it contains Ambient launch parameters, namely program icon descriptor and optionally descriptors of other icons, which have been shift-clicked, or dropped onto a panel. Secondly, a reply for the message is a singal for Ambient that the program finished its execution. Sending a reply is obligatory. This is the minimal set of things to be done by startup code. In practice it also should open required shared libraries. When one wants to use the C standard library, either with ''libnix'' or ''ixemul.library'', the startup code also creates a &amp;quot;standard environment&amp;quot; for the C standard library and POSIX functions ([[Installation of Software Development Kit and its basic usage#Standard C and C++ Libraries|more on this]]). Because of this, startup code linked when using one of these libraries is quite complex, so also long.&lt;br /&gt;
&lt;br /&gt;
=Reasons for Writing Own Startup=&lt;br /&gt;
&lt;br /&gt;
The main advantage of an own startup is its shortness. Reducing program startup time is negligible. Very short startup is good for very short programs (for example shell commands), a few kB in size. In this case the standard startup may be easily longer than the program code itself. One can also use own startup just for satisfaction of making the program shorter by those few kilobytes. Custom startup code cannot be used, when the program uses ''ixemul.library''. When program is linked with ''libnix'', possibility of using own startup depends on standard C library functions used. Most of them do not need any preparations and will work with any startup. Some more complex functions however require constructors to be executed in startup. If we use such functions, we will get linker errors of unresolved symbols. In such a case there is a simple choice &amp;amp;ndash; one either must replace these functions with something else, or just use the standard startup code. Own startup is then useful mostly when standard C library is not used at all (in favour of the native MorphOS API), or only simple functions from it are used.&lt;br /&gt;
&lt;br /&gt;
If we are still determined to use own startup, it is the time to tell the compiler about it. Skipping standard startup is done with '''&amp;amp;minus;nostartfiles''' argument. Then when we try to use our startup with ''libnix'', we use '''&amp;amp;minus;nostartfiles''' together with '''&amp;amp;minus;noixemul'''. Programmers wanting to go the pure MorphOS API way (without the C library), should add '''&amp;amp;minus;nostdlib''' to it.&lt;br /&gt;
&lt;br /&gt;
=Let's Write It=&lt;br /&gt;
&lt;br /&gt;
Before we start to write the code, note that except of things executed before calling the ''main()'' function, some code must be also called '''after''' it returns. Then we also have &amp;quot;cleanup code&amp;quot;. As this code is usually placed in the same function (one that calls ''main()''), both the parts are commonly called just startup code.&lt;br /&gt;
&lt;br /&gt;
As mentioned before, program execution does not really start from the ''main()''. Where does it start then? When an ELF executable is loaded from disk, a section named &amp;quot;.text&amp;quot; is found and operating system jumps to the start of its contents. When a program is written in C, it means start of the first function in code, as in C there is no way to write a code outside of a function. It must be noted, that C compiler may reorder functions in a single object file. GCC 2.95.3 compiler never does it, but aggressive optimizer of GCC 4 can change order of functions. Fortunately it is done only inside a single source file. To make sure that our startup function will be the first, it must be placed in a separate file. Then resulting object file must be linked as the first one, as linking order is always preserved. After this important note time for the code:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;amp;lt;proto/exec.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;proto/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;workbench/startup.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
The thing starts from including needed header files. We will need two basic system libraries: ''exec.library'' and ''dos.library''. It explains why standard startup code, be it ''libnix'' or ''ixemul.library'', opens these two libraries &amp;amp;ndash; it simply needs them for itself.&lt;br /&gt;
&lt;br /&gt;
 struct Library *SysBase = 0;&lt;br /&gt;
 struct Library *DOSBase = 0;&lt;br /&gt;
&lt;br /&gt;
As our code will use these two libaries, we need to define their bases. In fact global variables are zeroed automatically, but I've written it explicitly just in case. It also increases code readability a bit.&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(struct WBStartup *wbmessage);&lt;br /&gt;
&lt;br /&gt;
This is a declaration of the main function of our program. As the object file containing startup code should contain only one function (the entry one), the rest of code has to be moved to other object files, for reasons explained above. That is why the main function has to be declared here, as we call it from the startup code. Alternatively its declaration may be placed in some header file and included here. The name ''Main()'' is arbitrary, it can be anything. I've just called it typically, capitalizing the first letter to avoid possible name confilct with the standard library. The argument of ''Main()'' is startup message (mentioned above) being sent by Ambient. If we do not plan to use it inside ''Main()'', we can just declare it this way:&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(void);&lt;br /&gt;
&lt;br /&gt;
The next important thing is to define a mysterious global symbol ''__abox__''.&lt;br /&gt;
&lt;br /&gt;
 ULONG __abox__ = 1;&lt;br /&gt;
&lt;br /&gt;
While not needed in the code, this symbol is used by the system executable loader to differentiate between MorphOS ELF executables and other possible PowerPC ELF binaries. If there is no ''__abox__'' defined, our code won't run.&lt;br /&gt;
&lt;br /&gt;
 ULONG Start(void)&lt;br /&gt;
 {&lt;br /&gt;
   struct Process *myproc = 0;&lt;br /&gt;
   struct Message *wbmessage = 0;&lt;br /&gt;
   BOOL have_shell = FALSE; &lt;br /&gt;
   ULONG return_code = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
''Start()'' is the code entry point. Again, name of this function is not important, it may be anything. It just has to be the first function in the linked executable. Some local variables are declared here, which will be needed later. ''myproc'' will contain a pointer to our process, ''wbmessage'' will hold the Ambient startup message pointer. Variable ''have_shell'' will be used to detect if the program has been started from shell console or from Ambient. Finally ''return_code'' is just the return code of the program, it will be returned to the system. The return value is usually 0 when the program executed succesfully and ''RETURN_OK'' constant is just 0.&lt;br /&gt;
&lt;br /&gt;
   SysBase = *(struct Library**)4L;&lt;br /&gt;
&lt;br /&gt;
Time for initialization of the ''SysBase'', the base of ''exec.library''. The library is always open. For historical and backward compatibility reasons the base pointer is always placed by the system at address $00000004, so we just take it from there. Having ''exec.library'' available, our code can check whether it has been started from shell or from Ambient:&lt;br /&gt;
&lt;br /&gt;
   myproc = (struct Process*)FindTask(0);&lt;br /&gt;
   if (myproc-&amp;gt;pr_CLI) have_shell = TRUE;&lt;br /&gt;
&lt;br /&gt;
This information is taken from ''Process'' structure being just system process descriptor. The ''exec.library'' call ''FindTask()'' returns own descriptor of the caller if 0 is passed as its argument. In case we are started from Ambient, receiving its message is compulsory:&lt;br /&gt;
&lt;br /&gt;
   if (!have_shell)&lt;br /&gt;
   {&lt;br /&gt;
     WaitPort(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
     wbmessage = GetMsg(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The startup message is being sent to process system port, so we receive it there. The message may be then passed to our ''Main()'', if we plan to make some use of it, like handling additional icon arguments.&lt;br /&gt;
&lt;br /&gt;
   if (DOSBase = OpenLibrary((STRPTR)&amp;quot;dos.library&amp;quot;, 0))&lt;br /&gt;
   {&lt;br /&gt;
&lt;br /&gt;
The next step is opening the ''dos.library'', this library is opened in a pretty standard way. In fact this minimal startup code does not need it. There are two reasons to open it anyway. First, it is hard to imagine a program, which does not need ''dos.library'' &amp;amp;ndash; even &amp;quot;Hello world!&amp;quot; needs it. Secondly, all standard startup codes open it, so usually main code takes it for granted. Then my startup behaves conventionally and opens ''dos.library'' as well.&lt;br /&gt;
&lt;br /&gt;
     return_code = Main((struct WBStartup*)wbmessage);&lt;br /&gt;
&lt;br /&gt;
Yes, after these few lines we are ready to call the main code. As stated above, passing the startup message from Ambient is optional. On the other hand, receiving the result and passing it back to the system later is obligatory.&lt;br /&gt;
&lt;br /&gt;
     CloseLibrary(DOSBase);&lt;br /&gt;
   }&lt;br /&gt;
   else return_code = RETURN_FAIL;&lt;br /&gt;
&lt;br /&gt;
From this point the startup code becomes cleanup one. Note also that proper error handling must be done. The ''dos.library'' is being closed, but if its opening failed before, the result of execution is changed to ''RETURN_FAIL''. This is the hardest fail and means total inability to execute. In practice MorphOS can't boot if ''dos.library'' is not present in the system. But ''OpenLibrary()'' fail may have other reasons, for example simple lack of free memory. Then the startup code has to handle it in some reasonable way.&lt;br /&gt;
&lt;br /&gt;
   if (wbmessage)&lt;br /&gt;
   {&lt;br /&gt;
     Forbid();&lt;br /&gt;
     ReplyMsg(wbmessage);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This snippet of code handles the Ambient startup message. Even if we make no use of it, it '''must''' be replied at exit. But what ''Forbid()'' does here? This function halts system multitasking, precisely it prevents the system process scheduler to switch our process away. Usually it may be done for very short period of time only and followed by matched ''Permit()''. At the first glance this code makes no sense then, a process stops process switching and... exits. We have to know one important thing however: process switching is automatically reenabled when process which called ''Forbid()'' ends. Then here is what happens:&lt;br /&gt;
* Our task calls ''Forbid()'', so no other process can interrupt it.&lt;br /&gt;
* It replies Ambient startup message. As multitasking is stopped, Ambient is unable to receive yet. The message just waits at its message port.&lt;br /&gt;
* Our task exits. Then the system restores multitasking.&lt;br /&gt;
* Ambient gets CPU time and receives the message. Note that at this point it is absolutely certain, that our task does not exist anymore. Possibility of a race condition is eliminated. Without ''Forbid()'' it could be possible that our process is removed from the system while it still executes.&lt;br /&gt;
Of course multitasking halt period is extremely short, because our cleanup code ends immediately after replying to Ambient:&lt;br /&gt;
&lt;br /&gt;
   return return_code;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=$VER: &amp;amp;ndash; program identification string=&lt;br /&gt;
&lt;br /&gt;
This topic is not strictly related to startup code, but version string is usually placed in it, so I've decided to write a few words about it. Version string is a short text in some defined format. This text contains the program name, version and revision number, compilation date and optionally copyrigth string, or author info. Version string is decoded by many applications including Ambient, system command ''version'', Installer program and more. The text starts from '''$VER:''', so it can be easily found in the program executable. As version tools search for version string from the start of executable file, it is best if version string is placed as near to the start as possible. If version string is declared as a simple string constant, it is unfortunately placed in one of ELF data sections. These sections are placed by compiler after the code section. However we can force the version string to be placed in the code section:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;#95;_attribute__ ((section(&amp;quot;.text&amp;quot;))) UBYTE VString[] =&lt;br /&gt;
   &amp;quot;$VER: program 1.0 (21.6.2011) &amp;amp;copy; 2011 morphos.pl\r\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Using a GCC specific extension ''__attribute__'' we can push the string into ELF section named ''.text'', which is the code section. As the startup code object is linked as the first, version string will appear at the beginning of the executable, just after code of ''Start()'' function. Why after? It is simple, if we place it before the real code, operating system will jump &amp;quot;into&amp;quot; the string, trying to execute it, and then of course will crash.&lt;br /&gt;
&lt;br /&gt;
=A Complete Example=&lt;br /&gt;
&lt;br /&gt;
A complete &amp;quot;Hello world!&amp;quot; [http://krashan.ppa.pl/mph/files/helloworld.lha example] with custom startup code shows described ideas at work. It uses only MorphOS API, so is compiled with '''&amp;amp;minus;nostdlib''' option. Executable size is 1&amp;amp;nbsp;592 bytes. For comparision, ''libnix'' startup and ''printf()'' gives 30&amp;amp;nbsp;964 bytes, when one replaces ''printf()'' with MorphOS ''Printf()'' from ''dos.library'' it is still 13&amp;amp;nbsp;500 bytes.&lt;br /&gt;
&lt;br /&gt;
As the project consists of two *.c files, a simple makefile is added to it. Example may be compiled just by entering ''make'' in a console.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1741</id>
		<title>Writing Custom Startup Code</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1741"/>
				<updated>2012-12-29T11:31:22Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: Added author name&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
One can find in every C programming handboook, that program execution starts from ''main()'' function. In fact we have such an impression, when we write a program. There is no evidence to disprove it. In fact however, this is not true. There are at least a few, and sometimes even a few teens of kilobytes of code between the start of program execution and the first line of ''main()''. Most of this code is not really needed in most cases.&lt;br /&gt;
&lt;br /&gt;
What is being done by this code? Let's say for the start, it is perfectly possible to have a program without any startup code at all. The system can jump into ''main()'' right away. Unfortunately such a program would run only from commandline window. It would crash, when started from Ambient. It is because Ambient sends a special message to a message port of a freshly created process. This message serves two purposes. Firstly, it contains Ambient launch parameters, namely program icon descriptor and optionally descriptors of other icons, which have been shift-clicked, or dropped onto a panel. Secondly, a reply for the message is a singal for Ambient that the program finished its execution. Sending a reply is obligatory. This is the minimal set of things to be done by startup code. In practice it also should open required shared libraries. When one wants to use the C standard library, either with ''libnix'' or ''ixemul.library'', the startup code also creates a &amp;quot;standard environment&amp;quot; for the C standard library and POSIX functions ([morphos-sdk#Standard C and C++ Libraries|more on this]). Because of this, startup code linked when using one of these libraries is quite complex, so also long.&lt;br /&gt;
&lt;br /&gt;
=Reasons for Writing Own Startup=&lt;br /&gt;
&lt;br /&gt;
The main advantage of an own startup is its shortness. Reducing program startup time is negligible. Very short startup is good for very short programs (for example shell commands), a few kB in size. In this case the standard startup may be easily longer than the program code itself. One can also use own startup just for satisfaction of making the program shorter by those few kilobytes. Custom startup code cannot be used, when the program uses ''ixemul.library''. When program is linked with ''libnix'', possibility of using own startup depends on standard C library functions used. Most of them do not need any preparations and will work with any startup. Some more complex functions however require constructors to be executed in startup. If we use such functions, we will get linker errors of unresolved symbols. In such a case there is a simple choice &amp;amp;ndash; one either must replace these functions with something else, or just use the standard startup code. Own startup is then useful mostly when standard C library is not used at all (in favour of the native MorphOS API), or only simple functions from it are used.&lt;br /&gt;
&lt;br /&gt;
If we are still determined to use own startup, it is the time to tell the compiler about it. Skipping standard startup is done with '''&amp;amp;minus;nostartfiles''' argument. Then when we try to use our startup with ''libnix'', we use '''&amp;amp;minus;nostartfiles''' together with '''&amp;amp;minus;noixemul'''. Programmers wanting to go the pure MorphOS API way (without the C library), should add '''&amp;amp;minus;nostdlib''' to it.&lt;br /&gt;
&lt;br /&gt;
=Let's Write It=&lt;br /&gt;
&lt;br /&gt;
Before we start to write the code, note that except of things executed before calling the ''main()'' function, some code must be also called '''after''' it returns. Then we also have &amp;quot;cleanup code&amp;quot;. As this code is usually placed in the same function (one that calls ''main()''), both the parts are commonly called just startup code.&lt;br /&gt;
&lt;br /&gt;
As mentioned before, program execution does not really start from the ''main()''. Where does it start then? When an ELF executable is loaded from disk, a section named &amp;quot;.text&amp;quot; is found and operating system jumps to the start of its contents. When a program is written in C, it means start of the first function in code, as in C there is no way to write a code outside of a function. It must be noted, that C compiler may reorder functions in a single object file. GCC 2.95.3 compiler never does it, but aggressive optimizer of GCC 4 can change order of functions. Fortunately it is done only inside a single source file. To make sure that our startup function will be the first, it must be placed in a separate file. Then resulting object file must be linked as the first one, as linking order is always preserved. After this important note time for the code:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;amp;lt;proto/exec.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;proto/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;workbench/startup.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
The thing starts from including needed header files. We will need two basic system libraries: ''exec.library'' and ''dos.library''. It explains why standard startup code, be it ''libnix'' or ''ixemul.library'', opens these two libraries &amp;amp;ndash; it simply needs them for itself.&lt;br /&gt;
&lt;br /&gt;
 struct Library *SysBase = 0;&lt;br /&gt;
 struct Library *DOSBase = 0;&lt;br /&gt;
&lt;br /&gt;
As our code will use these two libaries, we need to define their bases. In fact global variables are zeroed automatically, but I've written it explicitly just in case. It also increases code readability a bit.&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(struct WBStartup *wbmessage);&lt;br /&gt;
&lt;br /&gt;
This is a declaration of the main function of our program. As the object file containing startup code should contain only one function (the entry one), the rest of code has to be moved to other object files, for reasons explained above. That is why the main function has to be declared here, as we call it from the startup code. Alternatively its declaration may be placed in some header file and included here. The name ''Main()'' is arbitrary, it can be anything. I've just called it typically, capitalizing the first letter to avoid possible name confilct with the standard library. The argument of ''Main()'' is startup message (mentioned above) being sent by Ambient. If we do not plan to use it inside ''Main()'', we can just declare it this way:&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(void);&lt;br /&gt;
&lt;br /&gt;
The next important thing is to define a mysterious global symbol ''__abox__''.&lt;br /&gt;
&lt;br /&gt;
 ULONG __abox__ = 1;&lt;br /&gt;
&lt;br /&gt;
While not needed in the code, this symbol is used by the system executable loader to differentiate between MorphOS ELF executables and other possible PowerPC ELF binaries. If there is no ''__abox__'' defined, our code won't run.&lt;br /&gt;
&lt;br /&gt;
 ULONG Start(void)&lt;br /&gt;
 {&lt;br /&gt;
   struct Process *myproc = 0;&lt;br /&gt;
   struct Message *wbmessage = 0;&lt;br /&gt;
   BOOL have_shell = FALSE; &lt;br /&gt;
   ULONG return_code = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
''Start()'' is the code entry point. Again, name of this function is not important, it may be anything. It just has to be the first function in the linked executable. Some local variables are declared here, which will be needed later. ''myproc'' will contain a pointer to our process, ''wbmessage'' will hold the Ambient startup message pointer. Variable ''have_shell'' will be used to detect if the program has been started from shell console or from Ambient. Finally ''return_code'' is just the return code of the program, it will be returned to the system. The return value is usually 0 when the program executed succesfully and ''RETURN_OK'' constant is just 0.&lt;br /&gt;
&lt;br /&gt;
   SysBase = *(struct Library**)4L;&lt;br /&gt;
&lt;br /&gt;
Time for initialization of the ''SysBase'', the base of ''exec.library''. The library is always open. For historical and backward compatibility reasons the base pointer is always placed by the system at address $00000004, so we just take it from there. Having ''exec.library'' available, our code can check whether it has been started from shell or from Ambient:&lt;br /&gt;
&lt;br /&gt;
   myproc = (struct Process*)FindTask(0);&lt;br /&gt;
   if (myproc-&amp;gt;pr_CLI) have_shell = TRUE;&lt;br /&gt;
&lt;br /&gt;
This information is taken from ''Process'' structure being just system process descriptor. The ''exec.library'' call ''FindTask()'' returns own descriptor of the caller if 0 is passed as its argument. In case we are started from Ambient, receiving its message is compulsory:&lt;br /&gt;
&lt;br /&gt;
   if (!have_shell)&lt;br /&gt;
   {&lt;br /&gt;
     WaitPort(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
     wbmessage = GetMsg(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The startup message is being sent to process system port, so we receive it there. The message may be then passed to our ''Main()'', if we plan to make some use of it, like handling additional icon arguments.&lt;br /&gt;
&lt;br /&gt;
   if (DOSBase = OpenLibrary((STRPTR)&amp;quot;dos.library&amp;quot;, 0))&lt;br /&gt;
   {&lt;br /&gt;
&lt;br /&gt;
The next step is opening the ''dos.library'', this library is opened in a pretty standard way. In fact this minimal startup code does not need it. There are two reasons to open it anyway. First, it is hard to imagine a program, which does not need ''dos.library'' &amp;amp;ndash; even &amp;quot;Hello world!&amp;quot; needs it. Secondly, all standard startup codes open it, so usually main code takes it for granted. Then my startup behaves conventionally and opens ''dos.library'' as well.&lt;br /&gt;
&lt;br /&gt;
     return_code = Main((struct WBStartup*)wbmessage);&lt;br /&gt;
&lt;br /&gt;
Yes, after these few lines we are ready to call the main code. As stated above, passing the startup message from Ambient is optional. On the other hand, receiving the result and passing it back to the system later is obligatory.&lt;br /&gt;
&lt;br /&gt;
     CloseLibrary(DOSBase);&lt;br /&gt;
   }&lt;br /&gt;
   else return_code = RETURN_FAIL;&lt;br /&gt;
&lt;br /&gt;
From this point the startup code becomes cleanup one. Note also that proper error handling must be done. The ''dos.library'' is being closed, but if its opening failed before, the result of execution is changed to ''RETURN_FAIL''. This is the hardest fail and means total inability to execute. In practice MorphOS can't boot if ''dos.library'' is not present in the system. But ''OpenLibrary()'' fail may have other reasons, for example simple lack of free memory. Then the startup code has to handle it in some reasonable way.&lt;br /&gt;
&lt;br /&gt;
   if (wbmessage)&lt;br /&gt;
   {&lt;br /&gt;
     Forbid();&lt;br /&gt;
     ReplyMsg(wbmessage);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This snippet of code handles the Ambient startup message. Even if we make no use of it, it '''must''' be replied at exit. But what ''Forbid()'' does here? This function halts system multitasking, precisely it prevents the system process scheduler to switch our process away. Usually it may be done for very short period of time only and followed by matched ''Permit()''. At the first glance this code makes no sense then, a process stops process switching and... exits. We have to know one important thing however: process switching is automatically reenabled when process which called ''Forbid()'' ends. Then here is what happens:&lt;br /&gt;
* Our task calls ''Forbid()'', so no other process can interrupt it.&lt;br /&gt;
* It replies Ambient startup message. As multitasking is stopped, Ambient is unable to receive yet. The message just waits at its message port.&lt;br /&gt;
* Our task exits. Then the system restores multitasking.&lt;br /&gt;
* Ambient gets CPU time and receives the message. Note that at this point it is absolutely certain, that our task does not exist anymore. Possibility of a race condition is eliminated. Without ''Forbid()'' it could be possible that our process is removed from the system while it still executes.&lt;br /&gt;
Of course multitasking halt period is extremely short, because our cleanup code ends immediately after replying to Ambient:&lt;br /&gt;
&lt;br /&gt;
   return return_code;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=$VER: &amp;amp;ndash; program identification string=&lt;br /&gt;
&lt;br /&gt;
This topic is not strictly related to startup code, but version string is usually placed in it, so I've decided to write a few words about it. Version string is a short text in some defined format. This text contains the program name, version and revision number, compilation date and optionally copyrigth string, or author info. Version string is decoded by many applications including Ambient, system command ''version'', Installer program and more. The text starts from '''$VER:''', so it can be easily found in the program executable. As version tools search for version string from the start of executable file, it is best if version string is placed as near to the start as possible. If version string is declared as a simple string constant, it is unfortunately placed in one of ELF data sections. These sections are placed by compiler after the code section. However we can force the version string to be placed in the code section:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;#95;_attribute__ ((section(&amp;quot;.text&amp;quot;))) UBYTE VString[] =&lt;br /&gt;
   &amp;quot;$VER: program 1.0 (21.6.2011) &amp;amp;copy; 2011 morphos.pl\r\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Using a GCC specific extension ''__attribute__'' we can push the string into ELF section named ''.text'', which is the code section. As the startup code object is linked as the first, version string will appear at the beginning of the executable, just after code of ''Start()'' function. Why after? It is simple, if we place it before the real code, operating system will jump &amp;quot;into&amp;quot; the string, trying to execute it, and then of course will crash.&lt;br /&gt;
&lt;br /&gt;
=A Complete Example=&lt;br /&gt;
&lt;br /&gt;
A complete &amp;quot;Hello world!&amp;quot; [http://krashan.ppa.pl/mph/files/helloworld.lha example] with custom startup code shows described ideas at work. It uses only MorphOS API, so is compiled with '''&amp;amp;minus;nostdlib''' option. Executable size is 1&amp;amp;nbsp;592 bytes. For comparision, ''libnix'' startup and ''printf()'' gives 30&amp;amp;nbsp;964 bytes, when one replaces ''printf()'' with MorphOS ''Printf()'' from ''dos.library'' it is still 13&amp;amp;nbsp;500 bytes.&lt;br /&gt;
&lt;br /&gt;
As the project consists of two *.c files, a simple makefile is added to it. Example may be compiled just by entering ''make'' in a console.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1740</id>
		<title>Writing Custom Startup Code</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Writing_Custom_Startup_Code&amp;diff=1740"/>
				<updated>2012-12-29T11:30:37Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: Added new article.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;One can find in every C programming handboook, that program execution starts from ''main()'' function. In fact we have such an impression, when we write a program. There is no evidence to disprove it. In fact however, this is not true. There are at least a few, and sometimes even a few teens of kilobytes of code between the start of program execution and the first line of ''main()''. Most of this code is not really needed in most cases.&lt;br /&gt;
&lt;br /&gt;
What is being done by this code? Let's say for the start, it is perfectly possible to have a program without any startup code at all. The system can jump into ''main()'' right away. Unfortunately such a program would run only from commandline window. It would crash, when started from Ambient. It is because Ambient sends a special message to a message port of a freshly created process. This message serves two purposes. Firstly, it contains Ambient launch parameters, namely program icon descriptor and optionally descriptors of other icons, which have been shift-clicked, or dropped onto a panel. Secondly, a reply for the message is a singal for Ambient that the program finished its execution. Sending a reply is obligatory. This is the minimal set of things to be done by startup code. In practice it also should open required shared libraries. When one wants to use the C standard library, either with ''libnix'' or ''ixemul.library'', the startup code also creates a &amp;quot;standard environment&amp;quot; for the C standard library and POSIX functions ([morphos-sdk#Standard C and C++ Libraries|more on this]). Because of this, startup code linked when using one of these libraries is quite complex, so also long.&lt;br /&gt;
&lt;br /&gt;
=Reasons for Writing Own Startup=&lt;br /&gt;
&lt;br /&gt;
The main advantage of an own startup is its shortness. Reducing program startup time is negligible. Very short startup is good for very short programs (for example shell commands), a few kB in size. In this case the standard startup may be easily longer than the program code itself. One can also use own startup just for satisfaction of making the program shorter by those few kilobytes. Custom startup code cannot be used, when the program uses ''ixemul.library''. When program is linked with ''libnix'', possibility of using own startup depends on standard C library functions used. Most of them do not need any preparations and will work with any startup. Some more complex functions however require constructors to be executed in startup. If we use such functions, we will get linker errors of unresolved symbols. In such a case there is a simple choice &amp;amp;ndash; one either must replace these functions with something else, or just use the standard startup code. Own startup is then useful mostly when standard C library is not used at all (in favour of the native MorphOS API), or only simple functions from it are used.&lt;br /&gt;
&lt;br /&gt;
If we are still determined to use own startup, it is the time to tell the compiler about it. Skipping standard startup is done with '''&amp;amp;minus;nostartfiles''' argument. Then when we try to use our startup with ''libnix'', we use '''&amp;amp;minus;nostartfiles''' together with '''&amp;amp;minus;noixemul'''. Programmers wanting to go the pure MorphOS API way (without the C library), should add '''&amp;amp;minus;nostdlib''' to it.&lt;br /&gt;
&lt;br /&gt;
=Let's Write It=&lt;br /&gt;
&lt;br /&gt;
Before we start to write the code, note that except of things executed before calling the ''main()'' function, some code must be also called '''after''' it returns. Then we also have &amp;quot;cleanup code&amp;quot;. As this code is usually placed in the same function (one that calls ''main()''), both the parts are commonly called just startup code.&lt;br /&gt;
&lt;br /&gt;
As mentioned before, program execution does not really start from the ''main()''. Where does it start then? When an ELF executable is loaded from disk, a section named &amp;quot;.text&amp;quot; is found and operating system jumps to the start of its contents. When a program is written in C, it means start of the first function in code, as in C there is no way to write a code outside of a function. It must be noted, that C compiler may reorder functions in a single object file. GCC 2.95.3 compiler never does it, but aggressive optimizer of GCC 4 can change order of functions. Fortunately it is done only inside a single source file. To make sure that our startup function will be the first, it must be placed in a separate file. Then resulting object file must be linked as the first one, as linking order is always preserved. After this important note time for the code:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;amp;lt;proto/exec.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;proto/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;workbench/startup.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
The thing starts from including needed header files. We will need two basic system libraries: ''exec.library'' and ''dos.library''. It explains why standard startup code, be it ''libnix'' or ''ixemul.library'', opens these two libraries &amp;amp;ndash; it simply needs them for itself.&lt;br /&gt;
&lt;br /&gt;
 struct Library *SysBase = 0;&lt;br /&gt;
 struct Library *DOSBase = 0;&lt;br /&gt;
&lt;br /&gt;
As our code will use these two libaries, we need to define their bases. In fact global variables are zeroed automatically, but I've written it explicitly just in case. It also increases code readability a bit.&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(struct WBStartup *wbmessage);&lt;br /&gt;
&lt;br /&gt;
This is a declaration of the main function of our program. As the object file containing startup code should contain only one function (the entry one), the rest of code has to be moved to other object files, for reasons explained above. That is why the main function has to be declared here, as we call it from the startup code. Alternatively its declaration may be placed in some header file and included here. The name ''Main()'' is arbitrary, it can be anything. I've just called it typically, capitalizing the first letter to avoid possible name confilct with the standard library. The argument of ''Main()'' is startup message (mentioned above) being sent by Ambient. If we do not plan to use it inside ''Main()'', we can just declare it this way:&lt;br /&gt;
&lt;br /&gt;
 extern ULONG Main(void);&lt;br /&gt;
&lt;br /&gt;
The next important thing is to define a mysterious global symbol ''__abox__''.&lt;br /&gt;
&lt;br /&gt;
 ULONG __abox__ = 1;&lt;br /&gt;
&lt;br /&gt;
While not needed in the code, this symbol is used by the system executable loader to differentiate between MorphOS ELF executables and other possible PowerPC ELF binaries. If there is no ''__abox__'' defined, our code won't run.&lt;br /&gt;
&lt;br /&gt;
 ULONG Start(void)&lt;br /&gt;
 {&lt;br /&gt;
   struct Process *myproc = 0;&lt;br /&gt;
   struct Message *wbmessage = 0;&lt;br /&gt;
   BOOL have_shell = FALSE; &lt;br /&gt;
   ULONG return_code = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
''Start()'' is the code entry point. Again, name of this function is not important, it may be anything. It just has to be the first function in the linked executable. Some local variables are declared here, which will be needed later. ''myproc'' will contain a pointer to our process, ''wbmessage'' will hold the Ambient startup message pointer. Variable ''have_shell'' will be used to detect if the program has been started from shell console or from Ambient. Finally ''return_code'' is just the return code of the program, it will be returned to the system. The return value is usually 0 when the program executed succesfully and ''RETURN_OK'' constant is just 0.&lt;br /&gt;
&lt;br /&gt;
   SysBase = *(struct Library**)4L;&lt;br /&gt;
&lt;br /&gt;
Time for initialization of the ''SysBase'', the base of ''exec.library''. The library is always open. For historical and backward compatibility reasons the base pointer is always placed by the system at address $00000004, so we just take it from there. Having ''exec.library'' available, our code can check whether it has been started from shell or from Ambient:&lt;br /&gt;
&lt;br /&gt;
   myproc = (struct Process*)FindTask(0);&lt;br /&gt;
   if (myproc-&amp;gt;pr_CLI) have_shell = TRUE;&lt;br /&gt;
&lt;br /&gt;
This information is taken from ''Process'' structure being just system process descriptor. The ''exec.library'' call ''FindTask()'' returns own descriptor of the caller if 0 is passed as its argument. In case we are started from Ambient, receiving its message is compulsory:&lt;br /&gt;
&lt;br /&gt;
   if (!have_shell)&lt;br /&gt;
   {&lt;br /&gt;
     WaitPort(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
     wbmessage = GetMsg(&amp;amp;myproc-&amp;gt;pr_MsgPort);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The startup message is being sent to process system port, so we receive it there. The message may be then passed to our ''Main()'', if we plan to make some use of it, like handling additional icon arguments.&lt;br /&gt;
&lt;br /&gt;
   if (DOSBase = OpenLibrary((STRPTR)&amp;quot;dos.library&amp;quot;, 0))&lt;br /&gt;
   {&lt;br /&gt;
&lt;br /&gt;
The next step is opening the ''dos.library'', this library is opened in a pretty standard way. In fact this minimal startup code does not need it. There are two reasons to open it anyway. First, it is hard to imagine a program, which does not need ''dos.library'' &amp;amp;ndash; even &amp;quot;Hello world!&amp;quot; needs it. Secondly, all standard startup codes open it, so usually main code takes it for granted. Then my startup behaves conventionally and opens ''dos.library'' as well.&lt;br /&gt;
&lt;br /&gt;
     return_code = Main((struct WBStartup*)wbmessage);&lt;br /&gt;
&lt;br /&gt;
Yes, after these few lines we are ready to call the main code. As stated above, passing the startup message from Ambient is optional. On the other hand, receiving the result and passing it back to the system later is obligatory.&lt;br /&gt;
&lt;br /&gt;
     CloseLibrary(DOSBase);&lt;br /&gt;
   }&lt;br /&gt;
   else return_code = RETURN_FAIL;&lt;br /&gt;
&lt;br /&gt;
From this point the startup code becomes cleanup one. Note also that proper error handling must be done. The ''dos.library'' is being closed, but if its opening failed before, the result of execution is changed to ''RETURN_FAIL''. This is the hardest fail and means total inability to execute. In practice MorphOS can't boot if ''dos.library'' is not present in the system. But ''OpenLibrary()'' fail may have other reasons, for example simple lack of free memory. Then the startup code has to handle it in some reasonable way.&lt;br /&gt;
&lt;br /&gt;
   if (wbmessage)&lt;br /&gt;
   {&lt;br /&gt;
     Forbid();&lt;br /&gt;
     ReplyMsg(wbmessage);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This snippet of code handles the Ambient startup message. Even if we make no use of it, it '''must''' be replied at exit. But what ''Forbid()'' does here? This function halts system multitasking, precisely it prevents the system process scheduler to switch our process away. Usually it may be done for very short period of time only and followed by matched ''Permit()''. At the first glance this code makes no sense then, a process stops process switching and... exits. We have to know one important thing however: process switching is automatically reenabled when process which called ''Forbid()'' ends. Then here is what happens:&lt;br /&gt;
* Our task calls ''Forbid()'', so no other process can interrupt it.&lt;br /&gt;
* It replies Ambient startup message. As multitasking is stopped, Ambient is unable to receive yet. The message just waits at its message port.&lt;br /&gt;
* Our task exits. Then the system restores multitasking.&lt;br /&gt;
* Ambient gets CPU time and receives the message. Note that at this point it is absolutely certain, that our task does not exist anymore. Possibility of a race condition is eliminated. Without ''Forbid()'' it could be possible that our process is removed from the system while it still executes.&lt;br /&gt;
Of course multitasking halt period is extremely short, because our cleanup code ends immediately after replying to Ambient:&lt;br /&gt;
&lt;br /&gt;
   return return_code;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=$VER: &amp;amp;ndash; program identification string=&lt;br /&gt;
&lt;br /&gt;
This topic is not strictly related to startup code, but version string is usually placed in it, so I've decided to write a few words about it. Version string is a short text in some defined format. This text contains the program name, version and revision number, compilation date and optionally copyrigth string, or author info. Version string is decoded by many applications including Ambient, system command ''version'', Installer program and more. The text starts from '''$VER:''', so it can be easily found in the program executable. As version tools search for version string from the start of executable file, it is best if version string is placed as near to the start as possible. If version string is declared as a simple string constant, it is unfortunately placed in one of ELF data sections. These sections are placed by compiler after the code section. However we can force the version string to be placed in the code section:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;#95;_attribute__ ((section(&amp;quot;.text&amp;quot;))) UBYTE VString[] =&lt;br /&gt;
   &amp;quot;$VER: program 1.0 (21.6.2011) &amp;amp;copy; 2011 morphos.pl\r\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Using a GCC specific extension ''__attribute__'' we can push the string into ELF section named ''.text'', which is the code section. As the startup code object is linked as the first, version string will appear at the beginning of the executable, just after code of ''Start()'' function. Why after? It is simple, if we place it before the real code, operating system will jump &amp;quot;into&amp;quot; the string, trying to execute it, and then of course will crash.&lt;br /&gt;
&lt;br /&gt;
=A Complete Example=&lt;br /&gt;
&lt;br /&gt;
A complete &amp;quot;Hello world!&amp;quot; [http://krashan.ppa.pl/mph/files/helloworld.lha example] with custom startup code shows described ideas at work. It uses only MorphOS API, so is compiled with '''&amp;amp;minus;nostdlib''' option. Executable size is 1&amp;amp;nbsp;592 bytes. For comparision, ''libnix'' startup and ''printf()'' gives 30&amp;amp;nbsp;964 bytes, when one replaces ''printf()'' with MorphOS ''Printf()'' from ''dos.library'' it is still 13&amp;amp;nbsp;500 bytes.&lt;br /&gt;
&lt;br /&gt;
As the project consists of two *.c files, a simple makefile is added to it. Example may be compiled just by entering ''make'' in a console.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Advanced_Topics&amp;diff=1739</id>
		<title>Advanced Topics</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Advanced_Topics&amp;diff=1739"/>
				<updated>2012-12-29T11:26:32Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: First advanced topic added.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[Writing Custom Startup Code]]&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Main_Page&amp;diff=1738</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Main_Page&amp;diff=1738"/>
				<updated>2012-12-29T11:25:20Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Development */ added &amp;quot;Advanced Topics&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;siteLogo&amp;quot; style=&amp;quot;float: right;&amp;quot;&amp;gt; &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:162%; border:none; margin:0; padding:.1em; color:#274572;&amp;quot;&amp;gt;Welcome to the MorphOS Library,&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;top:+0.2em; font-size:95%;&amp;quot;&amp;gt;the wiki based library of MorphOS related documentation.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Do you have suggestions or would like to contribute? Please contact: &amp;lt;div id=&amp;quot;message2library&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Important notes to editors:''' [[Basic Guidelines]] - [[List of Wanted Articles]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;small&amp;gt;This page in other languages: [[Strona główna|Polish]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==About MorphOS==&lt;br /&gt;
MorphOS - The Lightning OS&lt;br /&gt;
* [[What is MorphOS?]]&lt;br /&gt;
* [[Hardware Platforms]]&lt;br /&gt;
* [[Installation]]&lt;br /&gt;
* [[Characteristic features]]&lt;br /&gt;
* [[MorphOS integration]]&lt;br /&gt;
* [[MorphOS Development]]&lt;br /&gt;
* [[Developer tools]]&lt;br /&gt;
* [[3D graphics]]&lt;br /&gt;
* [[Games]]&lt;br /&gt;
* [[MorphOS key applications]]&lt;br /&gt;
* [[Platform expansion]]&lt;br /&gt;
* [[Who needs MorphOS?]]&lt;br /&gt;
* [[Conclusions]]&lt;br /&gt;
* [[Useful links]]&lt;br /&gt;
* [[F.A.Q.]]&lt;br /&gt;
* [[Historical notes]]&lt;br /&gt;
* [[Contributors]]&lt;br /&gt;
A five minute read for users familiar with the Commodore Amiga&lt;br /&gt;
*[[MorphOS in 5 minutes]]&lt;br /&gt;
&lt;br /&gt;
==Articles==&lt;br /&gt;
The core of the MorphOS Library can be found here.  Along with the provided manuals, there are several documents designed to help users get the most out of their MorphOS powered computer.&lt;br /&gt;
&lt;br /&gt;
* [[Fundamentals of MorphOS]]&lt;br /&gt;
* [[Dictionary of Terms]]&lt;br /&gt;
* [[Shell Commands|Shell: Commands]]&lt;br /&gt;
* [[Pattern matching|Shell: Pattern Matching]]&lt;br /&gt;
* [[Volume Names]]&lt;br /&gt;
&lt;br /&gt;
==Tutorials==&lt;br /&gt;
Welcome to the Tutorials section of the MorphOS Library.  In this aisle of the library you can find examples and step by step instructions to help get the most out of your MorphOS experience.&lt;br /&gt;
&lt;br /&gt;
*[[Modifying the User-Startup file]]&lt;br /&gt;
*[[Dual-boot MorphOS and MacOS X on a Mac Mini G4]]&lt;br /&gt;
*[[How to write Mails with SimpleMail]]&lt;br /&gt;
*[[MorphOS External USB Drive Backup Guide]]&lt;br /&gt;
*[[Scanning with SCANdal]]&lt;br /&gt;
*[[Recording an LP with Audio Evolution 4]]&lt;br /&gt;
*[[Passwordless SSH login with RemoteShell]]&lt;br /&gt;
&lt;br /&gt;
==Development==&lt;br /&gt;
In the development section of the MorphOS Library, you can find a collection of helpful articles and tutorials focused on MorphOS software development.&lt;br /&gt;
&lt;br /&gt;
*[[First steps in MorphOS programming]]&lt;br /&gt;
*[[Magic User Interface Programming]]&lt;br /&gt;
*[[In-depth: The New MorphOS Memory System]]&lt;br /&gt;
*[[Reggae: MorphOS multimedia framework]]&lt;br /&gt;
*[[An Introduction to MorphOS PPC Assembly]]&lt;br /&gt;
*[[Advanced Topics]]&lt;br /&gt;
&lt;br /&gt;
==Benchmarks, Reports &amp;amp; Reviews==&lt;br /&gt;
*[[jPV's MorphOS 2 Review]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
The MorphOS Link Database is a collection of websites that are of interest to all current and potential future users of MorphOS. For easier navigation, we have separated the list of websites into multiple categories.&lt;br /&gt;
&lt;br /&gt;
*[[Links#Community_Portals_.26_Forums|Community Portals]]&lt;br /&gt;
*[[Links#File_Repositories|File Repositories]]&lt;br /&gt;
*[[Links#Software|Software]]&lt;br /&gt;
*[[Links#Developers|Developers]]&lt;br /&gt;
*[[Links#Misc|Misc]]&lt;br /&gt;
&lt;br /&gt;
==Work in Progress==&lt;br /&gt;
*[[ReTooled]]&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=The_First_Traditional_%22Hello_world!%22&amp;diff=1735</id>
		<title>The First Traditional &quot;Hello world!&quot;</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=The_First_Traditional_%22Hello_world!%22&amp;diff=1735"/>
				<updated>2012-10-19T06:15:01Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* &amp;quot;Hello World!&amp;quot; With the MorphOS Native API */ style&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;small&amp;gt;This page in other languages: [[Pierwsze tradycyjne &amp;quot;Hello world!&amp;quot;|Polish]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;Hello World!&amp;quot; With the Standard C Library==&lt;br /&gt;
&lt;br /&gt;
With the standard C library, one can use the &amp;quot;Hello World!&amp;quot; example exactly as found in a C handbook. It is given below, just for completeness:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#include &amp;lt;stdio.h&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
int main(void)&amp;lt;br&amp;gt;&lt;br /&gt;
{&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;printf(&amp;quot;Hello World!\n&amp;quot;);&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;return 0;&amp;lt;br&amp;gt;&lt;br /&gt;
}&amp;lt;br&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This source may be copied to a text editor and saved as ''helloworld.c''. To compile it, one opens a shell window (from the Ambient menu, or using the ''rcommand + n'' key combo) and changes current directory to the one, where the C source is located. The compiler is run as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;gcc -o helloworld helloworld.c&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The compiler produces a ''helloworld'' executable, which is 10 340 bytes on my system. Note that MorphOS pays little attention to filename extensions, so ending the executable name with ''.exe'' is not needed, however, it can be done. Traditionally MorphOS executables are named without any extensions. The '''&amp;amp;minus;o''' compiler option specifies a desired executable name. If this option is not given, the executable will be named ''a.out'' (for some historical reasons).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As stated in the [[Installation_of_Software_Development_Kit_and_its_basic_usage#Standard_C_and_C++_Libraries|SDK section]], the standard C library will be provided by ''ixemul.library''. It can be easily confirmed by tracing the disk activity of ''helloworld'' using the ''Snoopium'' tool.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:snoopium_ixemul.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It can also be seen that many other libraries are also opened including ones related to TCP/IP networking. It looks like overkill for such a small program. This happens, because ''ixemul.library'' creates a complete unixlike environment for the application, which is not needed in this simple case. That is why the ''libnix'' alternative is recommended for use of the standard library. To use it, a '''&amp;amp;minus;noixemul''' option has to be added, so the compiler is called as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;gcc -noixemul -o helloworld helloworld.c&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The generated executable is much larger (30 964 bytes here), which just confirms the fact, that ''libnix'', which is now in use, is a statically linked library. Size of functions used adds to the size of the executable. Every C handbook states, that ''printf()'' is the most expensive function of standard I/O, which has just been proven experimentally... On the other hand program activity, as traced with ''Snoopium'', is reduced to three entries. No external resources are opened.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;Hello World!&amp;quot; With the MorphOS Native API==&lt;br /&gt;
&lt;br /&gt;
The MorphOS API (''Application Programmer Interface'') provides complete file and console input/output. In fact, functions in C and C++ standard libraries are, more or less complex wrappers around MorphOS native calls. Using the native API has the following advantages:&lt;br /&gt;
&lt;br /&gt;
* Programs are much shorter.&lt;br /&gt;
* Programs are faster, thanks to stripping some layers of abstraction.&lt;br /&gt;
* Programs are less resource hungry.&lt;br /&gt;
* Native API gives full access to MorphOS specific features.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
These advantages come at a price:&lt;br /&gt;
&lt;br /&gt;
* Programs using the native API are not portable (except for porting to AmigaOS and AROS to some degree).&lt;br /&gt;
* Native ''printf()''-like functions do not support floating point numbers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Hello World!&amp;quot; example using the native API is as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#include &amp;lt;proto/dos.h&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
int main(void)&amp;lt;br&amp;gt;&lt;br /&gt;
{&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;Printf(&amp;quot;Hello World!\n&amp;quot;);&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;return 0;&amp;lt;br&amp;gt;&lt;br /&gt;
}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The included header includes all things needed to use the ''dos.library'', where the ''Printf()'' function is located. The function itself works the same as the standard library ''printf()'', with some minor differences. The code is compiled with this command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;gcc -noixemul -o helloworld helloworld.c&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The command is the same as that used for the program using ''libnix'' and the standard library ''printf()'', however, the standard C function is not used, so it is not linked. Now the executable size reduces to 13 500 bytes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Why is ''libnix'' still needed in spite of the standard library calls not being used? Can't one just compile with '''&amp;amp;minus;nostdlib'''? Other than the standard C library, ''libnix'' also provides application startup code. A program without this startup code can still work when launched from the shell, but will crash when started from Ambient. The startup code also provides an automatic MorphOS library opening and closing feature. So, excluding ''libnix'' completely is possible, but requires [[writing your own startup code]] and [[MorphOS_API_and_Its_Organization#Manual_Library_Opening_and_Closing|handling library opening and closing manually]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Note: excluding ''libnix'' is usually done for MorphOS components other than applications, like shared libraries or Reggae and MUI public classes. It can also be done for ordinary programs just to make them shorter, especially if a program is small. For bigger projects bytes saved by writing custom startup code are not usually worth the effort.&amp;lt;/small&amp;gt;&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Installation_of_Software_Development_Kit_and_its_basic_usage&amp;diff=1734</id>
		<title>Installation of Software Development Kit and its basic usage</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Installation_of_Software_Development_Kit_and_its_basic_usage&amp;diff=1734"/>
				<updated>2012-10-19T06:12:25Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Choosing a Compiler */ style&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;small&amp;gt;This page in other languages: [[Instalacja SDK (Software Development Kit) i podstawy jego używania|polski]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Installing the SDK==&lt;br /&gt;
&lt;br /&gt;
The official MorphOS SDK provides a complete environment for creating programs&lt;br /&gt;
for MorphOS. It contains the following components:&lt;br /&gt;
&lt;br /&gt;
* MorphOS includes (for the MorphOS native API).&lt;br /&gt;
* Standard C and C++ library includes.&lt;br /&gt;
* MorphOS API documentation and example code.&lt;br /&gt;
* Two GCC compilers, 2.95.3 and 4.4.5.&lt;br /&gt;
* GCC toolchains (one for each compiler), sets of developer utility programs.&lt;br /&gt;
* ''Scribble'', an advanced programmer's editor with syntax highlighting and powerful autocomplete and code analyser/hinter feature.&lt;br /&gt;
* Perl scripting language (used by some SDK tools).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The first step of installation is to download the SDK archive from the [http://www.morphos.net morphos.net] site, or by clicking this [http://www.morphos-team.net/files/sdk-20110916.lha direct link]. The SDK is delivered as a LhA archive, which must be depacked before proceeding. The easiest way is to open a context menu for the archive (with the right mouse button in an Ambient window) and choose ''Extract''. After depacking a directory named ''morphossdk'' is created with an ''Installer'' application and a big file named ''sdk.pack'' inside. Installation is started by running ''Installer''. The only user choice that is needed here is to choose an installation directory. Then there is some time spent watching the progress bar...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After the installation a system reboot may be needed to update system assigns and paths.&lt;br /&gt;
&lt;br /&gt;
==Choosing a Compiler==&lt;br /&gt;
&lt;br /&gt;
As mentioned above, the SDK delivers two GCC compilers: an old but trusty 2.95.3 one, and the modern 4.4.5. There is a tool named ''GCCSelect'' in the SDK, which allows for fast switching between compilers. Just type in a shell window&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;GCCSelect 2.95.3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;GCCSelect 4.4.5&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to change the current compiler. ''GCCSelect'' works by making symbolic links to the proper version of GCC and its tools, so the compiler is always called as ''gcc'' or ''g++'', regardless of the version chosen currently.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Which one to choose? It depends on the code compiled and other constrains. Here is some guidance:&lt;br /&gt;
&lt;br /&gt;
* 2.95.3 compiles faster and consumes less memory.&lt;br /&gt;
* For old code 2.95.3 would be better, as GCC 4 will produce tons of warnings or even errors on code being flawlessly compiled by the old GCC.&lt;br /&gt;
* For new projects, especially written in C++, GCC 4 is recommended, as the old one simply does not keep up with modern standards.&lt;br /&gt;
* GCC 4 usually produces faster code (but sometimes also bigger, depending on optimizer options).&lt;br /&gt;
* GCC 4 is a relatively new and complex compiler, may contain more bugs than 2.95.3.&lt;br /&gt;
&lt;br /&gt;
My general advice is to use GCC 4 and only switch to GCC 2 if needed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
One can check which compiler is currently active using the '''&amp;amp;minus;v''' compiler option, which displays the compiler version and build options:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;gcc -v&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line of output shows the GCC version.&lt;br /&gt;
&lt;br /&gt;
==Standard C and C++ Libraries==&lt;br /&gt;
&lt;br /&gt;
These standard libraries are parts of the C and C++ language specifications respectively. They mainly deliver file and console input/output functions, mathematic functions and string operations. The C++ library also provides a set of basic container classes.&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/C_standard_library C standard library on Wikipedia]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/C%2B%2B_Standard_Library C++ standard library on Wikipedia]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are two ways to access these libraries on MorphOS. The first (and default) one is by using a MorphOS [[MorphOS_API_and_Its_Organization|shared library]]; ''ixemul.library''. As the name suggests, this library tries to provide some Unix environment emulation on MorphOS, which, other than the standard libraries, includes large part of [http://en.wikipedia.org/wiki/Posix POSIX] standard and some other commonly used functions. ''ixemul.library'' is usually used for porting big projects from the Unix/Linux world, for example it is used by GCC itself and many other tools in the SDK.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The second way is to use ''libnix'' (as in; '''''lib''' '''n'''o '''ix'''emul''). In contrast to ''ixemul.library'', ''libnix'' is statically linked with the application. This is the preferred way for providing standard libraries for MorphOS native applications. It is achieved by passing the '''&amp;amp;minus;noixemul''' flag to the compiler and the linker. ''libnix'' delivers full C and C++ standard libraries, but its POSIX implementation is less complete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Another alternative is to not use standard libraries at all. It may sound crazy at first, but the MorphOS native API provides complete file and console I/O as well as some string manipulation functions and many mathematic functions. Using the native API makes applications faster and smaller in size. On the other hand code using the MorphOS API directly is not portable to non-Amiga(like) systems. A '''&amp;amp;minus;nostdlib''' compiler option instructs the compiler to not link the code with the standard library. Note that this requires also writing your own [[Custom Startup Code|custom startup code]].&amp;lt;/small&amp;gt;&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Installation_of_Software_Development_Kit_and_its_basic_usage&amp;diff=1733</id>
		<title>Installation of Software Development Kit and its basic usage</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Installation_of_Software_Development_Kit_and_its_basic_usage&amp;diff=1733"/>
				<updated>2012-10-19T06:11:30Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Installing the SDK */ Scribble&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;small&amp;gt;This page in other languages: [[Instalacja SDK (Software Development Kit) i podstawy jego używania|polski]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Installing the SDK==&lt;br /&gt;
&lt;br /&gt;
The official MorphOS SDK provides a complete environment for creating programs&lt;br /&gt;
for MorphOS. It contains the following components:&lt;br /&gt;
&lt;br /&gt;
* MorphOS includes (for the MorphOS native API).&lt;br /&gt;
* Standard C and C++ library includes.&lt;br /&gt;
* MorphOS API documentation and example code.&lt;br /&gt;
* Two GCC compilers, 2.95.3 and 4.4.5.&lt;br /&gt;
* GCC toolchains (one for each compiler), sets of developer utility programs.&lt;br /&gt;
* ''Scribble'', an advanced programmer's editor with syntax highlighting and powerful autocomplete and code analyser/hinter feature.&lt;br /&gt;
* Perl scripting language (used by some SDK tools).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The first step of installation is to download the SDK archive from the [http://www.morphos.net morphos.net] site, or by clicking this [http://www.morphos-team.net/files/sdk-20110916.lha direct link]. The SDK is delivered as a LhA archive, which must be depacked before proceeding. The easiest way is to open a context menu for the archive (with the right mouse button in an Ambient window) and choose ''Extract''. After depacking a directory named ''morphossdk'' is created with an ''Installer'' application and a big file named ''sdk.pack'' inside. Installation is started by running ''Installer''. The only user choice that is needed here is to choose an installation directory. Then there is some time spent watching the progress bar...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After the installation a system reboot may be needed to update system assigns and paths.&lt;br /&gt;
&lt;br /&gt;
==Choosing a Compiler==&lt;br /&gt;
&lt;br /&gt;
As mentioned above, the SDK delivers two GCC compilers: an old but trusty 2.95.3 one, and the modern 4.4.5. There is a tool named ''GCCSelect'' in the SDK, which allows fast switching between compilers. Just type in a shell window&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;GCCSelect 2.95.3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;GCCSelect 4.4.5&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to change the current compiler. ''GCCSelect'' works by making symbolic links to the proper version of GCC and its tools, so the compiler is always called as ''gcc'' or ''g++'', regardless of the version chosen currently.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Which one to choose? It depends on the code compiled and other constrains. Here is some guidance:&lt;br /&gt;
&lt;br /&gt;
* 2.95.3 compiles faster and consumes less memory.&lt;br /&gt;
* For old code 2.95.3 would be better, as GCC 4 will produce tons of warnings or even errors on code being flawlessly compiled by the old GCC.&lt;br /&gt;
* For new projects, especially written in C++, GCC 4 is recommended, as the old one simply does not keep up with modern standards.&lt;br /&gt;
* GCC 4 usually produces faster code (but sometimes also bigger, depending on optimizer options).&lt;br /&gt;
* GCC 4 is a relatively new and complex compiler, may contain more bugs than 2.95.3.&lt;br /&gt;
&lt;br /&gt;
My general advice is to use GCC 4 and only switch to GCC 2 if needed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
One can check which compiler is currently active using the '''&amp;amp;minus;v''' compiler option, which displays the compiler version and build options:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;gcc -v&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last line of output shows the GCC version.&lt;br /&gt;
&lt;br /&gt;
==Standard C and C++ Libraries==&lt;br /&gt;
&lt;br /&gt;
These standard libraries are parts of the C and C++ language specifications respectively. They mainly deliver file and console input/output functions, mathematic functions and string operations. The C++ library also provides a set of basic container classes.&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/C_standard_library C standard library on Wikipedia]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/C%2B%2B_Standard_Library C++ standard library on Wikipedia]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are two ways to access these libraries on MorphOS. The first (and default) one is by using a MorphOS [[MorphOS_API_and_Its_Organization|shared library]]; ''ixemul.library''. As the name suggests, this library tries to provide some Unix environment emulation on MorphOS, which, other than the standard libraries, includes large part of [http://en.wikipedia.org/wiki/Posix POSIX] standard and some other commonly used functions. ''ixemul.library'' is usually used for porting big projects from the Unix/Linux world, for example it is used by GCC itself and many other tools in the SDK.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The second way is to use ''libnix'' (as in; '''''lib''' '''n'''o '''ix'''emul''). In contrast to ''ixemul.library'', ''libnix'' is statically linked with the application. This is the preferred way for providing standard libraries for MorphOS native applications. It is achieved by passing the '''&amp;amp;minus;noixemul''' flag to the compiler and the linker. ''libnix'' delivers full C and C++ standard libraries, but its POSIX implementation is less complete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Another alternative is to not use standard libraries at all. It may sound crazy at first, but the MorphOS native API provides complete file and console I/O as well as some string manipulation functions and many mathematic functions. Using the native API makes applications faster and smaller in size. On the other hand code using the MorphOS API directly is not portable to non-Amiga(like) systems. A '''&amp;amp;minus;nostdlib''' compiler option instructs the compiler to not link the code with the standard library. Note that this requires also writing your own [[Custom Startup Code|custom startup code]].&amp;lt;/small&amp;gt;&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1732</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1732"/>
				<updated>2012-10-09T11:37:02Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Saver Control Without GUI */ Image added.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Buffer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae. To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;br /&gt;
&lt;br /&gt;
==Saver Control Without GUI==&lt;br /&gt;
While the GUI object provided by Reggae for choosing encoder suits most needs of applications, there are cases, where some lower level control is needed. Some examples include (but are not limited to):&lt;br /&gt;
* shell commands&lt;br /&gt;
* scripting interface&lt;br /&gt;
* application log/undo&lt;br /&gt;
* applications using fixed output format&lt;br /&gt;
This lower level control is implemented as an argument string. This string contains the audio format specification in textual, human readable form, very similar to form of arguments of MorphOS shell commands. In fact Reggae argument string is parsed with the same function as shell arguments, namely ''ReadArgs()'' from ''dos.library''. To say more, even when application builds a Reggae saver chain from GUI, argument string is used internally as an intermediate stage.&lt;br /&gt;
&lt;br /&gt;
[[File:Saver_API.png|center]]&lt;br /&gt;
&lt;br /&gt;
How one builds a Reggae saver from an argument string? There is a function in ''multimedia.class'', named ''MediaBuildFromArgsTags()''. It works exactly the same as ''MediaBuildFromGuiTags()'', the only difference is it takes argument string instead of GUI object. But how the argument string looks like? Let's look at a simple example:&lt;br /&gt;
&lt;br /&gt;
 WAVE BITS=24&lt;br /&gt;
&lt;br /&gt;
Every Reggae saver specification consists of two parts. The first part is multiplexer class name, just without the &amp;quot;.muxer&amp;quot; extension. It is capitalized here, but Reggae argument strings are case insensitive. The second part is the rest of string (after skipping whitespaces after multiplexer name) so it can contain multiple arguments. In some cases the second part may be empty, as most formats have default values for encoder parameters. For example one can use simply&lt;br /&gt;
&lt;br /&gt;
 AIFF&lt;br /&gt;
&lt;br /&gt;
to have data stored as 16-bit AIFF file. Of course every multiplexer has its own set of parameters, described in its autodoc.&lt;br /&gt;
&lt;br /&gt;
Applications wanting to log operations done with GUI, or create some undo history can also retrieve the argument string from GUI object with ''MediaGetArgsFromGui()''. It will generate the argument string basing on current gadgets states.&lt;br /&gt;
&lt;br /&gt;
Compared to GUI, the textual interface to Reggae savers has two shortcomings:&lt;br /&gt;
* User (or application, if the argument string is not given by user) has to know which multiplexers are installed in the system and has to know encoder parameters.&lt;br /&gt;
* GUI is designed in a way, that does not allow user to enter senseless or conflicting combinations of parameters (for example ''rawaudio.muxer'' GUI automatically disables &amp;quot;Byte Order&amp;quot; gadget, when 8-bit samples are selected). For textual definition parameter validation is done when Reggae chain is built, and ''MediaBuildFromArgsTags()'' simply fail when arguments make no sense.&lt;br /&gt;
&lt;br /&gt;
==Yet Another Example==&lt;br /&gt;
The third example application using Reggae saver API is [http://krashan.ppa.pl/articles/zgrzytor Zgrzytor]. Unlike Zormanita and U1Synth, it is a shell command using textual saver description explained in the previous section. Zgrzytor is a simple noise generator using a shift register with EXOR feedback. It is a well known technique for generate periodic sounds (for short register) or pseudorandom noise (for long register). User can specify taps (bits) of the shift register where EXOR gate feeding back the register is connected. Sampling rate of output, output file name and output format can be also specified. Some example Zgrzytor call may be:&lt;br /&gt;
&lt;br /&gt;
 Zgrzytor 3 11 22050 somenoise.wav '''WAVE BITS=32'''&lt;br /&gt;
&lt;br /&gt;
This will attach EXOR to bits 3 and 11 (bits are counted from feed side and from 1) of the shift register and generate 5 seconds (time is hardcoded inside program) of noise, set sampling rate to 22.05 kHz and save as 32-bit WAVE (Zgrzytor works with 32-bit integers, so it can produce &amp;quot;real&amp;quot; 32-bit sound). The last, emboldened part of the call is just Reggae saver argument string. More about Zgrzytor can be found on its homepage. Of course full source code of Zgrzytor is added to the archive.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=File:Saver_API.png&amp;diff=1731</id>
		<title>File:Saver API.png</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=File:Saver_API.png&amp;diff=1731"/>
				<updated>2012-10-09T11:35:37Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: Reggae saver API functions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Reggae saver API functions&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1730</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1730"/>
				<updated>2012-10-08T19:32:04Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Yet Another Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Buffer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae. To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;br /&gt;
&lt;br /&gt;
==Saver Control Without GUI==&lt;br /&gt;
While the GUI object provided by Reggae for choosing encoder suits most needs of applications, there are cases, where some lower level control is needed. Some examples include (but are not limited to):&lt;br /&gt;
* shell commands&lt;br /&gt;
* scripting interface&lt;br /&gt;
* application log/undo&lt;br /&gt;
* applications using fixed output format&lt;br /&gt;
This lower level control is implemented as an argument string. This string contains the audio format specification in textual, human readable form, very similar to form of arguments of MorphOS shell commands. In fact Reggae argument string is parsed with the same function as shell arguments, namely ''ReadArgs()'' from ''dos.library''. To say more, even when application builds a Reggae saver chain from GUI, argument string is used internally as an intermediate stage.&lt;br /&gt;
&lt;br /&gt;
How one builds a Reggae saver from an argument string? There is a function in ''multimedia.class'', named ''MediaBuildFromArgsTags()''. It works exactly the same as ''MediaBuildFromGuiTags()'', the only difference is it takes argument string instead of GUI object. But how the argument string looks like? Let's look at a simple example:&lt;br /&gt;
&lt;br /&gt;
 WAVE BITS=24&lt;br /&gt;
&lt;br /&gt;
Every Reggae saver specification consists of two parts. The first part is multiplexer class name, just without the &amp;quot;.muxer&amp;quot; extension. It is capitalized here, but Reggae argument strings are case insensitive. The second part is the rest of string (after skipping whitespaces after multiplexer name) so it can contain multiple arguments. In some cases the second part may be empty, as most formats have default values for encoder parameters. For example one can use simply&lt;br /&gt;
&lt;br /&gt;
 AIFF&lt;br /&gt;
&lt;br /&gt;
to have data stored as 16-bit AIFF file. Of course every multiplexer has its own set of parameters, described in its autodoc.&lt;br /&gt;
&lt;br /&gt;
Applications wanting to log operations done with GUI, or create some undo history can also retrieve the argument string from GUI object with ''MediaGetArgsFromGui()''. It will generate the argument string basing on current gadgets states.&lt;br /&gt;
&lt;br /&gt;
Compared to GUI, the textual interface to Reggae savers has two shortcomings:&lt;br /&gt;
* User (or application, if the argument string is not given by user) has to know which multiplexers are installed in the system and has to know encoder parameters.&lt;br /&gt;
* GUI is designed in a way, that does not allow user to enter senseless or conflicting combinations of parameters (for example ''rawaudio.muxer'' GUI automatically disables &amp;quot;Byte Order&amp;quot; gadget, when 8-bit samples are selected). For textual definition parameter validation is done when Reggae chain is built, and ''MediaBuildFromArgsTags()'' simply fail when arguments make no sense.&lt;br /&gt;
&lt;br /&gt;
==Yet Another Example==&lt;br /&gt;
The third example application using Reggae saver API is [http://krashan.ppa.pl/articles/zgrzytor Zgrzytor]. Unlike Zormanita and U1Synth, it is a shell command using textual saver description explained in the previous section. Zgrzytor is a simple noise generator using a shift register with EXOR feedback. It is a well known technique for generate periodic sounds (for short register) or pseudorandom noise (for long register). User can specify taps (bits) of the shift register where EXOR gate feeding back the register is connected. Sampling rate of output, output file name and output format can be also specified. Some example Zgrzytor call may be:&lt;br /&gt;
&lt;br /&gt;
 Zgrzytor 3 11 22050 somenoise.wav '''WAVE BITS=32'''&lt;br /&gt;
&lt;br /&gt;
This will attach EXOR to bits 3 and 11 (bits are counted from feed side and from 1) of the shift register and generate 5 seconds (time is hardcoded inside program) of noise, set sampling rate to 22.05 kHz and save as 32-bit WAVE (Zgrzytor works with 32-bit integers, so it can produce &amp;quot;real&amp;quot; 32-bit sound). The last, emboldened part of the call is just Reggae saver argument string. More about Zgrzytor can be found on its homepage. Of course full source code of Zgrzytor is added to the archive.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1729</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1729"/>
				<updated>2012-10-08T19:30:45Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Yet Another Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Buffer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae. To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;br /&gt;
&lt;br /&gt;
==Saver Control Without GUI==&lt;br /&gt;
While the GUI object provided by Reggae for choosing encoder suits most needs of applications, there are cases, where some lower level control is needed. Some examples include (but are not limited to):&lt;br /&gt;
* shell commands&lt;br /&gt;
* scripting interface&lt;br /&gt;
* application log/undo&lt;br /&gt;
* applications using fixed output format&lt;br /&gt;
This lower level control is implemented as an argument string. This string contains the audio format specification in textual, human readable form, very similar to form of arguments of MorphOS shell commands. In fact Reggae argument string is parsed with the same function as shell arguments, namely ''ReadArgs()'' from ''dos.library''. To say more, even when application builds a Reggae saver chain from GUI, argument string is used internally as an intermediate stage.&lt;br /&gt;
&lt;br /&gt;
How one builds a Reggae saver from an argument string? There is a function in ''multimedia.class'', named ''MediaBuildFromArgsTags()''. It works exactly the same as ''MediaBuildFromGuiTags()'', the only difference is it takes argument string instead of GUI object. But how the argument string looks like? Let's look at a simple example:&lt;br /&gt;
&lt;br /&gt;
 WAVE BITS=24&lt;br /&gt;
&lt;br /&gt;
Every Reggae saver specification consists of two parts. The first part is multiplexer class name, just without the &amp;quot;.muxer&amp;quot; extension. It is capitalized here, but Reggae argument strings are case insensitive. The second part is the rest of string (after skipping whitespaces after multiplexer name) so it can contain multiple arguments. In some cases the second part may be empty, as most formats have default values for encoder parameters. For example one can use simply&lt;br /&gt;
&lt;br /&gt;
 AIFF&lt;br /&gt;
&lt;br /&gt;
to have data stored as 16-bit AIFF file. Of course every multiplexer has its own set of parameters, described in its autodoc.&lt;br /&gt;
&lt;br /&gt;
Applications wanting to log operations done with GUI, or create some undo history can also retrieve the argument string from GUI object with ''MediaGetArgsFromGui()''. It will generate the argument string basing on current gadgets states.&lt;br /&gt;
&lt;br /&gt;
Compared to GUI, the textual interface to Reggae savers has two shortcomings:&lt;br /&gt;
* User (or application, if the argument string is not given by user) has to know which multiplexers are installed in the system and has to know encoder parameters.&lt;br /&gt;
* GUI is designed in a way, that does not allow user to enter senseless or conflicting combinations of parameters (for example ''rawaudio.muxer'' GUI automatically disables &amp;quot;Byte Order&amp;quot; gadget, when 8-bit samples are selected). For textual definition parameter validation is done when Reggae chain is built, and ''MediaBuildFromArgsTags()'' simply fail when arguments make no sense.&lt;br /&gt;
&lt;br /&gt;
==Yet Another Example==&lt;br /&gt;
The third example application using Reggae saver API is [http://krashan.ppa.pl/articles/zgrzytor Zgrzytor]. Unlike Zormanita and U1Synth, it is a shell command using textual saver description explained in the previous section. Zgrzytor is a simple noise generator using a shift register with EXOR feedback. It is a well known technique for generate periodic sounds (for short register) or pseudorandom noise (for long register). User can specify taps (bits) of the shift register where EXOR gate feeding back the register is connected. Sampling rate of output, output file name and output format can be also specified. Some example Zgrzytor call may be:&lt;br /&gt;
&lt;br /&gt;
 Zgrzytor 3 11 22050 '''WAVE BITS=32'''&lt;br /&gt;
&lt;br /&gt;
This will attach EXOR to bits 3 and 11 (bits are counted from feed side and from 1) of the shift register and generate 5 seconds (time is hardcoded inside program) of noise, set sampling rate to 22.05 kHz and save as 32-bit WAVE (Zgrzytor works with 32-bit integers, so it can produce &amp;quot;real&amp;quot; 32-bit sound). The last, emboldened part of the call is just Reggae saver argument string. More about Zgrzytor can be found on its homepage. Of course full source code of Zgrzytor is added to the archive.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1728</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1728"/>
				<updated>2012-10-08T19:29:10Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Yet Another Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Buffer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae. To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;br /&gt;
&lt;br /&gt;
==Saver Control Without GUI==&lt;br /&gt;
While the GUI object provided by Reggae for choosing encoder suits most needs of applications, there are cases, where some lower level control is needed. Some examples include (but are not limited to):&lt;br /&gt;
* shell commands&lt;br /&gt;
* scripting interface&lt;br /&gt;
* application log/undo&lt;br /&gt;
* applications using fixed output format&lt;br /&gt;
This lower level control is implemented as an argument string. This string contains the audio format specification in textual, human readable form, very similar to form of arguments of MorphOS shell commands. In fact Reggae argument string is parsed with the same function as shell arguments, namely ''ReadArgs()'' from ''dos.library''. To say more, even when application builds a Reggae saver chain from GUI, argument string is used internally as an intermediate stage.&lt;br /&gt;
&lt;br /&gt;
How one builds a Reggae saver from an argument string? There is a function in ''multimedia.class'', named ''MediaBuildFromArgsTags()''. It works exactly the same as ''MediaBuildFromGuiTags()'', the only difference is it takes argument string instead of GUI object. But how the argument string looks like? Let's look at a simple example:&lt;br /&gt;
&lt;br /&gt;
 WAVE BITS=24&lt;br /&gt;
&lt;br /&gt;
Every Reggae saver specification consists of two parts. The first part is multiplexer class name, just without the &amp;quot;.muxer&amp;quot; extension. It is capitalized here, but Reggae argument strings are case insensitive. The second part is the rest of string (after skipping whitespaces after multiplexer name) so it can contain multiple arguments. In some cases the second part may be empty, as most formats have default values for encoder parameters. For example one can use simply&lt;br /&gt;
&lt;br /&gt;
 AIFF&lt;br /&gt;
&lt;br /&gt;
to have data stored as 16-bit AIFF file. Of course every multiplexer has its own set of parameters, described in its autodoc.&lt;br /&gt;
&lt;br /&gt;
Applications wanting to log operations done with GUI, or create some undo history can also retrieve the argument string from GUI object with ''MediaGetArgsFromGui()''. It will generate the argument string basing on current gadgets states.&lt;br /&gt;
&lt;br /&gt;
Compared to GUI, the textual interface to Reggae savers has two shortcomings:&lt;br /&gt;
* User (or application, if the argument string is not given by user) has to know which multiplexers are installed in the system and has to know encoder parameters.&lt;br /&gt;
* GUI is designed in a way, that does not allow user to enter senseless or conflicting combinations of parameters (for example ''rawaudio.muxer'' GUI automatically disables &amp;quot;Byte Order&amp;quot; gadget, when 8-bit samples are selected). For textual definition parameter validation is done when Reggae chain is built, and ''MediaBuildFromArgsTags()'' simply fail when arguments make no sense.&lt;br /&gt;
&lt;br /&gt;
==Yet Another Example==&lt;br /&gt;
The third example application using Reggae saver API is [http://krashan.ppa.pl/articles/zgrzytor|Zgrzytor]. Unlike Zormanita ans U1Synth it is a shell command using textual saver description explained in the previous section. Zgrzytor is a simple noise generator using a shift register with EXOR feedback. It is a well known technique for generate periodic sounds (for short register) or pseudorandom noise (for long register). User can specify taps (bits) of the shift register where EXOR gate feeding back the register is connected. Sampling rate of output, output file name and output format can be also specified. Some example Zgrzytor call may be:&lt;br /&gt;
&lt;br /&gt;
 Zgrzytor 3 11 22050 '''WAVE BITS=32'''&lt;br /&gt;
&lt;br /&gt;
This will attach EXOR to bits 3 and 11 (bits are counted from feed side and from 1) and generate 5 seconds (time is hardcoded inside program) of noise, set sampling rate to 22.05 kHz and save as 32-bit WAVE (Zgrzytor works with 32-bit integers, so it can produce &amp;quot;real&amp;quot; 32-bit sound). The last, emboldened part of the call is just Reggae saver argument string. More about Zgrzytor can be found on its homepage. Of course full source code of Zgrzytor is added to the archive.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1727</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1727"/>
				<updated>2012-10-08T19:28:11Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Buffer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae. To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;br /&gt;
&lt;br /&gt;
==Saver Control Without GUI==&lt;br /&gt;
While the GUI object provided by Reggae for choosing encoder suits most needs of applications, there are cases, where some lower level control is needed. Some examples include (but are not limited to):&lt;br /&gt;
* shell commands&lt;br /&gt;
* scripting interface&lt;br /&gt;
* application log/undo&lt;br /&gt;
* applications using fixed output format&lt;br /&gt;
This lower level control is implemented as an argument string. This string contains the audio format specification in textual, human readable form, very similar to form of arguments of MorphOS shell commands. In fact Reggae argument string is parsed with the same function as shell arguments, namely ''ReadArgs()'' from ''dos.library''. To say more, even when application builds a Reggae saver chain from GUI, argument string is used internally as an intermediate stage.&lt;br /&gt;
&lt;br /&gt;
How one builds a Reggae saver from an argument string? There is a function in ''multimedia.class'', named ''MediaBuildFromArgsTags()''. It works exactly the same as ''MediaBuildFromGuiTags()'', the only difference is it takes argument string instead of GUI object. But how the argument string looks like? Let's look at a simple example:&lt;br /&gt;
&lt;br /&gt;
 WAVE BITS=24&lt;br /&gt;
&lt;br /&gt;
Every Reggae saver specification consists of two parts. The first part is multiplexer class name, just without the &amp;quot;.muxer&amp;quot; extension. It is capitalized here, but Reggae argument strings are case insensitive. The second part is the rest of string (after skipping whitespaces after multiplexer name) so it can contain multiple arguments. In some cases the second part may be empty, as most formats have default values for encoder parameters. For example one can use simply&lt;br /&gt;
&lt;br /&gt;
 AIFF&lt;br /&gt;
&lt;br /&gt;
to have data stored as 16-bit AIFF file. Of course every multiplexer has its own set of parameters, described in its autodoc.&lt;br /&gt;
&lt;br /&gt;
Applications wanting to log operations done with GUI, or create some undo history can also retrieve the argument string from GUI object with ''MediaGetArgsFromGui()''. It will generate the argument string basing on current gadgets states.&lt;br /&gt;
&lt;br /&gt;
Compared to GUI, the textual interface to Reggae savers has two shortcomings:&lt;br /&gt;
* User (or application, if the argument string is not given by user) has to know which multiplexers are installed in the system and has to know encoder parameters.&lt;br /&gt;
* GUI is designed in a way, that does not allow user to enter senseless or conflicting combinations of parameters (for example ''rawaudio.muxer'' GUI automatically disables &amp;quot;Byte Order&amp;quot; gadget, when 8-bit samples are selected). For textual definition parameter validation is done when Reggae chain is built, and ''MediaBuildFromArgsTags()'' simply fail when arguments make no sense.&lt;br /&gt;
&lt;br /&gt;
==Yet Another Example==&lt;br /&gt;
The third example application using Reggae saver API is [http://krashan.ppa.pl/articles/zgrzytor|Zgrzytor]. Unlike Zormanita ans U1Synth it is a shell command using textual saver description explained in the previous section. Zgrzytor is a simple noise generator using a shift register with EXOR feedback. It is a well known technique for generate periodic sounds (for short register) or pseudorandom noise (for long register). User can specify taps (bits) of the shift register where EXOR gate feeding back the register is connected. Sampling rate of output, output file name and output format can be also specified. Some example Zgrzytor call may be:&lt;br /&gt;
&lt;br /&gt;
 Zgrzytor 3 11 22050 '''WAVE BITS=32'''&lt;br /&gt;
&lt;br /&gt;
This will attach EXOR to bits 3 and 11 (bits are counted from feed side and from 1) and generate 5 seconds (time is hardcoded inside program) of noise, set sampling rate to 22.05 kHz and save as 32-bit WAVE (Zgrzytor works with 32-bit integers, so it can produce &amp;quot;real&amp;quot; 32-bit sound). More about Zgrzytor on its homepage. Of course full source code of Zgrzytor is added to the archive.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1726</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1726"/>
				<updated>2012-10-08T19:10:24Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Saver Control Without GUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Buffer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae. To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;br /&gt;
&lt;br /&gt;
==Saver Control Without GUI==&lt;br /&gt;
While the GUI object provided by Reggae for choosing encoder suits most needs of applications, there are cases, where some lower level control is needed. Some examples include (but are not limited to):&lt;br /&gt;
* shell commands&lt;br /&gt;
* scripting interface&lt;br /&gt;
* application log/undo&lt;br /&gt;
* applications using fixed output format&lt;br /&gt;
This lower level control is implemented as an argument string. This string contains the audio format specification in textual, human readable form, very similar to form of arguments of MorphOS shell commands. In fact Reggae argument string is parsed with the same function as shell arguments, namely ''ReadArgs()'' from ''dos.library''. To say more, even when application builds a Reggae saver chain from GUI, argument string is used internally as an intermediate stage.&lt;br /&gt;
&lt;br /&gt;
How one builds a Reggae saver from an argument string? There is a function in ''multimedia.class'', named ''MediaBuildFromArgsTags()''. It works exactly the same as ''MediaBuildFromGuiTags()'', the only difference is it takes argument string instead of GUI object. But how the argument string looks like? Let's look at a simple example:&lt;br /&gt;
&lt;br /&gt;
 WAVE BITS=24&lt;br /&gt;
&lt;br /&gt;
Every Reggae saver specification consists of two parts. The first part is multiplexer class name, just without the &amp;quot;.muxer&amp;quot; extension. It is capitalized here, but Reggae argument strings are case insensitive. The second part is the rest of string (after skipping whitespaces after multiplexer name) so it can contain multiple arguments. In some cases the second part may be empty, as most formats have default values for encoder parameters. For example one can use simply&lt;br /&gt;
&lt;br /&gt;
 AIFF&lt;br /&gt;
&lt;br /&gt;
to have data stored as 16-bit AIFF file. Of course every multiplexer has its own set of parameters, described in its autodoc.&lt;br /&gt;
&lt;br /&gt;
Applications wanting to log operations done with GUI, or create some undo history can also retrieve the argument string from GUI object with ''MediaGetArgsFromGui()''. It will generate the argument string basing on current gadgets states.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1725</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1725"/>
				<updated>2012-10-08T18:58:11Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Saver Control Without GUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Buffer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae. To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;br /&gt;
&lt;br /&gt;
==Saver Control Without GUI==&lt;br /&gt;
While the GUI object provided by Reggae for choosing encoder suits most needs of applications, there are cases, where some lower level control is needed. Some examples include (but are not limited to):&lt;br /&gt;
* shell commands&lt;br /&gt;
* scripting interface&lt;br /&gt;
* application log/undo&lt;br /&gt;
* applications using fixed output format&lt;br /&gt;
This lower level control is implemented as an argument string. This string contains the audio format specification in textual, human readable form, very similar to form of arguments of MorphOS shell commands. In fact Reggae argument string is parsed with the same function as shell arguments, namely ''ReadArgs()'' from ''dos.library''. To say more, even when application builds a Reggae saver chain from GUI, argument string is used internally as an intermediate stage.&lt;br /&gt;
&lt;br /&gt;
How one builds a Reggae saver from an argument string? There is a function in ''multimedia.class'', named ''MediaBuildFromArgsTags()''. It works exactly the same as ''MediaBuildFromGuiTags()'', the only difference is it takes argument string instead of GUI object. But how the argument string looks like? Let's look at a simple example:&lt;br /&gt;
&lt;br /&gt;
 WAVE BITS=24&lt;br /&gt;
&lt;br /&gt;
Every Reggae saver specification consists of two parts. The first part is multiplexer class name, just without the &amp;quot;.muxer&amp;quot; extension. It is capitalized here, but Reggae argument strings are case insensitive. The second part is the rest of string (after skipping whitespaces after multiplexer name. In some cases the second part may be empty, as most formats have default values for encoder parameters. For example one can use simply&lt;br /&gt;
&lt;br /&gt;
 AIFF&lt;br /&gt;
&lt;br /&gt;
to have data stored as 16-bit AIFF file. Of course every multiplexer has its own set of parameters, described in its autodoc.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1724</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1724"/>
				<updated>2012-10-08T17:32:01Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: textual control&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Buffer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae. To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;br /&gt;
&lt;br /&gt;
==Saver Control Without GUI==&lt;br /&gt;
While the GUI object provided by Reggae for choosing encoder suits most needs of applications, there are cases, where some lower level control is needed. Some examples include (but are not limited to):&lt;br /&gt;
* shell commands&lt;br /&gt;
* scripting interface&lt;br /&gt;
* application log/undo&lt;br /&gt;
* applications using fixed output format&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1723</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1723"/>
				<updated>2012-10-04T15:28:41Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Memory Bufer as Data Source */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Buffer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae. To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1722</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1722"/>
				<updated>2012-10-04T12:41:18Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Encoder, Muxer and their Setup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae. To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1721</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1721"/>
				<updated>2012-10-04T12:36:48Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Cleanup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae . To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally, MUI stuff is disposed automatically by MUI.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1720</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1720"/>
				<updated>2012-10-04T12:35:42Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Cleanup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae . To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;br /&gt;
During cleanup application has to close all classes it created and dispose all objects. There are some exceptions however. Once MUI object returned by ''MediaGetGuiTags()'' is added to a MUI application, it need not to be disposed separately. It will be automatically disposed, when MUI ''Application'' object is disposed. &lt;br /&gt;
&lt;br /&gt;
Reggae objects should be disposed in order from output to source:&lt;br /&gt;
&lt;br /&gt;
 DisposeObject(writer);&lt;br /&gt;
 DisposeObject(codec);&lt;br /&gt;
 DisposeObject(raw_audio);&lt;br /&gt;
 DisposeObject(stream);&lt;br /&gt;
&lt;br /&gt;
This order is safe even if ''writer'' object is running when being disposed. If the order is not maintained and running chain is being disposed, it is theoretically possible that Reggae accesses already freed memory.&lt;br /&gt;
&lt;br /&gt;
Reggae classes used should be also closed, '''except of classes for muxer and encoder'''. As these classes are automatically opened by Reggae, they are also automatically closed. Then, in the example, only ''memory.stream'', ''rawaudio.filter'' and ''file.output'' classes must be closed by application. To sum it up, what is explicitly opened/created by application, must be explicitly closed/disposed. Anything created automatically by Reggae is handled by Reggae. Finally MUI stuff is disposed automatically by MUI.&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1719</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1719"/>
				<updated>2012-10-04T10:17:07Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Saving Audio */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae . To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
Notification on end of saving is usually set before starting it. Minimalistic code in a shell based application may look like this:&lt;br /&gt;
&lt;br /&gt;
 DoMethod(writer, MMM_SignalAtEnd, (IPTR)FindTask(NULL), SIGBREAKB_CTRL_C);&lt;br /&gt;
 DoMethod(writer, MMM_Play);&lt;br /&gt;
 Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
Note that while ''Wait()'' takes a signal mask, ''MMM_SignalAtEnd()'' takes a signal number. Do not mistake them. Of course such code blocks application for the saving time. More advanced one may for example check progress periodically and display some messages. For example [http://krashan.ppa.pl/articles/zormanita/ Zormanita] updates progressbar while saving.&lt;br /&gt;
&lt;br /&gt;
While saving media may be aborted at any time by executing ''MMM_Stop()'' method on the writer object, it is not recommended. Currently it is only safe for raw format (''rawaudio.muxer''). AIFF and WAVE multiplexers write headers at start and do not update them when writing is stopped. Then aborting the writer will left saved files incomplete, with header values not matching data actually stored. This behaviour may or may not be improved in the future. It is up to the application then to delete such broken files (it also include cases where writing is aborted due to I/O error).&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1718</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1718"/>
				<updated>2012-10-04T09:56:24Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Saving Audio */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae . To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
An object of ''file.output'' class creates a subprocess. All the work related to encoding media and writing it to disk is done by this subprocess. While writing, application is not blocked. Because of this it may be a good idea to disable gadgets triggering media saving for the time of writing.&lt;br /&gt;
&lt;br /&gt;
As saving is asynchronous, there must be a way to notify the application when it is finished. It is done exactly the same way as for [[Reggae_tutorial:_Playing_a_sound_from_file#Waiting_for_end_of_sound|audio playback]], one in fact uses even the same methods. Then we can either get a signal or a reply for a message, when saving is finished. Waiting for such a signal or message may be added to the [[Event_Driven_Programming,_Notifications#The_Ideal_MUI_Main_Loop|MUI event loop]].&lt;br /&gt;
&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1717</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1717"/>
				<updated>2012-10-04T09:37:54Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Data Output */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae . To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. Of course ''file.output'' class accepts complete paths, both absolute (starting with volume name) and relative to the current program directory. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1716</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1716"/>
				<updated>2012-10-04T09:36:30Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Data Output */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae . To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
The last thing we need is an object writing encoded data. In most cases it is ''file.output'' instance. One creates it with following code:&lt;br /&gt;
&lt;br /&gt;
 Object *writer;&lt;br /&gt;
 &lt;br /&gt;
 writer = NewObject(NULL, &amp;quot;file.output&amp;quot;,&lt;br /&gt;
   MMA_StreamName, (IPTR)&amp;quot;somefile&amp;quot;,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
In this example the file name is hardcoded, of course it is bad style. For shell based programs the file name comes from commandline arguments, for GUI programs it comes from a filerequester, or MUI ''Popasl'' object. After creation, output object is connected with codec output:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(codec, 1, writer, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Now the whole chain is ready to save data. We just need to pull a trigger...&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1715</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1715"/>
				<updated>2012-10-04T09:20:29Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Encoder, Muxer and their Setup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae . To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
At the end of this step, we have an almost complete and connected Reggae processing chain for saving audio. The output port of ''codec'' is not connected, waiting for writing stream object.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1714</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1714"/>
				<updated>2012-10-04T09:17:20Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Encoder, Muxer and their Setup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
This step is automatically performed by Reggae . To set up the encoder and multiplexer duo, Reggae needs two sources of information:&lt;br /&gt;
* GUI object with all selections made by user.&lt;br /&gt;
* Source data stream.&lt;br /&gt;
Both are provided as arguments to ''MediaBuildFromGuiTags()'' function:&lt;br /&gt;
&lt;br /&gt;
 Object *codec;&lt;br /&gt;
 &lt;br /&gt;
 codec = MediaBuildFromGuiTags(format_selector, raw_audio, 1, TAG_END);&lt;br /&gt;
&lt;br /&gt;
The function does a complex task of setting up media codec. Let's analyse it step by step:&lt;br /&gt;
* Reggae checks in the GUI which format has been selected by user. It opens appropriate multiplexer class and creates its instance.&lt;br /&gt;
* Based on detailed GUI selections, Reggae determines which encoder will cooperate with multiplexer selected before. Again its class is opened and object created.&lt;br /&gt;
* Encoder is connected to the data source passed in arguments (object and port). Encoder parameters are set according to GUI and source data parameters.&lt;br /&gt;
* Multiplexer is connected to encoder. Again, multiplexer parameters (if any) are set according to GUI and parameters of stream.&lt;br /&gt;
* Both the objects (plus any auxiliary objects Reggae may create silently) are packed into a single compound object and returned as such.&lt;br /&gt;
&lt;br /&gt;
====Data Output====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1713</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1713"/>
				<updated>2012-10-04T09:01:09Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Building Reggae Processing Chain */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
====Data Output====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1712</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1712"/>
				<updated>2012-10-04T08:38:37Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Memory Bufer as Data Source */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
Note that audio format is not specified as a tag for object constructor, but is just set for the output port. As the last step in this section, we connect these two objects together:&lt;br /&gt;
&lt;br /&gt;
 MediaConnectTagList(stream, 0, raw_audio, 0, NULL);&lt;br /&gt;
&lt;br /&gt;
Stream output is now connected to ''rawaudio.filter'' input.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
====Data Output====&lt;br /&gt;
====Connecting the Chain====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1711</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1711"/>
				<updated>2012-10-04T08:36:21Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Memory Bufer as Data Source */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
 &lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
These two objects are not yet connected togehter, we will do it later. Note that audio format is not specified as a tag for object constructor, but is just set for the output port.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
====Data Output====&lt;br /&gt;
====Connecting the Chain====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1710</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1710"/>
				<updated>2012-10-04T08:36:00Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Memory Bufer as Data Source */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
The next step is ''rawaudio.filter''. Its creation is pretty straightforward:&lt;br /&gt;
&lt;br /&gt;
 Object *raw_audio;&lt;br /&gt;
 &lt;br /&gt;
 raw_audio = NewObject(NULL, &amp;quot;rawaudio.filter&amp;quot;,&lt;br /&gt;
  MMA_Sound_Channels, 1,&lt;br /&gt;
  MMA_Sound_SampleRate, 44100,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
 MediaSetPort(raw_audio, 1, MMA_Port_Format, MMFC_AUDIO_INT16);&lt;br /&gt;
&lt;br /&gt;
These two objects are not yet connected togehter, we will do it later. Note that audio format is not specified as a tag for object constructor, but is just set for the output port.&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
====Data Output====&lt;br /&gt;
====Connecting the Chain====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1709</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1709"/>
				<updated>2012-10-04T08:26:00Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Preparing Source Data */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
Data in a buffer should be in one of Reggae [[Reggae_common_formats|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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
====Data Output====&lt;br /&gt;
====Connecting the Chain====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1708</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1708"/>
				<updated>2012-10-04T08:11:48Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Memory Bufer as Data Source */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
 Object *stream;&lt;br /&gt;
 QUAD stream_length = 88200;&lt;br /&gt;
 &lt;br /&gt;
 stream = NewObject(NULL, &amp;quot;memory.stream&amp;quot;,&lt;br /&gt;
   MMA_Stream_Handle, (IPTR)Buffer,&lt;br /&gt;
   MMA_Stream_Length, (IPTR)&amp;amp;stream_length,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
As the ''MMA_Stream_Length'' attribute takes ''QUAD'' number, it has to be passed via pointer. Length must be specified for ''memory.stream'', as it has no natural end, like for example ''file.stream''. Of course ''memory.stream'' class has to be opened previously with ''OpenLibrary()'', as [[Reggae_tutorial:_Accessing_Reggae_in_applications#Opening_and_closing_individual_classes|described here]].&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
====Data Output====&lt;br /&gt;
====Connecting the Chain====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1707</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1707"/>
				<updated>2012-10-04T08:02:41Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Preparing Source Data */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
Start address of the buffer should be AltiVec aligned. While this is not a requirement for data fetched via ''memory.stream'' object (more about it later), it may speed the processing up a bit. The easiest way to get the alignment 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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
====Data Output====&lt;br /&gt;
====Connecting the Chain====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1706</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1706"/>
				<updated>2012-10-04T07:58:08Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Memory Bufer as Data Source */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
Data contained in a memory buffer need some work to be used as a Reggae source. It need two Reggae objects to handle it. The first object is an instance of ''memory.stream'' class. At its output Reggae sees a stream of bytes, without further meaning or structure. Then we have to tell Reggae, it is not just a stream of bytes, but stream of audio samples with given type, number of channels, sampling rate and so on. This is done with ''rawaudio.filter'' object.&lt;br /&gt;
&lt;br /&gt;
While it looks unnecessarily complicated, it allows for more freedom. By changing ''memory.stream'' to ''file.stream'' one can fetch audio data from mass storage, so is not limited by available memory. It also should be noted that both ''memory.stream'' and ''rawaudio.filter'' are just wrappers. They do not introduce any processing overhead or unnecessary data copying. Reggae stream using a buffer in memory is created as follows:&lt;br /&gt;
&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
====Data Output====&lt;br /&gt;
====Connecting the Chain====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1705</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1705"/>
				<updated>2012-10-04T07:43:39Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Building Reggae Processing Chain */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
====Memory Bufer as Data Source====&lt;br /&gt;
====Encoder, Muxer and their Setup====&lt;br /&gt;
====Data Output====&lt;br /&gt;
====Connecting the Chain====&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1704</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1704"/>
				<updated>2012-10-04T07:43:00Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Building Reggae Processing Chain */ subchapters&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
===Memory Bufer as Data Source===&lt;br /&gt;
===Encoder, Muxer and their Setup===&lt;br /&gt;
===Data Output===&lt;br /&gt;
===Connecting the Chain===&lt;br /&gt;
&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1703</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1703"/>
				<updated>2012-10-04T07:29:02Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Creating Format Selection GUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above). The object is usually added to application's GUI as a value of some ''MUIA_Group_Child'' tag. In most cases it is created statically at application initialization. ''Zormanita'' and ''U1Synth'' create this object statically. It can be also created dynamically, for example as an element of dynamic window. All typical MUI techniques apply.&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1702</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1702"/>
				<updated>2012-10-04T07:25:53Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Creating Format Selection GUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has the standard group frame and group background (the frame is not shown on pictures above).&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1701</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1701"/>
				<updated>2012-10-04T07:25:11Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Creating Format Selection GUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
   MUIA_Background, MUII_GroupBack,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
The object returned is a subclass of MUI ''Group'' class. As such it can have a frame and background assigned if needed. In the example code it has a standard group frame and group background (the frame is not shown on pictures above).&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1700</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1700"/>
				<updated>2012-10-04T07:14:09Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Creating Format Selection GUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Mediaformat1.png]] &amp;amp;nbsp; &amp;amp;nbsp; [[File:Mediaformat2.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The form shown on the left uses cycle gadget for format selection. This style is more compact. On the other hand, list format selection has an advantage of showing immediately the choice of formats. In case of cycle gadget, user has to click it, to get a popup menu. Cycle selector is recommended only in case where space for GUI is limited (for example in custom filerequesters).&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	<entry>
		<id>https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1699</id>
		<title>Reggae tutorial: Saving audio in user selected format</title>
		<link rel="alternate" type="text/html" href="https://library.morph.zone/index.php?title=Reggae_tutorial:_Saving_audio_in_user_selected_format&amp;diff=1699"/>
				<updated>2012-10-04T07:10:09Z</updated>
		
		<summary type="html">&lt;p&gt;Krashan: /* Creating Format Selection GUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Grzegorz Kraszewski''&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
==Preparing Source Data==&lt;br /&gt;
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 [http://krashan.ppa.pl/articles/u1synth 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 [http://krashan.ppa.pl/articles/zormanita Zormanita], which also is opensourced.&lt;br /&gt;
&lt;br /&gt;
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 [&amp;amp;minus;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).&lt;br /&gt;
&lt;br /&gt;
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&amp;amp;nbsp;100 ''INT16'' audio samples, so the size of buffer is 88&amp;amp;nbsp;200 bytes.&lt;br /&gt;
&lt;br /&gt;
 WORD *Buffer;&lt;br /&gt;
 &lt;br /&gt;
 Buffer = (WORD*)MediaAllocVec(88200);&lt;br /&gt;
&lt;br /&gt;
Then the buffer is filled with sound. As an example it is shown how it can be filled by a 1 kHz sine wave.&lt;br /&gt;
&lt;br /&gt;
 LONG i;&lt;br /&gt;
 &lt;br /&gt;
 for (i = 0; i &amp;lt; 44100; i++) Buffer[i] = (WORD)(sin(2000 * M_PI * i / 44100) * 32767.0);&lt;br /&gt;
&lt;br /&gt;
The code is totally unoptimized, but has been left as such to be easy readable.&lt;br /&gt;
&lt;br /&gt;
==Creating Format Selection GUI==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
 Object *FormatSelector;&lt;br /&gt;
 &lt;br /&gt;
 FormatSelector = MediaGetGuiTags(&lt;br /&gt;
   MGG_Type, MGG_Type_Muxers,&lt;br /&gt;
   MGG_Media, MMT_SOUND,&lt;br /&gt;
   MGG_Selector, MGG_Selector_List,&lt;br /&gt;
   MUIA_Frame, MUIV_Frame_Group,&lt;br /&gt;
 TAG_END);&lt;br /&gt;
&lt;br /&gt;
Let's discuss the tags. The first one, ''MMG_Type'' selects type of Reggae classes queried for GUI. There are two possibilities currently. ''MGG_Type_Muxers'' is used when one encodes and saves media stream. There is also ''MGG_Type_Filters'', which may be used for create Reggae filter selector for media processing. The second one will be covered in other articles. The next tag, ''MGG_Media'' defines kind of saved media. When one has audio data it makes no sense to display image or video formats. The value ''MMT_SOUND'' makes sure only audio codecs are shown. The third tag, ''MGG_Selector'' influences visual appearance of the whole GUI object. Graphics interfaces provided by codecs are placed as pages of a MUI page group. Then one needs a gadget for flipping those pages. It may be either a list, or a cycle gadget, as shown below:&lt;br /&gt;
&lt;br /&gt;
[[File:Mediaformat1.png]] [[File:Mediaformat2.png]]&lt;br /&gt;
&lt;br /&gt;
==Building Reggae Processing Chain==&lt;br /&gt;
==Saving Audio==&lt;br /&gt;
==Cleanup==&lt;/div&gt;</summary>
		<author><name>Krashan</name></author>	</entry>

	</feed>