📄 speaker.c
字号:
/*
Play sound buffer
*/
#include "netfone.h"
/* GSMDECOMP -- Uncompress the contents of a sound buffer using GSM. */
static void gsmdecomp(LPCLIENT_DATA pClientData, soundbuf *sb)
{
gsm_signal dst[160];
int i, j, l = 0;
char *dpx = ((char *) sb->buffer.buffer_val) + sizeof(short);
static char dcb[BUFL];
short declen = ntohs(*((short *) sb->buffer.buffer_val));
if (declen <= 0 || declen > 1600) {
declen = 1600;
}
for (i = 0; i < (int) (sb->buffer.buffer_len - sizeof(short));
i += sizeof(gsm_frame))
{
// Decode audio using client's gsm handle.
gsm_decode(pClientData->gsmh, (gsm_byte *) dpx, dst);
dpx += sizeof(gsm_frame);
for (j = 0; j < 160; j++)
{
dcb[l++] = audio_s2u(dst[j]);
}
}
memcpy(sb->buffer.buffer_val, dcb, declen);
sb->buffer.buffer_len = declen;
}
/* ADPCMDECOMP -- Decompress the contents of a sound buffer using ADPCM. */
void adpcmdecomp( struct soundbuf *sb)
{
#define TINY_PACKETS 512
char *dp = (char *) sb->buffer.buffer_val;
unsigned char *sp;
static unsigned char dob[TINY_PACKETS * 2];
struct adpcm_state adpcm;
/* Restore the decoder state from the copy saved in the packet,
independent of the byte order of the machine we're running on. */
sp = (unsigned char *) dp + (sb->buffer.buffer_len - 3);
adpcm.valprev = (short) ((((int) sp[0]) << 8) | ((int) sp[1]));
adpcm.index = sp[2];
sb->buffer.buffer_len -= 3;
adpcm_decoder_u(dp, dob, (int) (sb->buffer.buffer_len * 2), &adpcm);
sb->buffer.buffer_len *= 2;
memcpy(dp, dob, (size_t) sb->buffer.buffer_len);
}
/* LPCDECOMP -- Uncompress the contents of a sound buffer using LPC. */
static void lpcdecomp(struct soundbuf *sb, LPCLIENT_DATA c)
{
int i, l = 0;
char *dpx = ((char *) sb->buffer.buffer_val) + sizeof(short);
static char dcb[LPC_FRAME_SIZE * 10];
short declen = ntohs(*((short *) sb->buffer.buffer_val));
if (declen <= 0 || declen > LPC_FRAME_SIZE * 10) {
declen = LPC_FRAME_SIZE * 10;
}
for (i = 0; l < declen; i += sizeof(lpcparams_t)) {
lpcparams_t *lp = (lpcparams_t *) (dpx + i);
lpc_synthesize(dcb + l, lp, &(c->lpc_state));
l += LPC_FRAME_SIZE;
}
memcpy(sb->buffer.buffer_val, dcb, declen);
sb->buffer.buffer_len = declen;
}
/* LPC10DECOMP -- Uncompress the contents of a sound buffer using LPC10. */
static void lpc10decomp(struct soundbuf *sb, LPCLIENT_DATA c)
{
int j;
char *dpx = ((char *) sb->buffer.buffer_val);
char dcb[BUFL];
j = lpc10decode(dpx, dcb, sb->buffer.buffer_len);
memcpy(sb->buffer.buffer_val, dcb, j);
sb->buffer.buffer_len = j;
}
/* CELPDECOMP -- Uncompress the contents of a sound buffer encoded in CELP. */
static void celpdecomp(struct soundbuf *sb, LPCLIENT_DATA c)
{
short dst[240];
unsigned int i;
int j, l = 0;
char *dpx = ((char *) sb->buffer.buffer_val) + sizeof(short);
static char dcb[BUFL];
short declen = ntohs(*((short *) sb->buffer.buffer_val));
if (declen <= 0 || declen > 1920) {
declen = 1920;
}
for (i = 0; i < sb->buffer.buffer_len - sizeof(short);
i += 18) {
#ifdef CELP_USE_CONTEXT
if (c->d_celp_ctx == NULL) {
c->d_celp_ctx = (struct celp_context *) GlobalAllocPtr(GPTR, sizeof(struct celp_context));
if (c->d_celp_ctx == NULL) {
return;
}
celp_context_init(c->d_celp_ctx);
celp_init(c->d_celp_ctx, FALSE);
}
celp_decode(c->d_celp_ctx, dpx, dst);
#else
celp_decode(dpx, dst);
#endif
dpx += 18;
for (j = 0; j < 240; j++) {
dcb[l++] = audio_s2u(dst[j]);
}
}
memcpy(sb->buffer.buffer_val, dcb, declen);
sb->buffer.buffer_len = declen;
}
// AES_cbc_decrypt -- Decrypt buffer with AES.
void AES_cbc_decrypt(unsigned char *in,
unsigned char *out,
int len, aes_ctx *ctx)
{
int i, j;
unsigned char feedback[AES_BLOCK_SIZE], fbnext[AES_BLOCK_SIZE];
// Initially zero the feedback buffer.
memset(feedback, 0, AES_BLOCK_SIZE);
Assert((len % AES_BLOCK_SIZE) == 0); // Attempt to encrypt non-multiple of block length
// Loop over encryption blocks in the buffer.
for (i = 0; i < len; i += AES_BLOCK_SIZE) {
// Save encrypted block as feedback for the following block.
memcpy(fbnext, in, AES_BLOCK_SIZE);
// Decrypt the current block.
aes_dec_blk(in, out, ctx);
// XOR it with the encrypted previous block saved in feedback.
for (j = 0; j < AES_BLOCK_SIZE; j++) {
out[j] ^= feedback[j];
}
// Move saved encrypted present block to feedback buffer.
memcpy(feedback, fbnext, AES_BLOCK_SIZE);
// Advance input and output pointers to next block.
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
}
/* DECODESOUNDPACKET -- Decode a sound buffer into a Windows
LPWAVEHDR structure compatible with the audio
output device. The sound buffer is decrypted,
decompressed, sample-rate adjusted, and
bits-per-sample transformed as required.
If saveSamp is TRUE, the decrypted and
decompressed 8000 u-law sample per second
canonical data will be saved in a dynamically buffer
linked to the end of the WAVEHDR. This is used
to permit the Audio Monitor to show the spectrum in
real time as the audio is played. Note that if you
set saveSamp, your wh buffer *must* have room at
the end after sizeof(SAVEHDR) to hold the required
(char *) for the saved sample buffer. */
static void decodeSoundPacket(LPCLIENT_DATA pClientData, soundbuf *d,
int bitsPerSample, int samplesPerSecond, LPWAVEHDR wh,
BOOL saveSamp)
{
short *sbuf;
unsigned char *ulp;
int i, len;
char *val, **specsamp;
static unsigned char auxbuf[BUFL + 2];
int bufferMicroseconds;
#ifdef CRYPTO
char bbuf[8], tbuf[8];
#endif
/* If the audio monitor is displayed and displaying input,
hide the original samples in a buffer linked to a
cell at the end of the wave header so we can update the
spectrum synchronously with the playing of the audio. */
if (saveSamp) {
specsamp = (char **) (((char *) wh) + sizeof(WAVEHDR));
*specsamp = NULL;
}
/* Perform requested decryption and decompression of the
received data. */
len = (int) d->buffer.buffer_len;
val = d->buffer.buffer_val;
/* If the fSetDest bit is on, turn up the volume all the way
if fDestJack is set. This indicates an attempt to get the
user's attention, even in case he's turned the volume all
the way down. This only happens if the user has requested
it by setting the "Set Maximum Volume on Ring" workaround.
Why? Well, for public consumption we say that it's annoying
to allow a remote user to override your chosen volume level.
In reality, the primary motivation is that volume setting is
one of the buggiest areas in sound card drivers and, without
naming names, a recent (admittedly beta) driver from the
largest vendor of sound cards for a (supposedly final release)
operating system from the largest vendor of such products
appears to zero the microphone gain whenever you set the output
volume. Imagine what fun this causes for users and how many
E-mails to your humble author this results in. So, pull it
unless the user explicitly enables the volume reset. */
if (waAudioRingMaxVolume && (d->compression & fSetDest)) {
if (!(d->compression & fDestJack)) {
waveOutSetVolume(hWaveOut, (DWORD) MAKELONG(0xFFFF, 0xFFFF));
}
}
#ifdef CRYPTO
/* If message is encrypted, decrypt. */
// Key file
if ((d->compression & fEncOTP) && (pClientData->otpFileName[0])) {
int i, slen = (len + 15) & (~15);
for (i = 0; i < slen; i ++) {
val[i] ^= pClientData->otp[i];
}
}
// PGP/IDEA
if ((d->compression & fEncPGP)) {
unsigned short iv[4];
int slen = (len + 7) & (~7);
char twibble[16];
/* Special gimmick: if we receive a PGP-encrypted packet while
we're still waiting for PGP to complete decrypting the session
key, ditch it. This is a lot easier on the user's ears when
he's trying furiously to enter the private key phrase. */
Assert(pClientData != NULL);
if (pClientData->pgpFileName[0] != 0) {
propeller(IDC_PH_INPUT_LOST, ++inputPacketsLost);
return;
} else if (pClientData->pgpkey[0] != 0) {
memcpy(twibble, pClientData->pgpkey + 1, 16);
memset(iv, 0, sizeof(iv));
initcfb_idea(iv, twibble, TRUE);
ideacfb(val, slen);
close_idea();
}
}
// AES
if ((d->compression & fEncAES) && pClientData->aes_spec) {
int slen = (len + 15) & (~15);
Assert(pClientData != NULL);
AES_cbc_decrypt((unsigned char *) val, (unsigned char *) val,
slen, &(pClientData->aesDkey));
}
// Blowfish
if ((d->compression & fEncBF) && pClientData->blowfish_spec) {
unsigned char iv[8];
int slen = (len + 7) & (~7);
Assert(pClientData != NULL);
memset(iv, 0, sizeof(iv));
BF_cbc_encrypt((unsigned char *) val,
(unsigned char *) val,
slen, &(pClientData->blowfishkey), iv, BF_DECRYPT);
}
// IDEA
if ((d->compression & fEncIDEA) && pClientData->ideaKeyString[0]) {
unsigned short iv[4];
int slen = (len + 7) & (~7);
char twibble[16];
Assert(pClientData != NULL);
memcpy(twibble, pClientData->ideakey + 1, 16);
memset(iv, 0, sizeof(iv));
initcfb_idea(iv, twibble, TRUE);
ideacfb(val, slen);
close_idea();
}
// DES
if ((d->compression & fEncDES) && pClientData->desKeyString[0]) {
int i;
char twibble[8];
Assert(pClientData != NULL);
memcpy(twibble, pClientData->deskey + 1, 8);
setkey(twibble);
for (i = 0; i < len; i += 8) {
memcpy(tbuf, val + i, 8);
dedes(val + i);
/* Reverse cipher block chaining. */
if (i > 0) {
int j;
for (j = 0; j < 8; j++) {
val[(i + j)] ^= bbuf[j];
}
}
memcpy(bbuf, tbuf, 8);
}
}
#endif
/* If message is compressed, decompress appropriately. */
if (d->compression & fCompGSM) {
Assert(pClientData != NULL);
gsmdecomp(pClientData, d);
len = (int) d->buffer.buffer_len;
}
if (d->compression & fCompADPCM) {
adpcmdecomp(d);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -