📄 wmaudiosignals.c
字号:
WM_AUDIO_CHANNELS channels = 0;
WMSTATUS status;
unsigned int nSignal;
WM_BOOL found = FALSE;
/*
* Look up our chipdef.
*/
pChipDef = WMGetChipDef( hDevice );
if ( !pChipDef )
{
status = WMS_NO_SUPPORTED_DEVICE;
goto error;
}
/*
* Run through the signals, looking for ones which match. If we get
* both left and right, we've got a stereo signal.
*/
for ( nSignal = 0; nSignal < pChipDef->signalCount; nSignal++ )
{
pSignalDetails = &pChipDef->pSignalDetails[ nSignal ];
if ( pSignalDetails->signal == signal )
{
/* It matches. Remember the channel. */
channels |= ( pSignalDetails->flags & WM_SIG_CHANNEL_MASK );
found = TRUE;
}
}
if ( !found )
{
status = WMS_UNSUPPORTED;
goto error;
}
/*
* Success - return the channels we found.
*/
*pChannels = channels;
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioMuteSignal
*
* Called to mute or unmute the signal to all paths.
*
* Note: This function will set and clear all the mute bits for the signal.
*
* Parameters:
* hDevice The handle to the device (from WMOpenDevice).
* signal The signal to mute.
* mute Mute if TRUE, unmute if FALSE.
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioMuteSignal( WM_DEVICE_HANDLE hDevice,
WM_AUDIO_SIGNAL signal,
WM_BOOL mute
)
{
const WM_SIGNAL_DETAILS *pSignalDetails = NULL;
const WM_CHIPDEF *pChipDef;
WMSTATUS status = WMS_UNSUPPORTED;
unsigned int nSignal;
WM_REGTYPE reg = WM_REG_INVALID;
WM_REGVAL regval = 0;
WM_REGVAL update = 0;
WM_REGVAL mask = 0;
/*
* Look up our chipdef.
*/
pChipDef = WMGetChipDef( hDevice );
if ( !pChipDef )
{
status = WMS_NO_SUPPORTED_DEVICE;
goto error;
}
/*
* Run through the signals, looking for ones which match. Apply the
* mute to each. We have several scenarios here:
*
* - single field (one entry)
* - multiple fields in the same register (e.g. AC'97)
* - multiple fields in multiple registers (e.g. WM8753)
*/
for ( nSignal = 0; nSignal < pChipDef->signalCount; nSignal++ )
{
pSignalDetails = &pChipDef->pSignalDetails[ nSignal ];
if ( pSignalDetails->signal == signal &&
WM_REG_INVALID != pSignalDetails->muteReg
)
{
/*
* It matches. Do some checks.
*/
if ( !mute && pSignalDetails->flags & WM_SIG_VOLUME_MUTE )
{
/*
* This signal is muted by setting the volume value to a special
* value. This means we've lost the information about what the
* volume used to be, so the only way to unmute is to set the
* volume to a non-muted value.
*/
WM_TRACE( hDevice, (
"WMAudioMuteSignal: signal %s has a zero mute - to unmute set new volume",
WMSignalName( signal )
));
status = WMS_UNSUPPORTED;
goto error;
}
/*
* Check whether we need to setup for a new register.
*/
if ( pSignalDetails->muteReg != reg )
{
if ( WM_REG_INVALID != reg )
{
/*
* If we're adding to a previous signal, but it's a different
* register, write the previous one.
*/
status = WMSetField( hDevice, reg, regval, mask );
if ( WM_ERROR( status ) )
{
goto error;
}
}
/* Now initialise our working variables */
reg = pSignalDetails->muteReg;
regval = 0;
mask = 0;
if ( pSignalDetails->flags & WM_SIG_HAS_UPDATE )
{
update = pSignalDetails->special;
}
}
/* Now add this mute */
if ( mute )
regval |= pSignalDetails->mute;
mask |= pSignalDetails->muteMask;
/* Check whether we've got a "both" bit we can use */
if ( pSignalDetails->flags & WM_SIG_HAS_BOTH )
{
regval |= pSignalDetails->special;
mask |= pSignalDetails->special;
break;
}
}
}
/* Did we find it? */
if ( WM_REG_INVALID == reg )
{
status = WMS_UNSUPPORTED;
goto error;
}
/* Now do our final write, setting the update bit if we have one */
if ( update )
{
regval |= update;
mask |= update;
}
/*
* And do the write.
*/
status = WMSetField( hDevice, reg, regval, mask );
if ( WM_ERROR( status ) )
{
goto error;
}
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioIsSignalMuted
*
* Check to see if the signal is muted to all paths.
*
* Parameters:
* hDevice The handle to the device (from WMOpenDevice).
* signal The signal to check.
*
* Returns: WMSTATUS
* WMS_RETURN_TRUE if the signal is muted to all paths.
* WMS_RETURN_FALSE if the signal is unmuted to one or more paths.
* WMS_UNSUPPORTED if the signal is not available on this device.
* See WMStatus.h for all other values and meanings.
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioIsSignalMuted( WM_DEVICE_HANDLE hDevice,
WM_AUDIO_SIGNAL signal
)
{
const WM_SIGNAL_DETAILS *pSignalDetails = NULL;
const WM_CHIPDEF *pChipDef;
WMSTATUS status = WMS_UNSUPPORTED;
unsigned int nSignal;
/*
* Look up our chipdef.
*/
pChipDef = WMGetChipDef( hDevice );
if ( !pChipDef )
{
status = WMS_NO_SUPPORTED_DEVICE;
goto finish;
}
/*
* Run through the signals, looking for ones which match. If we get
* one, check whether it's muted.
*/
for ( nSignal = 0; nSignal < pChipDef->signalCount; nSignal++ )
{
pSignalDetails = &pChipDef->pSignalDetails[ nSignal ];
if ( pSignalDetails->signal == signal &&
WM_REG_INVALID != pSignalDetails->muteReg
)
{
WM_REGTYPE muteReg = pSignalDetails->muteReg;
WM_REGVAL signalMute = pSignalDetails->mute;
WM_REGVAL muteMask = pSignalDetails->muteMask;
WM_REGVAL signalVal;
/* It matches. Check the mute. */
WMRead( hDevice, muteReg, &signalVal );
if ( signalMute != ( signalVal & muteMask ) )
{
/* It's not completely muted */
status = WMS_RETURN_FALSE;
break;
}
/* It's muted so far... */
status = WMS_RETURN_TRUE;
}
}
finish:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioVolToDbAdv
*
* Called to calculate the dB volume for a given perceived volume level.
* Experiments have shown that a 10dB increase in sound level corresponds
* approximately to a perceived doubling of loudness. We take 0x10000 as
* 0dBFS, and scale from there (so 0xFFFF is loudest, 0x8000 is -10dBFS,
* 0x4000 is -20dBFS, etc).
*
* Note: Linearly reducing the perceived volume does _not_ result in a linear
* attenuation of the output signal.
*
* Parameters:
* hDevice device handle
* perceivedVolume 16-bit volume where 0xFFFF is 0dBFS
*
* Returns: int
* corresponding volume in 1/16dB steps
*---------------------------------------------------------------------------*/
int WMAudioVolToDbAdv( WM_DEVICE_HANDLE hDevice, unsigned short perceivedVolume )
{
int dbVol = 0;
unsigned short currVal = perceivedVolume;
unsigned int index;
/*
* First we get the 10dB range by shifting until we get a bit in the top.
*/
while ( currVal && !(currVal & 0x8000) )
{
/* Each shift is a halving of the volume, so a 10dB attenuation */
dbVol -= WM_SIGNAL_LEVEL( 10 );
currVal = currVal << 1;
}
/*
* Now we get the rest of the range. The value of the next few bits
* comes from the lookup table. We use significant bits 2:6 as the
* index into our lookup table.
*/
/* Skip the first bit */
index = currVal & 0x7FFF;
/* Now shift down */
index = index >> (16 - VOL_SIGNIFICANT_BITS);
if ( (currVal & VOL_INSIGNIFICANT_MASK) > VOL_INSIGNIFICANT_MASK/2 )
{
index++;
}
WM_ASSERT( hDevice, index < WM_ARRAY_COUNT( s_VolumeTable ) );
WM_ASSERT( hDevice,
0 == currVal ||
s_VolumeTable[index].pattern == (currVal & VOL_SIGNIFICANT_MASK) ||
( index > 0 &&
s_VolumeTable[index-1].pattern == (currVal & VOL_SIGNIFICANT_MASK)
)
);
dbVol -= s_VolumeTable[index].level;
return dbVol;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioSetSignalVolume
*
* Set the perceived volume for the given signal.
* Experiments have shown that a 10dB increase in sound level corresponds
* approximately to a perceived doubling of loudness. We take 0x10000 as
* 0dBFS, and scale from there (so 0xFFFF is loudest, 0x8000 is -10dBFS,
* 0x4000 is -20dBFS, etc).
*
* Note: Linearly reducing the perceived volume does _not_ result in a linear
* attenuation of the output signal.
*
* Parameters:
* hDevice The handle to the device (from WMOpenDevice).
* signal The signal to set.
* volume The level to apply, where 0xFFFF is 0dBFS.
* channels One or more of the WM_CHANNEL_XXX constants.
*
*
* Returns: WMSTATUS
* WMS_SUCCESS - success
* WMS_UNSUPPORTED - signal is not supported, or doesn't
* support volume control
* WMS_NO_SUPPORTED_DEVICE - device support not present
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -