📄 recorder.c
字号:
/* [KSC4]-------------------------------------------------------------------[]
*
* RECORDER.C - Test program for the AVR phone recorder, version 0.1
* Written by AT3344.
*
* []-----------------------------------------------------------------------[]
*/
#include <time.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "commands.h"
#define BAUD_RATE B115200
#define FALSE 0
#define TRUE 1
/* --------------------------- Macro-declared Constants ------------------- */
#define MAXLINELENGTH 80
/* ---------------------- Declarations and Global Variables --------------- */
char *device=NULL;
char timestamp=FALSE;
int raw_mode=0;
/* Intel ADPCM step variation table */
static char indexTable[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8,
};
static int stepsizeTable[89] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};
int abuf_tail;
char abuf[AUDIO_BLOCK_LENGTH];
short sbuf[AUDIO_BLOCK_LENGTH*2];
/* ADPCM state */
struct adpcm_state {
short valprev; /* Previous output value */
char index; /* Index into stepsize table */
} state;
/* ---------------------------- Function Prototypes ----------------------- */
void handle_values(char *buf);
void save_random_data(FILE *fp,char *buf);
void print_timestamp();
void audio_decode(char c);
void adpcm_decoder(char indata[], short outdata[], int len,
struct adpcm_state *state);
/* ------------------------------- Main Program --------------------------- */
main(int argc, char **argv)
{
FILE *fp=NULL;
int fd,res,a,n;
struct termios oldtio,newtio;
unsigned char c;
int in_cmd,adpcm_cnt,in_sync,has_state=0;
struct adpcm_state mystate;
char *cmds=NULL;
char *pbfilename=NULL;
int recording_in_progress=TRUE;
if (argc<2) {
fprintf(stderr,"usage: read <device>\n");
exit(1);
}
for (a=0,n=1;n<argc;n++) {
if (argv[n][0]=='-') {
switch(argv[n][1]) {
case 'c':
cmds=argv[n][2] ? argv[n]+2 : argv[n++];
break;
case 'p':
pbfilename=argv[n][2] ? argv[n]+2 : argv[n++];
break;
}
} else {
switch(a) {
case 0: device=argv[n];
break;
}
a++;
}
}
fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd < 0) {
fprintf(stderr,"Can't open %s\n",device);
exit(1);
}
FILE *infp=fopen(pbfilename,"rb");
unsigned char *outdata=NULL;
int outsize,outindex=0;
if (infp) {
fseek(infp,0,SEEK_END);
outsize=ftell(infp);
fprintf(stderr,"size=%d\n",outsize);
outdata=malloc(outsize);
if (!outdata) {
fclose(infp);
fprintf(stderr,"unable to alloc all that, aborting\n"); exit(1);
}
fseek(infp,0,SEEK_SET);
fread(outdata,1,outsize,infp);
fclose(infp);
}
tcgetattr(fd,&oldtio); /* save current port settings */
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUD_RATE | CS8 | CLOCAL | CREAD | CRTSCTS;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
cfsetospeed(&newtio,BAUD_RATE);
cfsetispeed(&newtio,BAUD_RATE);
/* set input mode (non-canonical, no echo,...) */
newtio.c_lflag = 0;
newtio.c_cc[VTIME]=0;
newtio.c_cc[VMIN] =1;
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
if (cmds) {
char tst[5];
tst[0]=CMD_BLOCK_START;
char *p=cmds;
for (;*p;p++) {
switch (*p) {
case 'b': tst[1]=CMD_LCD_BACKLIGHT_OFF;
write(fd,tst,2);
break;
case 'B': tst[1]=CMD_LCD_BACKLIGHT_ON;
write(fd,tst,2);
break;
case 'h': tst[1]=CMD_GO_OFF_HOOK;
write(fd,tst,2);
break;
case 'H': tst[1]=CMD_GO_ON_HOOK;
write(fd,tst,2);
break;
case 'c': {
time_t tt;
struct tm *t;
time(&tt); t=localtime(&tt);
fprintf(stderr,"Setting time to "
"%02d:%02d:%02d... ",t->tm_hour,
t->tm_min,t->tm_sec);
tst[1]=CMD_SET_TIME;
tst[2]=t->tm_hour;
tst[3]=t->tm_min;
tst[4]=t->tm_sec;
write(fd,tst,5);
fprintf(stderr,"done\n");
}
break;
case 'C': {
time_t tt;
struct tm *t;
time(&tt); t=localtime(&tt);
fprintf(stderr,"Setting date to "
"%02d-%02d-%02d... ",t->tm_year-100,
t->tm_mon+1,t->tm_mday);
tst[1]=CMD_SET_DATE;
tst[2]=t->tm_year-100;
tst[3]=t->tm_mon+1;
tst[4]=t->tm_mday;
write(fd,tst,5);
fprintf(stderr,"done\n");
}
break;
}
}
}
in_cmd=0; adpcm_cnt=0; in_sync=0;
long count=0,divcnt=0;
for (;;) {
if (!divcnt) {
if (outdata) {
char buf[8000];
int n,buflen=0;
for (n=0;n<1;n++) {
unsigned char c=outdata[outindex++];
if (outindex>=outsize) outindex=0;
buf[buflen++]=c;
if (c==CMD_BLOCK_START) buf[buflen++]=c;
}
write(fd,buf,buflen);
}
divcnt=1;
} else {
divcnt--;
}
res = read(fd,&c,1);
if (res>0) {
count++;
if (adpcm_cnt) {
switch(adpcm_cnt) {
case 1: mystate.valprev=c;
adpcm_cnt=2;
break;
case 2: mystate.valprev|=c<<8;
adpcm_cnt=3;
break;
case 3: mystate.index=c;
if (!has_state) {
state=mystate;
fprintf(stderr,"at %d got state %d %d\n ",
count,mystate.valprev,mystate.index);
}
adpcm_cnt=0; in_cmd=0; has_state=1; in_sync=1;
break;
}
continue;
}
if (in_cmd>0) {
switch (c) {
case CMD_BLOCK_START:
if (in_sync) audio_decode(c);
in_cmd=0;
break;
case CMD_ADPCM_STATE:
adpcm_cnt=1;
break;
case CMD_NOTIFY_ON_HOOK:
in_cmd=0;
fprintf(stderr,"Now on hook\n");
break;
case CMD_NOTIFY_OFF_HOOK:
in_cmd=0;
fprintf(stderr,"Now off hook\n");
break;
case CMD_NOTIFY_DISCONNECTED:
in_cmd=0;
fprintf(stderr,"DISCONNECTED\n");
break;
case CMD_RAW_BLOCK:
if (!raw_mode) fprintf(stderr,"** Raw mode\n");
raw_mode=1; in_sync=1; in_cmd=0;
break;
case CMD_DTMF_DETECTED:
in_cmd=0;
res = read(fd,&c,1);
if (res>0)
fprintf(stderr,"-- DTMF detected = '%c'\n",c);
break;
case CMD_LOCAL_RING_DETECTED:
in_cmd=0;
res = read(fd,&c,1);
if (res>0)
fprintf(stderr,"** LOCAL RING #%d\n",c);
break;
case CMD_RECORDING_STARTED:
in_cmd=0;
recording_in_progress=TRUE;
fprintf(stderr,">> Recoding now in progress\n",c);
break;
case CMD_RECORDING_STOPPED:
in_cmd=0;
recording_in_progress=FALSE;
fprintf(stderr,">> Recoding stopped\n",c);
break;
case CMD_GOERTZEL_DEBUG:
in_cmd=0;
unsigned char n;
res = read(fd,&n,1);
unsigned short x=0;
res = read(fd,&x,1);
res = read(fd,&c,1);
x|=c<<8;
fprintf(stderr,"%6d ",x);
if (n==9) putc('\n',stderr);
break;
}
} else {
if (c==CMD_BLOCK_START) {
in_cmd=1;
} else {
if (in_sync) audio_decode(c);
}
}
}
//usleep(120);
}
tcsetattr(fd,TCSANOW,&oldtio);
fclose(fp);
} /* main */
void audio_decode(char c)
{
int n,s;
if (raw_mode) {
putc(c,stdout); return;
}
abuf[abuf_tail++]=c;
if (abuf_tail==AUDIO_BLOCK_LENGTH) {
abuf_tail=0;
adpcm_decoder(abuf,sbuf,AUDIO_BLOCK_LENGTH*2,&state);
//fwrite(sbuf,2,2*AUDIO_BLOCK_LENGTH,stdout);
for (n=0;n<2*AUDIO_BLOCK_LENGTH;n++) {
s=sbuf[n]+32768;
putc((s>>8)&0xFF,stdout);
}
}
}
/* ---------------------------- Auxiliary Functions ----------------------- */
void
adpcm_decoder(char indata[], short outdata[], int len,
struct adpcm_state *state)
{
signed char *inp; /* Input buffer pointer */
short *outp; /* output buffer pointer */
int sign; /* Current adpcm sign bit */
int delta; /* Current adpcm output value */
int step; /* Stepsize */
int valpred; /* Predicted value */
int vpdiff; /* Current change to valpred */
int index; /* Current step change index */
int inputbuffer; /* place to keep next 4-bit value */
int bufferstep; /* toggle between inputbuffer/input */
outp = outdata;
inp = (signed char *)indata;
valpred = state->valprev;
index = state->index;
step = stepsizeTable[index];
bufferstep = 0;
for ( ; len > 0 ; len-- ) {
/* Step 1 - get the delta value */
if ( bufferstep ) {
delta = inputbuffer & 0xf;
} else {
inputbuffer = *inp++;
delta = (inputbuffer >> 4) & 0xf;
}
bufferstep = !bufferstep;
/* Step 2 - Find new index value (for later) */
index += indexTable[delta];
if ( index < 0 ) index = 0;
if ( index > 88 ) index = 88;
/* Step 3 - Separate sign and magnitude */
sign = delta & 8;
delta = delta & 7;
/* Step 4 - Compute difference and new predicted value */
/*
** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
** in adpcm_coder.
*/
vpdiff = step >> 3;
if ( delta & 4 ) vpdiff += step;
if ( delta & 2 ) vpdiff += step>>1;
if ( delta & 1 ) vpdiff += step>>2;
if ( sign )
valpred -= vpdiff;
else
valpred += vpdiff;
/* Step 5 - clamp output value */
if ( valpred > 32767 )
valpred = 32767;
else if ( valpred < -32768 )
valpred = -32768;
/* Step 6 - Update step value */
step = stepsizeTable[index];
/* Step 7 - Output value */
*outp++ = valpred;
}
state->valprev = valpred;
state->index = index;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -