*** empty log message ***
This commit is contained in:
parent
d9da365a39
commit
fbbf7b3116
|
@ -23,6 +23,7 @@
|
|||
#include <ifax/isdn.h>
|
||||
#include <ifax/g711.h>
|
||||
#include <ifax/atan.h>
|
||||
#include <ifax/sqrt.h>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Copyright (C) 1999 Oliver Eichler [Oliver.Eichler@regensburg.netsurf.de]
|
||||
*/
|
||||
|
||||
int modulator_V21_construct (ifax_modp self, va_list args);
|
||||
/*int modulator_V21_construct (ifax_modp self, va_list args);*/
|
||||
|
||||
#ifndef __V29_DEMOD
|
||||
#define __V29_DEMOD
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
|
||||
Fax program for ISDN.
|
||||
|
||||
Copyright (C) 1999 Oliver Eichler [oliver.eichler@regensburg.netsurf.de
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
extern unsigned short intsqrt (short x);
|
|
@ -2,7 +2,7 @@ LDFLAGS=-lm
|
|||
CFLAGS=-O2 -g -Wall -pedantic -I../include
|
||||
|
||||
LIBOBJS = bitreverse.o debug.o int2alaw.o module.o sincos.o isdn.o g711.o \
|
||||
rate-7k2-8k-1.o atan.o atantbl.o
|
||||
rate-7k2-8k-1.o atan.o atantbl.o sqrt.o sqrttbl.o
|
||||
|
||||
all: isdnlib.a
|
||||
|
||||
|
|
58
lib/atan.c
58
lib/atan.c
|
@ -75,33 +75,33 @@
|
|||
|
||||
|
||||
#ifdef CALC_TBL
|
||||
void
|
||||
gen_atan_tbl (void)
|
||||
{
|
||||
float x;
|
||||
short y;
|
||||
FILE *fid;
|
||||
int n, i;
|
||||
|
||||
fid = fopen ("atantbl.c", "wt");
|
||||
fprintf (fid, "short atantbl[] = \n");
|
||||
fprintf (fid, "{\n");
|
||||
|
||||
n = 8;
|
||||
for (i = 0; i < 65536; i++)
|
||||
{
|
||||
x = (float) i / 32768;
|
||||
y = (short) (atan (x) / atan (1) * 8192);
|
||||
fprintf (fid, "0x%04X, ", y & 0x0000FFFF);
|
||||
n--;
|
||||
if (!n)
|
||||
{
|
||||
fprintf (fid, "\n");
|
||||
n = 8;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (fid, "};\n\n");
|
||||
fclose (fid);
|
||||
}
|
||||
void
|
||||
gen_atan_tbl (void)
|
||||
{
|
||||
float x;
|
||||
short y;
|
||||
FILE *fid;
|
||||
int n, i;
|
||||
|
||||
fid = fopen ("atantbl.c", "wt");
|
||||
fprintf (fid, "short atantbl[] = \n");
|
||||
fprintf (fid, "{\n");
|
||||
|
||||
n = 8;
|
||||
for (i = 0; i < 65536; i++)
|
||||
{
|
||||
x = (float) i / 32768;
|
||||
y = (short) (atan (x) / atan (1) * 8192);
|
||||
fprintf (fid, "0x%04X, ", y & 0x0000FFFF);
|
||||
n--;
|
||||
if (!n)
|
||||
{
|
||||
fprintf (fid, "\n");
|
||||
n = 8;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (fid, "};\n\n");
|
||||
fclose (fid);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
|
||||
Fax program for ISDN.
|
||||
|
||||
Copyright (C) 1999 Oliver Eichler [oliver.eichler@regensburg.netsurf.de
|
||||
|
||||
This function calculates the angle of a complex number x = real, y = imag.
|
||||
The angle is represented as: 0..360° -> 0x0000..0xFFFFF
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#undef CALC_TBL
|
||||
|
||||
|
||||
#ifdef CALC_TBL
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
extern short sqrttbl[];
|
||||
#endif
|
||||
|
||||
unsigned short intsqrt (short x)
|
||||
{
|
||||
short res;
|
||||
if(x>=0){
|
||||
res = sqrttbl[x];
|
||||
}
|
||||
else{
|
||||
res = (short)0x0FFFF;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef CALC_TBL
|
||||
void
|
||||
gen_sqrt_tbl (void)
|
||||
{
|
||||
float x;
|
||||
short y;
|
||||
FILE *fid;
|
||||
int n, i;
|
||||
|
||||
fid = fopen ("sqrttbl.c", "wt");
|
||||
fprintf (fid, "short sqrttbl[] = \n");
|
||||
fprintf (fid, "{\n");
|
||||
|
||||
n = 8;
|
||||
for (i = 0; i < 32767; i++)
|
||||
{
|
||||
x = (float) i / 32768;
|
||||
y = (short) (sqrt(x) * 32768);
|
||||
fprintf (fid, "0x%04X, ", y & 0x0000FFFF);
|
||||
n--;
|
||||
if (!n)
|
||||
{
|
||||
fprintf (fid, "\n");
|
||||
n = 8;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (fid, "};\n\n");
|
||||
fclose (fid);
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -28,7 +28,7 @@
|
|||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signum.h>
|
||||
/*#include <signum.h>*/
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
|
|
@ -72,8 +72,24 @@
|
|||
#define L_2 0x0013
|
||||
|
||||
#define NIL 0x0
|
||||
#define LISTEN 0x1
|
||||
#define PHASEHUNT 0x2
|
||||
#define ESTIMATEGAIN 0x1
|
||||
#define LISTEN 0x2
|
||||
#define PHASEHUNT 0x3
|
||||
|
||||
#define TAU50
|
||||
#undef TAU30
|
||||
#ifdef TAU50
|
||||
#define AGCESTDLY 50
|
||||
#define TAU 0x0288
|
||||
#endif
|
||||
#ifdef TAU30
|
||||
#define AGCESTDLY 30
|
||||
#define TAU 0x0432
|
||||
#endif
|
||||
#define B 0x7FFF
|
||||
#define LEVEL 0x16D6
|
||||
#define LEVEL63 0x0E63
|
||||
#define SQRT_LEVEL63 0x2AE9
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -105,7 +121,7 @@
|
|||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short agc_gain1;
|
||||
unsigned short agc_gain;
|
||||
unsigned short w;
|
||||
int phi;
|
||||
short a;
|
||||
|
@ -134,8 +150,9 @@
|
|||
short Demod (short s, V29demod_private * priv);
|
||||
short FindSeq2(V29demod_private * priv);
|
||||
short PhaseHuntSeq2(V29demod_private * priv);
|
||||
short agc(short s, V29demod_private * priv);
|
||||
short agc_dummy(short s, V29demod_private * priv);
|
||||
short SymbolMapping(V29demod_private * priv);
|
||||
void agc_estimate(V29demod_private *priv);
|
||||
|
||||
|
||||
void
|
||||
|
@ -160,20 +177,33 @@
|
|||
V29demod_private *priv = (V29demod_private *) self->private;
|
||||
int n;
|
||||
short *ps_s = data;
|
||||
static short max = 0;
|
||||
|
||||
for (n = 0; n < length; n++)
|
||||
{
|
||||
|
||||
if(max<*ps_s){
|
||||
max = *ps_s;
|
||||
printf("max %i\n",max);
|
||||
}
|
||||
|
||||
*ps_s = (*ps_s*0x1300)>>15;
|
||||
switch (priv->state)
|
||||
{
|
||||
|
||||
|
||||
case NIL: /* idle and measure power */
|
||||
DCD (*ps_s, priv);
|
||||
|
||||
ps_s++;
|
||||
break;
|
||||
|
||||
case ESTIMATEGAIN: /* estimate initial input gain */
|
||||
DCD (*ps_s, priv);
|
||||
agc_estimate(priv);
|
||||
ps_s++;
|
||||
break;
|
||||
|
||||
case LISTEN: /* try to detect Segment 2 */
|
||||
*ps_s = agc_dummy(*ps_s, priv);
|
||||
DCD (*ps_s, priv);
|
||||
Demod (*ps_s, priv);
|
||||
FindSeq2(priv);
|
||||
|
@ -182,7 +212,7 @@
|
|||
break;
|
||||
|
||||
case PHASEHUNT: /* synchronize the carrier phase */
|
||||
*ps_s = agc(*ps_s, priv);
|
||||
*ps_s = agc_dummy(*ps_s, priv);
|
||||
DCD (*ps_s, priv);
|
||||
Demod (*ps_s, priv);
|
||||
if(priv->smpl_cnt == 0){
|
||||
|
@ -222,27 +252,42 @@
|
|||
self->command = V29demod_command;
|
||||
self->handle_demand = V29demod_demand;
|
||||
|
||||
priv->w = 0; /* the carrier's omega */
|
||||
priv->phi = 0; /* phi to achive carrier sync. */
|
||||
priv->a = 0x0288; /* equals a tau of 50 for power measurement*/
|
||||
priv->state = NIL; /* state variable for the demodulators statemachine*/
|
||||
priv->dem_index = 0; /* index of the actual demodulated sample within
|
||||
the demodulator buffers */
|
||||
priv->smpl_cnt = -1; /* offset for symbol sync.
|
||||
-1 stands for 'no symb. found' */
|
||||
priv->agc_gain1 = 0x0D55; /* equals 0.8333 in (4:12) format */
|
||||
/*priv->agc_gain1 = 0x1000; /* equals 1 in (4:12) format */
|
||||
priv->w = 0; /* the carrier's omega */
|
||||
priv->phi = 0; /* phi to achive carrier sync. */
|
||||
priv->a = TAU;
|
||||
priv->state = NIL; /* state variable for the demodulators statemachine*/
|
||||
priv->dem_index = 0; /* index of the actual demodulated sample within
|
||||
the demodulator buffers */
|
||||
priv->smpl_cnt = -1; /* offset for symbol sync.
|
||||
-1 stands for 'no symb. found' */
|
||||
priv->agc_gain = 0x0D55; /* equals 0.8333 in (4:12) format */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
short agc(short s, V29demod_private * priv)
|
||||
short agc_dummy(short s, V29demod_private * priv)
|
||||
{
|
||||
|
||||
return (s*priv->agc_gain1)>>12;
|
||||
return (s*priv->agc_gain)>>12;
|
||||
}
|
||||
|
||||
void agc_estimate(V29demod_private *priv)
|
||||
{
|
||||
static int cnt;
|
||||
long num;
|
||||
short g;
|
||||
|
||||
cnt++;
|
||||
if(cnt == AGCESTDLY){
|
||||
num = intsqrt(LEVEL63);
|
||||
num <<= 12;
|
||||
g = num/intsqrt(priv->power);
|
||||
priv->agc_gain = g;
|
||||
printf("I would guess gain is %04X\n", g);
|
||||
priv->state = LISTEN;
|
||||
}
|
||||
|
||||
}
|
||||
short Demod (short s, V29demod_private * priv)
|
||||
{
|
||||
static int cnt = 0;
|
||||
|
@ -353,6 +398,7 @@
|
|||
if(re < 0) point = ReMinusTbl[point];
|
||||
if(im < 0) point = ImMinusTbl[point];
|
||||
|
||||
printf("%i\n",point);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -447,15 +493,26 @@
|
|||
short
|
||||
PhaseHuntSeq2(V29demod_private * priv)
|
||||
{
|
||||
short e;
|
||||
static int cnt = 0;
|
||||
|
||||
/* adjust phi by the current phase difference */
|
||||
priv->phi +=
|
||||
priv->current_symbol.angl -
|
||||
priv->dem_angl[priv->dem_index];
|
||||
|
||||
/*printf("0x%04X\n",priv->dem_re[priv->dem_index]);*/
|
||||
/* toggle symbol */
|
||||
if(priv->current_symbol.angl == DEG180)
|
||||
if(priv->current_symbol.angl == DEG180){
|
||||
if(cnt > 10){
|
||||
e = priv->current_symbol.Re - priv->dem_re[priv->dem_index];
|
||||
/*printf("%04X ",e);*/
|
||||
e = (e * B) >> 18;
|
||||
priv->agc_gain -= e;
|
||||
printf("agc gain: %04X\n",priv->agc_gain);
|
||||
}
|
||||
cnt++;
|
||||
priv->current_symbol = V29_symb_tbl[B9600];
|
||||
}
|
||||
else
|
||||
priv->current_symbol = V29_symb_tbl[A9600];
|
||||
|
||||
|
@ -466,6 +523,7 @@
|
|||
DCD (short s, V29demod_private * priv)
|
||||
{
|
||||
int s_s;
|
||||
|
||||
/* Power Measurement s_s = a*(s[n] ) + s_s[n-1]*(1-a) */
|
||||
|
||||
s_s = (s * s) >> 15;
|
||||
|
@ -474,13 +532,14 @@
|
|||
s_s = s_s + priv->power;
|
||||
|
||||
priv->power = s_s;
|
||||
printf("power: 0x%04X\n",s_s);
|
||||
|
||||
if (s_s < L_MIN){
|
||||
priv->state = NIL;
|
||||
return s_s;
|
||||
}
|
||||
if (s_s > L_2){
|
||||
if(priv->state == NIL) priv->state = LISTEN;
|
||||
if(priv->state == NIL) priv->state = ESTIMATEGAIN;
|
||||
return s_s;
|
||||
}
|
||||
return s_s;
|
||||
|
|
|
@ -91,51 +91,51 @@
|
|||
#define BUFFERSIZE 256
|
||||
#define ATOMICSAMPLES 16
|
||||
|
||||
typedef struct dummy
|
||||
{ /* header for *.WAV-Files */
|
||||
typedef struct dummy
|
||||
{ /* header for *.WAV-Files */
|
||||
/* format, 1st left, 2nd right */
|
||||
char main_chunk[4]; /* 'RIFF' */
|
||||
unsigned long length; /* length of file */
|
||||
char chunk_type[4]; /* 'WAVE' */
|
||||
char sub_chunk[4]; /* 'fmt' */
|
||||
unsigned long length_chunk; /* length sub_chunk, always 16 bytes
|
||||
*/
|
||||
unsigned short format; /* always 1 = PCM-Code */
|
||||
unsigned short channels; /* 1 = Mono, 2 = Stereo */
|
||||
unsigned long ft; /* Sample Freq */
|
||||
unsigned long bytes_per_second; /* Data per sec */
|
||||
unsigned short bytes_per_sample; /* bytes per sample, 1=8 bit, 2=16
|
||||
bit (mono) 2=8 bit, 4=16 bit
|
||||
(stereo) */
|
||||
unsigned short bits_per_sample; /* bits per sample, 8, 12, 16 */
|
||||
char data_chunk[4]; /* 'data' */
|
||||
unsigned long data_length; /* length of data */
|
||||
char main_chunk[4]; /* 'RIFF' */
|
||||
unsigned long length; /* length of file */
|
||||
char chunk_type[4]; /* 'WAVE' */
|
||||
char sub_chunk[4]; /* 'fmt' */
|
||||
unsigned long length_chunk; /* length sub_chunk, always 16 bytes
|
||||
*/
|
||||
unsigned short format; /* always 1 = PCM-Code */
|
||||
unsigned short channels; /* 1 = Mono, 2 = Stereo */
|
||||
unsigned long ft; /* Sample Freq */
|
||||
unsigned long bytes_per_second; /* Data per sec */
|
||||
unsigned short bytes_per_sample; /* bytes per sample, 1=8 bit, 2=16
|
||||
bit (mono) 2=8 bit, 4=16 bit
|
||||
(stereo) */
|
||||
unsigned short bits_per_sample; /* bits per sample, 8, 12, 16 */
|
||||
char data_chunk[4]; /* 'data' */
|
||||
unsigned long data_length; /* length of data */
|
||||
|
||||
}
|
||||
wav_header;
|
||||
|
||||
}
|
||||
wav_header;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
int isdn_fd, dsp_fd;
|
||||
FILE *file_fd;
|
||||
ifax_sint32 dsp_rx_volume, dsp_tx_volume;
|
||||
|
||||
ifax_sint16 tx_buffer[ATOMICSAMPLES];
|
||||
ifax_sint16 rx_buffer[ATOMICSAMPLES];
|
||||
ifax_sint16 dsp_buffer[2 * ATOMICSAMPLES];
|
||||
|
||||
struct queue
|
||||
typedef struct
|
||||
{
|
||||
|
||||
int isdn_fd, dsp_fd;
|
||||
FILE *file_fd;
|
||||
ifax_sint32 dsp_rx_volume, dsp_tx_volume;
|
||||
|
||||
ifax_sint16 tx_buffer[ATOMICSAMPLES];
|
||||
ifax_sint16 rx_buffer[ATOMICSAMPLES];
|
||||
ifax_sint16 dsp_buffer[2 * ATOMICSAMPLES];
|
||||
|
||||
struct queue
|
||||
{
|
||||
int wp, rp, size;
|
||||
ifax_sint16 buffer[BUFFERSIZE];
|
||||
int wp, rp, size;
|
||||
ifax_sint16 buffer[BUFFERSIZE];
|
||||
}
|
||||
input, output;
|
||||
|
||||
wav_header wh;
|
||||
|
||||
}
|
||||
linedriver_private;
|
||||
input, output;
|
||||
|
||||
wav_header wh;
|
||||
|
||||
}
|
||||
linedriver_private;
|
||||
|
||||
|
||||
|
||||
|
@ -152,250 +152,253 @@ linedriver_private;
|
|||
* so the timers may be updated.
|
||||
*/
|
||||
|
||||
static int
|
||||
linedriver_handle (ifax_modp self, void *data, size_t length)
|
||||
{
|
||||
linedriver_private *priv = self->private;
|
||||
ifax_sint16 *src = data;
|
||||
size_t remaining = length;
|
||||
|
||||
// printf("Got: %d\n",length);
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
priv->output.buffer[priv->output.wp++] = *src++;
|
||||
priv->output.size++;
|
||||
if (priv->output.wp >= BUFFERSIZE)
|
||||
priv->output.wp = 0;
|
||||
remaining--;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
static int
|
||||
linedriver_handle (ifax_modp self, void *data, size_t length)
|
||||
{
|
||||
linedriver_private *priv = self->private;
|
||||
ifax_sint16 *src = data;
|
||||
size_t remaining = length;
|
||||
|
||||
// printf("Got: %d\n",length);
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
priv->output.buffer[priv->output.wp++] = *src++;
|
||||
priv->output.size++;
|
||||
if (priv->output.wp >= BUFFERSIZE)
|
||||
priv->output.wp = 0;
|
||||
remaining--;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
work (ifax_modp self)
|
||||
{
|
||||
int wanted, t;
|
||||
ifax_sint32 sp;
|
||||
ifax_uint32 up;
|
||||
linedriver_private *priv = self->private;
|
||||
short p;
|
||||
|
||||
/* Fill output queue by demanding data */
|
||||
while (priv->output.size < ATOMICSAMPLES)
|
||||
{
|
||||
wanted = ATOMICSAMPLES - priv->output.size + 5;
|
||||
static int
|
||||
work (ifax_modp self)
|
||||
{
|
||||
int wanted, t;
|
||||
ifax_sint32 sp;
|
||||
ifax_uint32 up;
|
||||
linedriver_private *priv = self->private;
|
||||
short p;
|
||||
int tmp;
|
||||
|
||||
/* Fill output queue by demanding data */
|
||||
while (priv->output.size < ATOMICSAMPLES)
|
||||
{
|
||||
wanted = ATOMICSAMPLES - priv->output.size + 5;
|
||||
/* printf("Want: %d\n",wanted); */
|
||||
ifax_handle_demand (self->recvfrom, wanted);
|
||||
}
|
||||
|
||||
/* Prepare TX-buffer */
|
||||
priv->output.size -= ATOMICSAMPLES;
|
||||
for (t = 0; t < ATOMICSAMPLES; t++)
|
||||
{
|
||||
priv->tx_buffer[t] = priv->output.buffer[priv->output.rp++];
|
||||
if (priv->output.rp >= BUFFERSIZE)
|
||||
priv->output.rp = 0;
|
||||
}
|
||||
|
||||
if (priv->isdn_fd >= 0)
|
||||
{
|
||||
ifax_handle_demand (self->recvfrom, wanted);
|
||||
}
|
||||
|
||||
/* Prepare TX-buffer */
|
||||
priv->output.size -= ATOMICSAMPLES;
|
||||
for (t = 0; t < ATOMICSAMPLES; t++)
|
||||
{
|
||||
priv->tx_buffer[t] = priv->output.buffer[priv->output.rp++];
|
||||
if (priv->output.rp >= BUFFERSIZE)
|
||||
priv->output.rp = 0;
|
||||
}
|
||||
|
||||
if (priv->isdn_fd >= 0)
|
||||
{
|
||||
/* ISDN is online, send TX-buffer, receive into RX-buffer */
|
||||
}
|
||||
else
|
||||
{
|
||||
for (t = 0; t < ATOMICSAMPLES; t++)
|
||||
{
|
||||
priv->rx_buffer[t] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->dsp_fd >= 0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
for (t = 0; t < ATOMICSAMPLES; t++)
|
||||
{
|
||||
priv->rx_buffer[t] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->dsp_fd >= 0)
|
||||
{
|
||||
/* Soundcard audio monitoring enabled */
|
||||
for (t = 0; t < ATOMICSAMPLES; t++)
|
||||
{
|
||||
|
||||
sp = priv->tx_buffer[t] * priv->dsp_tx_volume;
|
||||
up = sp;
|
||||
up >>= 16;
|
||||
priv->dsp_buffer[2 * t + 0] = up;
|
||||
|
||||
sp = priv->rx_buffer[t] * priv->dsp_rx_volume;
|
||||
up = sp;
|
||||
up >>= 16;
|
||||
priv->dsp_buffer[2 * t + 1] = up;
|
||||
}
|
||||
|
||||
write (priv->dsp_fd, priv->dsp_buffer, 4 * ATOMICSAMPLES);
|
||||
}
|
||||
if (priv->file_fd)
|
||||
{
|
||||
for (t = 0; t < ATOMICSAMPLES; t++)
|
||||
{
|
||||
|
||||
sp = priv->tx_buffer[t] * priv->dsp_tx_volume;
|
||||
up = sp;
|
||||
up >>= 16;
|
||||
priv->dsp_buffer[2 * t + 0] = up;
|
||||
|
||||
sp = priv->rx_buffer[t] * priv->dsp_rx_volume;
|
||||
up = sp;
|
||||
up >>= 16;
|
||||
priv->dsp_buffer[2 * t + 1] = up;
|
||||
}
|
||||
|
||||
write (priv->dsp_fd, priv->dsp_buffer, 4 * ATOMICSAMPLES);
|
||||
}
|
||||
if (priv->file_fd)
|
||||
{
|
||||
/* wave file monitoring enabled */
|
||||
for (t = 0; t < ATOMICSAMPLES; t++)
|
||||
{
|
||||
p = (short) priv->tx_buffer[t];
|
||||
fwrite (&p, sizeof (p), 1, priv->file_fd);
|
||||
}
|
||||
}
|
||||
if (self->sendto)
|
||||
{
|
||||
ifax_handle_input (self->sendto, &priv->tx_buffer[0], ATOMICSAMPLES);
|
||||
}
|
||||
return ATOMICSAMPLES;
|
||||
}
|
||||
for (t = 0; t < ATOMICSAMPLES; t++)
|
||||
{
|
||||
p = (short) priv->tx_buffer[t];
|
||||
tmp = (p*0x0D55);
|
||||
p = tmp>>12;
|
||||
fwrite (&p, sizeof (p), 1, priv->file_fd);
|
||||
}
|
||||
}
|
||||
if (self->sendto)
|
||||
{
|
||||
ifax_handle_input (self->sendto, &priv->tx_buffer[0], ATOMICSAMPLES);
|
||||
}
|
||||
return ATOMICSAMPLES;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
linedriver_destroy (ifax_modp self)
|
||||
{
|
||||
int pos;
|
||||
linedriver_private *priv = self->private;
|
||||
static void
|
||||
linedriver_destroy (ifax_modp self)
|
||||
{
|
||||
int pos;
|
||||
linedriver_private *priv = self->private;
|
||||
|
||||
if (priv->file_fd)
|
||||
{
|
||||
pos = ftell (priv->file_fd);
|
||||
priv->wh.length = pos + 44;
|
||||
priv->wh.channels = 1;
|
||||
priv->wh.ft = 8000;
|
||||
priv->wh.bytes_per_second = 16000;
|
||||
priv->wh.bytes_per_sample = 2;
|
||||
priv->wh.bits_per_sample = 16;
|
||||
priv->wh.data_length = pos;
|
||||
rewind (priv->file_fd);
|
||||
fwrite (&priv->wh, sizeof (wav_header), 1, priv->file_fd);
|
||||
fclose (priv->file_fd);
|
||||
}
|
||||
free (self->private);
|
||||
}
|
||||
|
||||
if (priv->file_fd)
|
||||
{
|
||||
pos = ftell (priv->file_fd);
|
||||
priv->wh.length = pos + 44;
|
||||
static int
|
||||
init_audio ()
|
||||
{
|
||||
int rate = 8000;
|
||||
int stereo = 1;
|
||||
int format = AFMT_S16_LE;
|
||||
int smplsize = 16;
|
||||
int dspfd, bufsize, err = 0;
|
||||
|
||||
dspfd = open ("/dev/dsp", O_WRONLY);
|
||||
err |= ioctl (dspfd, SNDCTL_DSP_GETBLKSIZE, &bufsize);
|
||||
if (bufsize < ATOMICSAMPLES)
|
||||
exit (54);
|
||||
err |= ioctl (dspfd, SNDCTL_DSP_SPEED, &rate);
|
||||
err |= ioctl (dspfd, SNDCTL_DSP_STEREO, &stereo);
|
||||
err |= ioctl (dspfd, SNDCTL_DSP_SAMPLESIZE, &smplsize);
|
||||
err |= ioctl (dspfd, SNDCTL_DSP_SETFMT, &format);
|
||||
|
||||
if (err)
|
||||
exit (3);
|
||||
|
||||
/* printf("dsp_fd=%d err=%d\n",dspfd,err); */
|
||||
|
||||
return dspfd;
|
||||
}
|
||||
|
||||
FILE *
|
||||
init_file (ifax_modp self)
|
||||
{
|
||||
linedriver_private *priv = self->private;
|
||||
|
||||
|
||||
priv->file_fd = fopen ("test.wav", "wb");
|
||||
|
||||
priv->wh.length = 0;
|
||||
priv->wh.channels = 1;
|
||||
priv->wh.ft = 8000;
|
||||
priv->wh.bytes_per_second = 16000;
|
||||
priv->wh.bytes_per_sample = 2;
|
||||
priv->wh.bits_per_sample = 16;
|
||||
priv->wh.data_length = pos;
|
||||
rewind (priv->file_fd);
|
||||
priv->wh.data_length = 0;
|
||||
|
||||
priv->wh.main_chunk[0] = 'R';
|
||||
priv->wh.main_chunk[1] = 'I';
|
||||
priv->wh.main_chunk[2] = 'F';
|
||||
priv->wh.main_chunk[3] = 'F';
|
||||
priv->wh.chunk_type[0] = 'W';
|
||||
priv->wh.chunk_type[1] = 'A';
|
||||
priv->wh.chunk_type[2] = 'V';
|
||||
priv->wh.chunk_type[3] = 'E';
|
||||
priv->wh.sub_chunk[0] = 'f';
|
||||
priv->wh.sub_chunk[1] = 'm';
|
||||
priv->wh.sub_chunk[2] = 't';
|
||||
priv->wh.sub_chunk[3] = 0x20;
|
||||
priv->wh.length_chunk = 0x10;
|
||||
priv->wh.format = 1;
|
||||
priv->wh.data_chunk[0] = 'd';
|
||||
priv->wh.data_chunk[1] = 'a';
|
||||
priv->wh.data_chunk[2] = 't';
|
||||
priv->wh.data_chunk[3] = 'a';
|
||||
priv->wh.length = priv->wh.data_length + sizeof (wav_header);
|
||||
|
||||
fwrite (&priv->wh, sizeof (wav_header), 1, priv->file_fd);
|
||||
fclose (priv->file_fd);
|
||||
}
|
||||
free (self->private);
|
||||
}
|
||||
|
||||
static int
|
||||
init_audio ()
|
||||
{
|
||||
int rate = 8000;
|
||||
int stereo = 1;
|
||||
int format = AFMT_S16_LE;
|
||||
int smplsize = 16;
|
||||
int dspfd, bufsize, err = 0;
|
||||
|
||||
dspfd = open ("/dev/dsp", O_WRONLY);
|
||||
err |= ioctl (dspfd, SNDCTL_DSP_GETBLKSIZE, &bufsize);
|
||||
if (bufsize < ATOMICSAMPLES)
|
||||
exit (54);
|
||||
err |= ioctl (dspfd, SNDCTL_DSP_SPEED, &rate);
|
||||
err |= ioctl (dspfd, SNDCTL_DSP_STEREO, &stereo);
|
||||
err |= ioctl (dspfd, SNDCTL_DSP_SAMPLESIZE, &smplsize);
|
||||
err |= ioctl (dspfd, SNDCTL_DSP_SETFMT, &format);
|
||||
|
||||
if (err)
|
||||
exit (3);
|
||||
|
||||
/* printf("dsp_fd=%d err=%d\n",dspfd,err); */
|
||||
|
||||
return dspfd;
|
||||
}
|
||||
|
||||
FILE *
|
||||
init_file (ifax_modp self)
|
||||
{
|
||||
linedriver_private *priv = self->private;
|
||||
|
||||
return priv->file_fd;
|
||||
}
|
||||
|
||||
|
||||
priv->file_fd = fopen ("test.wav", "wb");
|
||||
static int
|
||||
linedriver_command (ifax_modp self, int cmd, va_list cmds)
|
||||
{
|
||||
linedriver_private *priv = self->private;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
|
||||
case CMD_LINEDRIVER_WORK:
|
||||
return work (self);
|
||||
break;
|
||||
|
||||
case CMD_LINEDRIVER_AUDIO:
|
||||
priv->dsp_fd = init_audio ();
|
||||
break;
|
||||
|
||||
case CMD_LINEDRIVER_FILE:
|
||||
priv->file_fd = init_file (self);
|
||||
break;
|
||||
|
||||
case CMD_LINEDRIVER_CLOSE:
|
||||
linedriver_destroy (self);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv->wh.length = 0;
|
||||
priv->wh.channels = 1;
|
||||
priv->wh.ft = 8000;
|
||||
priv->wh.bytes_per_second = 16000;
|
||||
priv->wh.bytes_per_sample = 2;
|
||||
priv->wh.bits_per_sample = 16;
|
||||
priv->wh.data_length = 0;
|
||||
|
||||
priv->wh.main_chunk[0] = 'R';
|
||||
priv->wh.main_chunk[1] = 'I';
|
||||
priv->wh.main_chunk[2] = 'F';
|
||||
priv->wh.main_chunk[3] = 'F';
|
||||
priv->wh.chunk_type[0] = 'W';
|
||||
priv->wh.chunk_type[1] = 'A';
|
||||
priv->wh.chunk_type[2] = 'V';
|
||||
priv->wh.chunk_type[3] = 'E';
|
||||
priv->wh.sub_chunk[0] = 'f';
|
||||
priv->wh.sub_chunk[1] = 'm';
|
||||
priv->wh.sub_chunk[2] = 't';
|
||||
priv->wh.sub_chunk[3] = 0x20;
|
||||
priv->wh.length_chunk = 0x10;
|
||||
priv->wh.format = 1;
|
||||
priv->wh.data_chunk[0] = 'd';
|
||||
priv->wh.data_chunk[1] = 'a';
|
||||
priv->wh.data_chunk[2] = 't';
|
||||
priv->wh.data_chunk[3] = 'a';
|
||||
priv->wh.length = priv->wh.data_length + sizeof (wav_header);
|
||||
|
||||
fwrite (&priv->wh, sizeof (wav_header), 1, priv->file_fd);
|
||||
|
||||
return priv->file_fd;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
linedriver_command (ifax_modp self, int cmd, va_list cmds)
|
||||
{
|
||||
linedriver_private *priv = self->private;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
|
||||
case CMD_LINEDRIVER_WORK:
|
||||
return work (self);
|
||||
break;
|
||||
|
||||
case CMD_LINEDRIVER_AUDIO:
|
||||
priv->dsp_fd = init_audio ();
|
||||
break;
|
||||
|
||||
case CMD_LINEDRIVER_FILE:
|
||||
priv->file_fd = init_file (self);
|
||||
break;
|
||||
|
||||
case CMD_LINEDRIVER_CLOSE:
|
||||
linedriver_destroy (self);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
linedriver_construct (ifax_modp self, va_list args)
|
||||
{
|
||||
linedriver_private *priv;
|
||||
|
||||
if ((priv = self->private = malloc (sizeof (linedriver_private))) == 0)
|
||||
return 1;
|
||||
|
||||
self->destroy = linedriver_destroy;
|
||||
self->handle_input = linedriver_handle;
|
||||
self->command = linedriver_command;
|
||||
|
||||
priv->input.wp = 0;
|
||||
priv->input.rp = 0;
|
||||
priv->input.size = 0;
|
||||
|
||||
priv->output.wp = 0;
|
||||
priv->output.rp = 0;
|
||||
priv->output.size = 0;
|
||||
|
||||
priv->isdn_fd = -1;
|
||||
priv->dsp_fd = -1;
|
||||
priv->dsp_rx_volume = 0x8000;
|
||||
priv->dsp_tx_volume = 0x6000;
|
||||
|
||||
priv->file_fd = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
linedriver_construct (ifax_modp self, va_list args)
|
||||
{
|
||||
linedriver_private *priv;
|
||||
|
||||
if ((priv = self->private = malloc (sizeof (linedriver_private))) == 0)
|
||||
return 1;
|
||||
|
||||
self->destroy = linedriver_destroy;
|
||||
self->handle_input = linedriver_handle;
|
||||
self->command = linedriver_command;
|
||||
|
||||
priv->input.wp = 0;
|
||||
priv->input.rp = 0;
|
||||
priv->input.size = 0;
|
||||
|
||||
priv->output.wp = 0;
|
||||
priv->output.rp = 0;
|
||||
priv->output.size = 0;
|
||||
|
||||
priv->isdn_fd = -1;
|
||||
priv->dsp_fd = -1;
|
||||
priv->dsp_rx_volume = 0x8000;
|
||||
priv->dsp_tx_volume = 0x6000;
|
||||
|
||||
priv->file_fd = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
5
test.c
5
test.c
|
@ -387,7 +387,7 @@ test_v29demod (void)
|
|||
linedriver->sendto = v29demod;
|
||||
|
||||
ifax_command (modulator, CMD_GENERIC_INITIALIZE);
|
||||
remaining = 20260;
|
||||
remaining = 528;/*20260;*/
|
||||
while (remaining > 0)
|
||||
{
|
||||
remaining -= ifax_command (linedriver, CMD_LINEDRIVER_WORK);
|
||||
|
@ -399,8 +399,7 @@ test_v29demod (void)
|
|||
|
||||
|
||||
|
||||
void
|
||||
main (int argc, char **argv)
|
||||
void main (int argc, char **argv)
|
||||
{
|
||||
|
||||
ifax_debugsetlevel (DEBUG_INFO);
|
||||
|
|
Loading…
Reference in New Issue