Xaudio Misc Topics
Output Samples Format
In the decoder's output buffer, the audio data is stored as sequences of
samples.
By default, all samples are 16 bit signed values that have the native
endianness of the platform (if the machine is little-endian, the samples
will be in little-endian format, if the machine is big-endian, they will
be in big-endian format).
When the buffer is stereo,the samples are interleaved, alternating
samples from the left channel and samples from the right channel ( L,R,L,R,L,R,L,R,
etc...)
If the output module declares that it does not support 16 bits, the
Xaudio library will convert the buffer into an 8 bit buffer (losing audio
quality). However, the output module can declare the it supports uLaw format,
in which case the 8 bit samples will be coded as uLaw samples, which gives
better quality than lineat 8 bit samples.
Symbol Naming
A few function will take a parameter that identifies a function (XA_MSG_COMMAND_INPUT_MODULE_REGISTER,
XA_MSG_COMMAND_OUTPUT_MODULE_REGISTER, XA_MSG_COMMAND_INPUT_ADD_FILTER,
XA_MSG_COMMAND_OUTPUT_ADD_FITLER, etc...). Each time such a parameter is
needed, the caller can pass:
-
The name of a dynamic library, in which the decoder engine will look for
the right symbol name (depends on the function)
-
The name of a dynamic library AND the name of the symbol to look for (in
the case the symbol name is not the default name), expressed as: <symbol-name>@<library-name>.
-
The name of a built-in module.
-
The synthetic address of a function, expressed as function@<addr>,
where <addr> is the address of the function in hexadecimal format.
Examples:
Registering an input module implemented in a dynamic library:
control_message_send(player, XA_MSG_COMMAND_INPUT_MODULE_REGISTER, "my_input_module.dll")
Registering an output module with a registration name different from the
default ('output_module_register'):
control_message_send(player, XA_MSG_COMMAND_INPUT_MODULE_REGISTER, "my_fucntion@my_input_module.dll")
Registering a builtin output module:
control_message_send(player, XA_MSG_COMMAND_OUTPUT_MODULE_REGISTER, "builtin-directsound-output-module")
Registering an input module implemented as a function that was linked with
the program:
char name[256];
sprintf(name, "function@%x", dsound_output_module_register);
control_message_send(this->player, XA_MSG_COMMAND_OUTPUT_MODULE_REGISTER, name);
Equalizer Bands
The API to set the codec equalizer uses the XA_EqualizerInfo
structure to pass the equalizer settings to the library.
This structure contains 2 sets of 32 equalizer band values (one set
for the left channel, one set for the right channel).
However, most programs will want to use less than 32 'sliders' or 'controls'
to let the user set the bands. Typically, 8, to 12 bands are largely enough
to get a good equalizer control. So the program needs to 'remap' the slider
values into 32 band values for the codec.
Keep in mind that the lower frequency values will make a much bigger
difference than the higher frequency values. Therefore, it is best to make
a one to one mapping of the lower frequency sliders and lower frequency
bands, and a one to many mapping for the higher bands (i.e one slider will
set the value of more than one band).
Each band value is a signed integer between -128 and +127. Negative
values attenuate the corresponding frequency band, and positive values
amplify the corresponding frequency band. Be aware that pushing these values
to their min and max limits will produce a distorted sound. It is usually
good that the user be constrained to a smaller range of values. It is best
to experiment with these values to find the best range for each of the
frequency band.
Example:
Assume we have a user interface with 10 sliders for the equalizer.
We choose not to have independent controls for left and right, so we'll
set the same values in the left and right channel.
Each time the user makes a change to one of the sliders, we recompute
the 2 sets of 32 values needed for the XA_EqualizerInfo
structure. We choose this mapping:
slider 0 --> band index 0
slider 1 --> band index 1
slider 2 --> band index 2
slider 3 --> band index 3
slider 4 --> band index 4
slider 5 --> band index 5
slider 6 --> band index 6-7
slider 7 --> band index 8-11
slider 8 --> band index 12-19
slider 9 --> band index 20-31
so if the slider values are
+10, +05, +03, +02, +00, -05, -10, -20, -13, -05
the corresponding band values would be:
+10, +05, +03, +02, +00, -05, -10, -10, -20, -20, -20, -20, -13, -13, -13, -13, -13, -13, -13, -13, -05, -05, -05, -05, -05, -05, -05, -05, -05, -05, -05, -05
Environment Variables
The Xaudio SDK provides a facility for the different software component
to share global settings, called Environment Variables.
The client application can set and retrieve the values of environment
variables, as well as the decoder itself, and the different input and output
modules, intput and output fitlers.
For instance, a DirectSound output module could have the need for the
window ID of the main application, and it would be cumbersome to require
the client application to send that information to the module each time
the output is opened. So the solution would be for the DirectSound output
module to read an environment variable (the name is totally up to the software
designer) that could be named 'output.directsound.window'. The client application
only needs to set that environment variable once, and never have to worry
about it again.
Environment variables come in 2 flavors: integer variables (can hold
positive and negative integer values), and string variables (can hold string
of up to 1023 characaters).