⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recorder.c

📁 基于AVR制作的电话语音录制系统
💻 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 + -