Recently we faced this problem:
1)the 'waveOutSetVolume' documentation states that 'The low-order word [of
'DWORD dwVolume' parameter] contains the left-channel
volume setting, and the high-order word contains the right-channel setting'.
2)AC97 codec registers for volume(s) are 16 bit: the LSB is the attenuation
for the right channel, while the MSB is the attenuation for the
left channel (actually only 5 bits out of 8 are used).
Let's take a look to the low-level function which sets the volume in
%_WINCEROOT%\..\DRIVERS\WAVEDEV\UNIFIED\ENSONIQ
(comments are mine):
****************************************************
CDriverContext::SetVolume (ULONG ulVolume)
m_ulVolume = ulVolume;
/*
The '&' keeps only the higher 5 bits due to the AC97 register format.
Then we 'justify' the data to the right
*/
USHORT usLeft = (USHORT) ((m_ulVolume & 0x0000F800) >> 11);
USHORT usRight = (USHORT) ((m_ulVolume & 0xF8000000) >> 27);
/*
Since AC97 volume register represents the attenuation (i.e. 0 dB ==
MAX_VOLUME),
we subtract the volume from 0x1F
*/
usLeft = 31 - usLeft;
usRight = 31 - usRight;
/*
Here we build up the value to write in the AC97 register:
NOTE that we are putting the RIGHT volume in the higher part of the word
when
we should put the LEFT volume, and viceversa
*/
USHORT usRegVal = (usRight << 8) | usLeft;
/*
Write data to the codec
*/
m_pDevice->WriteCodecRegister(AC97_PCMOUT_VOL, usRegVal);
****************************************************
All the other audio drivers I've seen in WINCE600 (and previous version of
the OS),
although with slightly different semantics, seem to make the same mistake...
Am I wrong or missing something...?
--
Luca Calligaris
www.eurotech.it