📄 wmaudiosignals.c
字号:
}
/* Now do our final write, setting the update bit if we have one */
if ( update )
{
regval |= update;
mask |= update;
}
status = WMSetField( hDevice, reg, regval, mask );
if ( WM_ERROR( status ) )
{
goto error;
}
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioSetSignalVolumesAdv
*
* Set the signal level relative to full-scale, specifying the level in 1/16dB
* steps relative to full scale. The WM_SIGNAL_LEVEL macro can convert from
* a dB value to the corresponding 1/16dB value. E.g. WM_SIGNAL_LEVEL( 1.5 )
* gives 0x18, which corresponds to 1.5dBFS.
*
* Note: the underlying device will probably not be able to set this level
* precisely. The applied level will be rounded to the nearest available
* step. For example, if the device has a 1.5dB step size (typical of AC'97
* devices), a level of WM_SIGNAL_LEVEL(4) (0x40), WM_SIGNAL_LEVEL(4.125) (0x42),
* WM_SIGNAL_LEVEL(4.5) (0x48) or WM_SIGNAL_LEVEL( 5 ) (0x50) would all
* result in a 4.5dBFS signal.
*
* Parameters:
* hDevice The handle to the device (from WMOpenDevice).
* signal The signal to set.
* leftVol The relative amplification or attenuation to apply,
* in 1/16 dB steps.
* rightVol The relative amplification or attenuation to apply,
* in 1/16 dB steps.
*
* 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
* See WMStatus.h for all other values and meanings.
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioSetSignalVolumesAdv( WM_DEVICE_HANDLE hDevice,
WM_AUDIO_SIGNAL signal,
int leftVol,
int rightVol
)
{
WMSTATUS status;
if ( leftVol == rightVol )
{
/*
* Call through to our helper function.
*/
status = WMAudioSetSignalVolumeAdv( hDevice,
signal,
leftVol,
WM_CHANNEL_ALL
);
if ( WM_ERROR( status ) )
goto finish;
}
else
{
status = WMAudioSetSignalVolumeAdv( hDevice,
signal,
leftVol,
WM_CHANNEL_LEFT
);
if ( WM_ERROR( status ) )
goto finish;
status = WMAudioSetSignalVolumeAdv( hDevice,
signal,
rightVol,
WM_CHANNEL_RIGHT
);
if ( WM_ERROR( status ) )
goto finish;
}
finish:
/*
* And return.
*/
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioGetSignalVolumeDb
*
* Returns the signal level relative to full-scale, rounded to the nearest dB
* relative to a full-scale signal.
*
* Note: If multiple channels are specified (e.g. WM_CHANNEL_STEREO) this function
* assumes all channels are at the same level and returns the level of the first
* channel it finds. To check for different levels on different channels, call this
* function once for each channel (e.g. once with WM_CHANNEL_LEFT and once with
* WM_CHANNEL_RIGHT).
*
* Parameters:
* hDevice The handle to the device (from WMOpenDevice).
* signal The signal to get.
* pVol Receives the relative signal level in decibels.
* channel One 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
* See WMStatus.h for all other values and meanings.
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioGetSignalVolumeDb( WM_DEVICE_HANDLE hDevice,
WM_AUDIO_SIGNAL signal,
int *pVol,
WM_AUDIO_CHANNELS channel
)
{
return private_GetSignalVolumeUnits( hDevice,
signal,
pVol,
channel,
WM_SIGNAL_LEVEL( 1 )
);
}
/*-----------------------------------------------------------------------------
* Function: WMAudioGetSignalVolumeAdv
*
* Returns the signal level relative to full-scale, using 1/16dB steps.
*
* Note: If multiple channels are specified (e.g. WM_CHANNEL_STEREO) this function
* assumes all channels are at the same level and returns the level of the first
* channel it finds. To check for different levels on different channels, call this
* function once for each channel (e.g. once with WM_CHANNEL_LEFT and once with
* WM_CHANNEL_RIGHT).
*
* Parameters:
* hDevice The handle to the device (from WMOpenDevice).
* signal The signal to get.
* pVol Receives the relative signal level in 1/16 dB steps.
* channel One 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
* See WMStatus.h for all other values and meanings.
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioGetSignalVolumeAdv( WM_DEVICE_HANDLE hDevice,
WM_AUDIO_SIGNAL signal,
int *pVol,
WM_AUDIO_CHANNELS channel
)
{
return private_GetSignalVolumeUnits( hDevice,
signal,
pVol,
channel,
1
);
}
/*-----------------------------------------------------------------------------
* Function: private_GetSignalVolumeUnits
*
* Returns the signal level relative to full-scale in multiples of the given
* unit.
*
* Note: If multiple channels are specified (e.g. WM_CHANNEL_STEREO) this function
* assumes all channels are at the same level and returns the level of the first
* channel it finds. To check for different levels on different channels, call this
* function once for each channel (e.g. once with WM_CHANNEL_LEFT and once with
* WM_CHANNEL_RIGHT).
*
* Parameters:
* hDevice The handle to the device (from WMOpenDevice).
* signal The signal to get.
* pVol Receives the relative signal level in decibels.
* channel One of the WM_CHANNEL_XXX constants.
* baseUnit The unit size to return (in 1/16dB steps)
*
* Returns: WMSTATUS
* WMS_SUCCESS - success
* WMS_UNSUPPORTED - signal is not supported, or doesn't
* support volume control
* WMS_NO_SUPPORTED_DEVICE - device support not available in this build
*---------------------------------------------------------------------------*/
static WMSTATUS private_GetSignalVolumeUnits( WM_DEVICE_HANDLE hDevice,
WM_AUDIO_SIGNAL signal,
int *pVol,
WM_AUDIO_CHANNELS channel,
int baseUnit
)
{
WMSTATUS status = WMS_UNSUPPORTED;
const WM_SIGNAL_DETAILS *pSignalDetails = NULL;
const WM_CHIPDEF *pChipDef;
unsigned int nSignal;
int baseVol;
WM_REGTYPE reg = WM_REG_INVALID;
/*
* Make sure that the signal is valid.
*/
if ( !WM_SIGNAL_IS_VALID( signal ) )
{
status = WMS_UNSUPPORTED;
goto error;
}
/*
* Look up our chipdef.
*/
pChipDef = WMGetChipDef( hDevice );
if ( !pChipDef )
{
status = WMS_NO_SUPPORTED_DEVICE;
goto error;
}
/*
* Run through the signals, looking for the first one which matches.
*/
for ( nSignal = 0; nSignal < pChipDef->signalCount; nSignal++ )
{
pSignalDetails = &pChipDef->pSignalDetails[ nSignal ];
if ( pSignalDetails->signal == signal &&
WM_REG_INVALID != pSignalDetails->reg
)
{
/* The signal matches. Does the channel? */
if ( ( WM_CHANNEL_ALL == channel ) ||
( 0 == ( pSignalDetails->flags & WM_CHANNEL_ALL ) ) ||
( 0 != ( channel & pSignalDetails->flags ) )
)
{
int regVol;
WM_REGVAL regval;
int step;
/*
* It matches. Get the current value.
*/
reg = pSignalDetails->reg;
status = WMRead( hDevice, reg, ®val );
if ( WM_ERROR( status ) )
{
goto error;
}
/* Mask and shift */
regval &= pSignalDetails->mask;
regVol = regval >> pSignalDetails->shift;
/* Now work out the dB value (in 1/16dB steps) */
regVol -= pSignalDetails->zerodB;
step = pSignalDetails->step;
baseVol = regVol * step;
/*
* Now convert into the appropriate units.
*/
if ( baseUnit > 1 )
{
/*
* Work out what is the largest value less than half a unit
* (i.e. the largest value we can add to an exact multiple
* of the unit so we can guarantee it will not change on
* rounding.
*/
int halfUnit = baseUnit/2;
halfUnit = halfUnit - 1;
/*
* Add it to the baseVol so it will round the right way.
*/
if ( baseVol > 0 )
baseVol += halfUnit;
else
baseVol -= halfUnit;
baseVol = baseVol / baseUnit;
}
/* And we're done */
break;
}
}
}
/* Did we find it? */
if ( WM_REG_INVALID == reg )
{
status = WMS_UNSUPPORTED;
goto error;
}
/*
* Return the value.
*/
*pVol = baseVol;
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioSetOutputAttenuations
*
* Called to set the left and right channel attenuations applied to a
* given analogue output. For example, a 0dBFS input with 6dB attenuation
* would result in a -6dBFS signal from the output.
*
* Note: the underlying device may not use dB step sizes. In this case the
* applied attenuation will be rounded to the nearest available step.
* For example, if the device has a 1.5dB step size
* (typical of AC'97 devices), an attenuation of either 4dB or 5dB would
* result in a -4.5dBFS signal.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* outputL left output to attenuate
* outputR right output to attenuate
* attenuationdBLeft left channel attenuation to apply in dB steps.
* attenuationdBRight right channel attenuation to apply in dB steps.
*
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioSetOutputAttenuations( WM_DEVICE_HANDLE hDevice,
WM_AUDIO_SIGNAL outputL,
WM_AUDIO_SIGNAL outputR,
int attenuationdBLeft,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -