Difference between revisions of "Reggae tutorial: Playing a synthesized, continuous wave"

From MorphOS Library

m (Raw sine wave synthesis: Fixed a typo.)
(Applying audio parameters with rawaudio.filter: The first paragraph added.)
Line 14: Line 14:
  
 
==Applying audio parameters with rawaudio.filter==
 
==Applying audio parameters with rawaudio.filter==
 +
While the sine wave generation is done, the ''memory.stream'' output cannot be conncted directly to ''audio.output'' object. This is because stream classes deliver just plain stream of bytes with no meaning assigned. In the previous tutorial Reggae was able to play this stream, because it has been self-descripting (contained a header, for example AIFF or WAVE one). Raw data are not self-descripting, so we have to describe it to Reggae ourselves. A "conversion" of stream into audio signal is done with ''rawaudio.filter'' object. Usage of quotes is intentional. In fact this class does not convert the data, it just attaches audio format and attributes to the data stream. Then the stream is recognized by Reggae as audio and may be further processed, which of course includes playing it with ''audio.output''.
  
 
==Looping the sound to make it continuous==
 
==Looping the sound to make it continuous==

Revision as of 12:02, 18 July 2010

Grzegorz Kraszewski


Introduction

This tutorial shows how raw sound data may be played with Reggae. The example code synthesizes a 1 kHz sine wave and plays it continuously. The wave is synthesized into a table in memory. Then memory.stream is used to access it. The next object, an instance of rawaudio.filter, attaches audio parameters to the raw data. Finally audio.output plays the wave in a endless loop, using its looping feature.

Raw sine wave synthesis

In theory a single period of sine wave is enough to play it continuously. There are two reasons for using more periods however. The first is number of samples in one period. We want to play a 1 kHz wave sampled at 44.1 kHz. Then one period would contain 44.1 samples, which is not integer obviously. The second reason is processing overhead of tight loop. Every loop turn takes additional processing time, so it is better, when the loop is longer.

Taking both these reasons into account, 100 periods of the sine are generated into the table containing 4410 samples, which makes 0.1 second of sound. The generation is then straightforward and uses sin() function from the standard C math library. As the argument of sin() is in radians (so one period is 2π), it goes from 0 to 200π in 4410 steps (without the last value). The amplitude of the sine wave (which is normally 1.0) is scaled to 16-bit signed range by multiplying by 32767.

Using memory.stream for synthesis buffer

Basic usage of memory.stream has been discussed in "Playing a Sound From Memory" tutorial. MMA_StreamHandle attribute is used to pass the memory table address, MMA_StreamLength one takes the table size in bytes (note, it is not the same as the table size, as every element of the table ocuppies two bytes). Note also, MMA_StreamLength is 64-bit attribute, and as such is passed as a pointer to a QUAD variable containing the value.

Applying audio parameters with rawaudio.filter

While the sine wave generation is done, the memory.stream output cannot be conncted directly to audio.output object. This is because stream classes deliver just plain stream of bytes with no meaning assigned. In the previous tutorial Reggae was able to play this stream, because it has been self-descripting (contained a header, for example AIFF or WAVE one). Raw data are not self-descripting, so we have to describe it to Reggae ourselves. A "conversion" of stream into audio signal is done with rawaudio.filter object. Usage of quotes is intentional. In fact this class does not convert the data, it just attaches audio format and attributes to the data stream. Then the stream is recognized by Reggae as audio and may be further processed, which of course includes playing it with audio.output.

Looping the sound to make it continuous