Difference between revisions of "Reggae tutorial: Playing a sound from memory"

From MorphOS Library

(Started a new article, introduction.)
 
(More contents.)
Line 3: Line 3:
  
 
While [[Reggae tutorial: Playing a sound from file|playing a sound from file]] is the most common way, there are applications where it has several disadvantages. When a sound is short, played many times and low latency is required, playing this sound from memory will be the better option. Seeking in the sound, or restarting it will be substantially faster then, as it does not involve any disk activity.
 
While [[Reggae tutorial: Playing a sound from file|playing a sound from file]] is the most common way, there are applications where it has several disadvantages. When a sound is short, played many times and low latency is required, playing this sound from memory will be the better option. Seeking in the sound, or restarting it will be substantially faster then, as it does not involve any disk activity.
 +
 +
On the other hand playing from memory should be used with care. Audio data are very space consuming usually. Five seconds audio effect stored as PCM in audio CD quality takes 861 kB of memory. A solution for this problem is to use compressed formats and let Reggae decompress it on the fly.
 +
 +
There are two ways of placing audio file in memory. Firstly, it can be loaded from disk. Secondly the audio file contents may be embedded into the executable file. The second way is a bit dangerous, as it can make the executable very big. On the other hand, such an application is more self contained. Audio file of any fomat can be converted to C code of a large table with [http://morphos-files.net/download/BinToC BinToC] tool. Generated source is added to the project and compiled. Then address of the table (denoted in C just as the table name) and its length in bytes, are passed as parameters to ''memory.stream'' object.
 +
 +
Reggae uses the ''memory.stream'' class to access data located in system memory. Its usage is similar to ''file.stream'', there are some differencies however. The first one is stream name. For ''memory.stream'' it is a string containing stream address as a hexadecimal number, like for example "2749FA0C". ''MMA_StreamName'' attribute is not used often however. One usually has the address just as number, not as text. Converting it to text just to make Reggae to converting it back to number makes not much sense. Then ''MMA_StreamHandle'' attribute comes with help. It's value is just the address of stream, passed as number. Another very important attribute is ''MMA_StreamLength''. Memory based streams have no "natural" end. When one is reading a file, DOS just reports EOF (end of file) condition, when the file ends. In memory one can read endlessly, until he hits end of physical memory space. That is why ''MMA_StreamLenght'' is a '''required''' attribute for memory streams. Reggae will refuse to create a stream object, if the attribute is not specified. Note also that the attribute in general is '''64-bit''' one, and takes a '''pointer to 64-bit number'''. Passing just a 32-bit number as the value is a common mistake here. Code snippet below shows typical creation of memory stream object from a sound embedded in executable file:
 +
 +
 +
<tt>CONST UBYTE SoundData [12837] =  { /* audio data here */ }; /* The length is just example. */<br>
 +
QUAD length = 12837;<br>
 +
Object *stream;<br><br>
 +
stream = MediaNewObject(<br>
 +
&nbsp;&nbsp;MMA_StreamType, "memory.stream",<br>
 +
&nbsp;&nbsp;MMA_StreamHandle, SoundData,<br>
 +
&nbsp;&nbsp;MMA_StreamLength, &length,<br>
 +
TAG_END);</tt>

Revision as of 08:28, 17 June 2010

Grzegorz Kraszewski


While playing a sound from file is the most common way, there are applications where it has several disadvantages. When a sound is short, played many times and low latency is required, playing this sound from memory will be the better option. Seeking in the sound, or restarting it will be substantially faster then, as it does not involve any disk activity.

On the other hand playing from memory should be used with care. Audio data are very space consuming usually. Five seconds audio effect stored as PCM in audio CD quality takes 861 kB of memory. A solution for this problem is to use compressed formats and let Reggae decompress it on the fly.

There are two ways of placing audio file in memory. Firstly, it can be loaded from disk. Secondly the audio file contents may be embedded into the executable file. The second way is a bit dangerous, as it can make the executable very big. On the other hand, such an application is more self contained. Audio file of any fomat can be converted to C code of a large table with BinToC tool. Generated source is added to the project and compiled. Then address of the table (denoted in C just as the table name) and its length in bytes, are passed as parameters to memory.stream object.

Reggae uses the memory.stream class to access data located in system memory. Its usage is similar to file.stream, there are some differencies however. The first one is stream name. For memory.stream it is a string containing stream address as a hexadecimal number, like for example "2749FA0C". MMA_StreamName attribute is not used often however. One usually has the address just as number, not as text. Converting it to text just to make Reggae to converting it back to number makes not much sense. Then MMA_StreamHandle attribute comes with help. It's value is just the address of stream, passed as number. Another very important attribute is MMA_StreamLength. Memory based streams have no "natural" end. When one is reading a file, DOS just reports EOF (end of file) condition, when the file ends. In memory one can read endlessly, until he hits end of physical memory space. That is why MMA_StreamLenght is a required attribute for memory streams. Reggae will refuse to create a stream object, if the attribute is not specified. Note also that the attribute in general is 64-bit one, and takes a pointer to 64-bit number. Passing just a 32-bit number as the value is a common mistake here. Code snippet below shows typical creation of memory stream object from a sound embedded in executable file:


CONST UBYTE SoundData [12837] = { /* audio data here */ }; /* The length is just example. */
QUAD length = 12837;
Object *stream;

stream = MediaNewObject(
  MMA_StreamType, "memory.stream",
  MMA_StreamHandle, SoundData,
  MMA_StreamLength, &length,
TAG_END);