
Overview
The following table lists the order in which the data appears in the “CALBLOCK&[]” section of a FBDF file header.
| Entry | Number of bytes | Description |
| “CALBLOCK&[]“ | 13 | Section Name |
| comma | 1 | delimiter |
| integer string | variable | length of the section starting at the first byte after the equals. |
| comma & equals | 2 | delimiters |
| string | variable | Name of DLL whose rescale function is called. |
| comma | 1 | delimiter |
| integer string | variable | Ordinal number of rescale function. |
| comma | 1 | delimiter |
| sCalBlock structure | variable | See Note 1. |
| DEVSCALESTRUCT | variable * NumChans | One for each channel is written. See Note 1. |
| array of integers | 2 * NumChans | List of channel numbers. |
| CR/LF | 2 | Carriage return and line feed. |
Note 1: These structures have grown with newer versions of HDI. The following sections will show you how to deal with how much of a particular structure is present in an existing FBDF file.
Structures
The following are the 2 structures written to the FBDF header as of HDI v1.60.
typedef struct tagDEVSCALESTRUCT
{
int nLen; // size of the structure
float fFactor; // Scale Factor for channel, used during scaling
float fOffset; // Scale Offset for channel, used during scaling
float fFactor2; // Scale Factor 2, if needed, for channel used during scaling
float fOffset2; // Scale Offset 2, if needed, for channel used during scaling
float CALLBACK (*lpNonLinearScale)(int, lpCalBlock, float );
// OEM supplied callback to support non-linear ranges
} DEVSCALESTRUCT;
typedef struct tagCalBlock
{
float fVersion; // Version of the structure
int nLen; // Size of the structure
int nInterleave; // Number of channels in the raw unsigned buffer
int nFloatInterleave; // Number of channels in the float buffer
long lBufLength; // Size of the buffer
WORD wAndMask; // And mask used with raw data 16-bits or less
WORD wXorMask; // Xor mask used with raw data 16-bits or less
WORD wCalBlockSize; // Size of the structure
WORD wScaleBlockSize; // Size of the scale block array in bytes
LPDEVSCALESTRUCT lpScaleBlock; // Pointer to array of DEVSCALESTRUCT structures. One for each channel
int *lpOffset; // Pointer to array of channel offsets
int *nCh; // Pointer to array of physical channel numbers
enumSAMPLEFORMAT eSampleFormat; // Sample format of the data. Used with enumSAMPLEFORMAT
unsigned long uAndMask32; // And mask used with raw data 32-bits or less
unsigned long uXorMask32; // Xor mask used with raw data 32-bits or less
int nDevice; // Device number the element belongs to
} sCalBlock;
Example Code
The following code excerpt assumes you have already read the header into a buffer called lpBuf and that a “CALBLOCK&[]” section exists.
// declare some variables
sCalBlock CalBlock;
DEVSCALESTRUCT DevScale;
// find the start of the "CALBLOCK&[]" section in lpBuf
char *lpCalBlock = strstr( lpBuf, "\"CALBLOCK&[]\"" );
lpCalBlock += 14; // skip "CALBLOCK&[]",
char *lpTmp = strtok( lpCalBlock, “,” ); // NULL comma after section length
// get section length
int nSectionLen = atoi( lpTmp );
lpTmp = strtok( 0, “,” ); // NULL comma after dll name
lpTmp++; // skip the equal sign
// At this point lpTmp points to the dll name
lpTmp = strtok( 0, “,” ); // NULL comma after ordinal number
int nOrdinal = atoi( lpTmp );
// skip ordinal number
while( *lpTmp )
lpTmp++;
// skip NULL after ordinal number
lpTmp++;
// At this point lpTmp points to the start of the sCalBlock structure.
// Lets get the size of the sCalBlock saved in this file.
// From the structure definition above we know the length is at bytes 4&5.
// Could be smaller than the current structure.
int nCalBlockLen = *((int *)(lpTmp+4));
// copy from byte stream lpTmp into our local CalBlock variable.
memcpy( &CalBlock, lpTmp, nCalBlockLen );
// skip the cal block structure.
lpTmp += CalBlock.nLen;
// At this point lpTmp points to the start of the DEVSCALESTRUCT(s). One per channel.
// Calculate the size of one of these structures saved in this file. Could be smaller than
// the current structure.
int nSBLen = CalBlock.wScaleBlockSize / CalBlock.nInterleave;
// create an array of DEVSCALESTRUCT(s) off of the CalBlock structure. One per channel.
CalBlock.lpScaleBlock = new DEVSCALESTRUCT [ CalBlock.nInterleave ];
// copy from byte stream lpTmp into our local DEVSCALESTRUCT array.
for( int i=0; i < CalBlock.nInterleave; i++ )
{
memcpy( &(CalBlock.lpScaleBlock[i]), lpTmp, nSBLen );
lpTmp += nSBLen; // skip DEVSCALESTRUCT for ith channel.
}
// At this point lpTmp points to the start of the channel numbers.
WORD *lpChs = new WORD [ CalBlock.nInterleave ];
// copy from byte stream lpTmp into our local channel numbers array.
memcpy( lpChs, lpTmp, CalBlock.nInterleave * sizeof( WORD ) );
Scaling the Data
The following code excerpt shows how to scale one sample stored in the unsigned variable uSample. Assume its from channel 0.
float fVal = ((uSample ^ CalBlock.wXorMask) & CalBlock.wAndMask) *
CalBlock.lpScaleBlock[0].fFactor + CalBlock.lpScaleBlock[0].fOffset;





