You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
7.7 KiB
299 lines
7.7 KiB
|
|
#include "precomp.h"
|
|
|
|
|
|
// SHORT g_BeepSamples[] = {195,-4352,-14484,-8778,397,-1801,2376,12278,6830,-2053};
|
|
SHORT g_BeepSamples[] = {195,-4352,-12484,-8778,397,-1801,2376,10278,6830,-2053};
|
|
|
|
|
|
#define BL 1024
|
|
|
|
|
|
#if 0
|
|
DEFWAVEFORMAT g_wfDefList[] =
|
|
{
|
|
{WAVE_FORMAT_PCM, 1, 22050, 22050, 1, 8, 0},
|
|
{WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8, 0},
|
|
{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8, 0},
|
|
{WAVE_FORMAT_PCM, 1, 5510, 5510, 1, 8, 0},
|
|
{WAVE_FORMAT_ADPCM, 1, 11025, 11025/2, BL, 4, 32, (BL-7)*2+2, 7, 0x0100,0x0000,0x0200,0xFF00,0x0000,0x0000,0x00C0,0x0040,0x00F0,0x0000,0x01CC,0xFF30,0x0188,0xFF18},
|
|
{WAVE_FORMAT_ADPCM, 1, 8000, 8000/2, BL, 4, 32, (BL-7)*2+2, 7, 0x0100,0x0000,0x0200,0xFF00,0x0000,0x0000,0x00C0,0x0040,0x00F0,0x0000,0x01CC,0xFF30,0x0188,0xFF18},
|
|
{WAVE_FORMAT_ADPCM, 1, 5510, 5510/2, BL, 4, 32, (BL-7)*2+2, 7, 0x0100,0x0000,0x0200,0xFF00,0x0000,0x0000,0x00C0,0x0040,0x00F0,0x0000,0x01CC,0xFF30,0x0188,0xFF18},
|
|
{WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8, 0},
|
|
};
|
|
#endif
|
|
|
|
|
|
DEFWAVEFORMAT g_wfDefList[] =
|
|
{
|
|
{WAVE_FORMAT_VOXWARE,1,8000, 16000, 2, 16, 0},
|
|
{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8, 0},
|
|
{WAVE_FORMAT_PCM, 1, 5510, 5510, 1, 8, 0},
|
|
{WAVE_FORMAT_ADPCM, 1, 8000, 4096, 256, 4, 32, 500, 7, 0x0100,0x0000,0x0200,0xFF00,0x0000,0x0000,0x00C0,0x0040,0x00F0,0x0000,0x01CC,0xFF30,0x0188,0xFF18},
|
|
{WAVE_FORMAT_ADPCM, 1, 5510, 2755, 256, 4, 32, 500, 7, 0x0100,0x0000,0x0200,0xFF00,0x0000,0x0000,0x00C0,0x0040,0x00F0,0x0000,0x01CC,0xFF30,0x0188,0xFF18},
|
|
{WAVE_FORMAT_GSM610,1, 8000, 1625, 65, 0, 2, 320, 240, 0},
|
|
{WAVE_FORMAT_ALAW, 1, 8000, 8000, 1, 8, 0},
|
|
{WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8, 0},
|
|
{WAVE_FORMAT_PCM, 1, 8000, 16000, 2, 16, 0},
|
|
};
|
|
|
|
|
|
WAVEFORMATEX * GetDefWaveFormat ( int idx )
|
|
{
|
|
return ((idx < DWF_NumOfWaveFormats) ?
|
|
(WAVEFORMATEX *) &g_wfDefList[idx] :
|
|
(WAVEFORMATEX *) NULL);
|
|
}
|
|
|
|
|
|
ULONG GetWaveFormatSize ( PVOID pwf )
|
|
{
|
|
return (((WAVEFORMAT *) pwf)->wFormatTag == WAVE_FORMAT_PCM
|
|
? sizeof (PCMWAVEFORMAT)
|
|
: sizeof (PCMWAVEFORMAT) + sizeof (WORD) + ((WAVEFORMATEX *) pwf)->cbSize);
|
|
}
|
|
|
|
|
|
BOOL IsSameWaveFormat ( PVOID pwf1, PVOID pwf2 )
|
|
{
|
|
UINT u1 = GetWaveFormatSize (pwf1);
|
|
UINT u2 = GetWaveFormatSize (pwf2);
|
|
BOOL fSame = FALSE;
|
|
|
|
if (u1 == u2)
|
|
{
|
|
fSame = ! CompareMemory1 ((char *)pwf1, (char *)pwf2, u1);
|
|
}
|
|
|
|
return fSame;
|
|
}
|
|
|
|
|
|
void FillSilenceBuf ( WAVEFORMATEX *pwf, PBYTE pb, ULONG cb )
|
|
{
|
|
if (pwf && pb)
|
|
{
|
|
if ((pwf->wFormatTag == WAVE_FORMAT_PCM) && (pwf->wBitsPerSample == 8))
|
|
{
|
|
FillMemory (pb, cb, (BYTE) 0x80);
|
|
}
|
|
else
|
|
{
|
|
ZeroMemory (pb, cb);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void MakeDTMFBeep(WAVEFORMATEX *pwf, PBYTE pb, ULONG cb)
|
|
{
|
|
SHORT *pShort = (SHORT*)pb;
|
|
int nBeepMod = sizeof (g_BeepSamples) / sizeof(g_BeepSamples[0]);
|
|
int nIndex, nLoops = 0;
|
|
BYTE bSample;
|
|
|
|
if (pwf->wBitsPerSample == 16)
|
|
{
|
|
nLoops = cb / 2;
|
|
for (nIndex=0; nIndex < nLoops; nIndex++)
|
|
{
|
|
pShort[nIndex] = g_BeepSamples[(nIndex % nBeepMod)];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nLoops = cb;
|
|
for (nIndex=0; nIndex < nLoops; nIndex++)
|
|
{
|
|
bSample = (g_BeepSamples[(nIndex % nBeepMod)] >> 8) & 0x00ff;
|
|
bSample = bSample ^ 0x80;
|
|
pb[nIndex] = bSample;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
char CompareMemory1 ( char * p1, char * p2, UINT u )
|
|
{
|
|
char i;
|
|
|
|
while (u--)
|
|
{
|
|
i = *p1++ - *p2++;
|
|
if (i) return i;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
short CompareMemory2 ( short * p1, short * p2, UINT u )
|
|
{
|
|
short i;
|
|
|
|
while (u--)
|
|
{
|
|
i = *p1++ - *p2++;
|
|
if (i) return i;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
long CompareMemory4 ( long * p1, long * p2, UINT u )
|
|
{
|
|
long i;
|
|
|
|
while (u--)
|
|
{
|
|
i = *p1++ - *p2++;
|
|
if (i) return i;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
const DWORD WIN98GOLDBUILD = 1998;
|
|
const DWORD WIN98GOLDMAJOR = 4;
|
|
const DWORD WIN98GOLDMINOR = 10;
|
|
|
|
|
|
inline bool ISWIN98GOLD()
|
|
{
|
|
OSVERSIONINFO osVersion;
|
|
BOOL bRet;
|
|
|
|
osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
bRet = GetVersionEx(&osVersion);
|
|
|
|
|
|
if ( bRet &&
|
|
( (osVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
|
|
(osVersion.dwMajorVersion == WIN98GOLDMAJOR) &&
|
|
(osVersion.dwMinorVersion == WIN98GOLDMINOR) // &&
|
|
// (osVersion.dwBuildNumber == WIN98GOLDBUILD)
|
|
)
|
|
)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// dwPacketSize is the size of the audio payload (excludes RTP header)
|
|
// pwf represents the compressed audio format
|
|
HRESULT InitAudioFlowspec(FLOWSPEC *pFlowspec, WAVEFORMATEX *pwf, DWORD dwPacketSize)
|
|
{
|
|
|
|
DWORD dwPacketOverhead = 0;
|
|
OSVERSIONINFO osVersion;
|
|
DWORD dwTotalSize;
|
|
BOOL bRet;
|
|
|
|
|
|
// on Windows 2000 and Win98 OSR, the FLOWSPEC needs to be set without regard
|
|
// to the UDP/IP headers.
|
|
|
|
// On Win98 Gold, FLOWSPEC needs to account for IP/UDP headers
|
|
|
|
// no way to detect this without explicitly checking the version number
|
|
|
|
if (ISWIN98GOLD())
|
|
{
|
|
dwPacketOverhead = IP_HEADER_SIZE + UDP_HEADER_SIZE;
|
|
}
|
|
|
|
dwTotalSize = dwPacketOverhead + dwPacketSize + sizeof(RTP_HDR);
|
|
|
|
// rather than specify the exact minimum bandwidth we need for audio,
|
|
// make it slightly larger (10%) to account for bursts and beginning
|
|
// of talk spurts
|
|
|
|
// peakbandwidth is set another increment above TR, and bucket size
|
|
// is adjusted high as well
|
|
|
|
|
|
pFlowspec->TokenRate = (dwTotalSize * pwf->nAvgBytesPerSec) / dwPacketSize;
|
|
pFlowspec->TokenRate = (11 * pFlowspec->TokenRate) / 10;
|
|
|
|
// peak bandwidth is an ADDITIONAL 10% greater than TokenRate, so it's
|
|
// really a 21% increase over the theoretical minimum
|
|
pFlowspec->PeakBandwidth = (11 * pFlowspec->TokenRate) / 10;
|
|
pFlowspec->TokenBucketSize = dwTotalSize * 4;
|
|
pFlowspec->MinimumPolicedSize = dwTotalSize;
|
|
pFlowspec->MaxSduSize = pFlowspec->MinimumPolicedSize;
|
|
pFlowspec->Latency = QOS_NOT_SPECIFIED;
|
|
pFlowspec->DelayVariation = QOS_NOT_SPECIFIED;
|
|
pFlowspec->ServiceType = SERVICETYPE_GUARANTEED;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT InitVideoFlowspec(FLOWSPEC *pFlowspec, DWORD dwMaxBitRate, DWORD dwMaxFrag, DWORD dwAvgPacketSize)
|
|
{
|
|
DWORD dwPacketOverhead = 0;
|
|
|
|
|
|
// I-Frames will be fragmented into 3 or 4 packets
|
|
// and will be about 1000 bytes each
|
|
|
|
// P-Frames average about 250 - 500 bytes each
|
|
|
|
// we'll assume the reservation is a NetMeeting to NetMeeting call
|
|
// so there will be few I-Frames sent
|
|
|
|
|
|
|
|
if (ISWIN98GOLD())
|
|
{
|
|
dwPacketOverhead = IP_HEADER_SIZE + UDP_HEADER_SIZE;
|
|
}
|
|
|
|
// for 28.8 modems, 11kbits/sec have already been allocated for audio
|
|
// so only allocate 17kbits/sec for video. This means that some packets
|
|
// will be "non-conforming" and may receive less than a best-effort services.
|
|
// but this is believed to be better than having no RSVP/QOS at all
|
|
|
|
// if this becomes an issue, then it may be better to have no RSVP/QOS at all
|
|
|
|
// maxBitRate will be equal to 14400 (14.4 modem), 28000 (28.8 modem), 85000 (ISDN/DSL), or 621700 (LAN)
|
|
// (* .70, so really it can be: 10080, 20160, 59500, 435190)
|
|
|
|
|
|
if (dwMaxBitRate <= BW_144KBS_BITS)
|
|
{
|
|
dwMaxBitRate = 4000; // is it worth it to attempt QOS at 14.4 ?
|
|
}
|
|
else if (dwMaxBitRate <= BW_288KBS_BITS)
|
|
{
|
|
dwMaxBitRate = 17000;
|
|
}
|
|
|
|
|
|
|
|
pFlowspec->TokenRate = dwMaxBitRate / 8;
|
|
pFlowspec->MaxSduSize = dwMaxFrag + dwPacketOverhead + sizeof(RTP_HDR);
|
|
pFlowspec->MinimumPolicedSize = dwAvgPacketSize + dwPacketOverhead;
|
|
pFlowspec->PeakBandwidth = (DWORD)(pFlowspec->TokenRate * 1.2);
|
|
pFlowspec->TokenBucketSize = dwMaxFrag * 3;
|
|
|
|
pFlowspec->Latency = QOS_NOT_SPECIFIED;
|
|
pFlowspec->DelayVariation = QOS_NOT_SPECIFIED;
|
|
pFlowspec->ServiceType = SERVICETYPE_CONTROLLEDLOAD;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|