Simple automatic telephone audio recording in linux.

Written in C code.

This program can be used to record from almost any audio source.
It is tested on a stationary ISDN telephone, where the audio is taken from the two wires going up to the handset.
The audio is DC separated by two capacitors before it enters the sound card on the computer.
This program records 1 second of audio, and then evaluates if the signal level is above a sertain noise limit. If so, then the program stores the recorded audio to a file and starts evaluating the next second. If there is silence for 10 seconds, then the file is closed, and the program starts over.
The stored files will have their filenames equal to the date and time of the start of the recorded audio, and the files will automatically be converted to the compressed .ogg format and then encryptet with a public gpg key.
This program can be used to automatically record all conversations - each in a separate file. So when an important conversation has taken place, the audio will be available for re-play.

Note 1: If two calls have less than 10 seconds of silence in between, then the calls will be saved in one common file.
Note 2: The file can not be played back during recording, as this program blocks the sound card device. So play back the file on a separate computer or stop the recording program before playing back the files.
/* 
 * autorec_v103.c
 *
 * 2009-01-07: Default noise limit changed from 1 to 0.5.
 * Possible to specify noise level at the command line at runtime. If not specified, the default of 0.5 is used.
 * Started with "<programname> 0.4" to get a noise level of 0.4
 *
 * 2008-03-07: Changed program to only read from /dev/dsp (so that it will not
 * block for other programs writing to /dev/dsp for play back).
 *
 * Runs until Control-C is pressed.
 * Compile like this: gcc -o autorec_v102 autorec_v102.c && chmod 744 autorec_v102
 * Storing ALSA-settings: /usr/sbin/alsactl -f alsa_settings.copy store
 * Decrypt files like this (needs private key and password):
 *   gpg -o <output_filename> -d <input_filename>
 *   ex: gpg -o out.ogg -d 20080225_181220.ogg.gpg
 *
 * The program flow is like this:
 * Get input (one second of data) and evaluate if data or noise.
 * If data=true & recording=false: Generate filename
 *                                 Start recording to file
 *                                 Set variable "recording" to true.
 *                                 Set "number_of_silent_runs" to zero.
 * If data=true & recording=true:  Add data to open file.
 *                                 Set "number_of_silent_runs" to zero.
 *                                 Append data to file.
 * If data=false & recording=true. Increment "number_of_silent_runs".
 *    If "number_of_silent_runs" > 10:
 *                                 Close file.
 *                                 Remove last 10 seconds in file (is silence).
 *                                 Convert file to ogg format.
 *                                 Encrypt file to gpg
 *                                 Set "recording" to false.
 *    Else   Append data to file.
 */

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <linux/soundcard.h>
#include <time.h>

#define LENGTH 1    /* how many seconds of speech to store */
#define RATE 8000   /* the sampling rate */
#define SIZE 8      /* sample size: 8 or 16 bits */
#define CHANNELS 1  /* 1 = mono 2 = stereo */
#define NOISE_LIMIT 0.5  /* The limit for average amplitude for deciding to record or not */
#define DEBUG 0     /* If DEBUG=1 then print extra information to screen. */
unsigned char buf[LENGTH*RATE*SIZE*CHANNELS/8]; /* buffer holding digitized audio */


int write_buf_to_file(FILE *fptr){  // Function to write 1 second of audio data to file.
  if(fwrite(buf,sizeof(buf),1,fptr) != 1){
    printf("\nError. Can not write to file.\n");
    return 1;
  } else {
    if (DEBUG) printf("Have now written data to file.\n");
    return 0;
  }
}

int read_buf_from_file(FILE *fptr){  // Function to read 1 second of audio from file.
  if(fread(buf,sizeof(buf),1,fptr) != 1){
    printf("\nError. Can not read from file.\n");
    return 1;
  } else {
    if (DEBUG) printf("Have now read data from file.\n");
    return 0;
  }
}

int main(int argc,char *argv[])
{
  int fd;	/* sound device file descriptor */
  int arg;	/* argument for ioctl calls */
  int status;   /* return status of system calls */
  int number_of_silent_runs = 0; int data=0; int recording=0;
  int index=0; int avg_norm=0; int count=0;
  float noise_limit_var = 0;
  FILE *fptr;
  FILE *fptr_final;
  char timestring[30]; char filename[30]; char filename_final[30];
  time_t tval;
  struct tm *now;
  char timebuf[128];

  if (argc>2) {
    printf("Program should only be started with max 1 argument. Exiting program.\n");
    exit(0);
  } else if (argc==2) {
    noise_limit_var = atof(argv[1]);
    printf("Using LIMIT value of %f\n",noise_limit_var);
  } else {
    noise_limit_var = NOISE_LIMIT;
    printf("No noise_limit specified as arugment. Using default value %f.\n",noise_limit_var);
  }


  fd = open("/dev/dsp", O_RDONLY);  /* open sound device for read only*/
  if (fd < 0) {
    perror("open of /dev/dsp failed");
    exit(1);
  }

  /* set sampling parameters */
  arg = SIZE;	   /* sample size */
  status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
  if (status == -1)
    perror("SOUND_PCM_WRITE_BITS ioctl failed");
  if (arg != SIZE)
    perror("unable to set sample size");

  arg = CHANNELS;  /* mono or stereo */
  status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
  if (status == -1)
    perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
  if (arg != CHANNELS)
    perror("unable to set number of channels");

  arg = RATE;	   /* sampling rate */
  status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
  if (status == -1)
    perror("SOUND_PCM_WRITE_WRITE ioctl failed");
  while(1) { //loop until Control-C
    if (DEBUG) printf("Now starting to record some sound....");
    index=0; avg_norm=0; count=0;
    status = read(fd, buf, sizeof(buf)); /* record some sound */
    if (status != sizeof(buf))
      perror("Read wrong number of bytes");
    if (DEBUG) printf("Evaluating...");
    while(index<sizeof(buf)) {
      avg_norm = avg_norm + abs(buf[index]-128);
      count++; index++;
    }
    double avg_result= (double) avg_norm/count;
    if (DEBUG) printf("Signal level result %f. ",avg_result);
    if (avg_result > noise_limit_var) data=1; else {data=0;number_of_silent_runs++;}
    if (DEBUG) printf("Data=%d, rec=%d, silent_runs=%d.\n",data,recording,number_of_silent_runs);
    if (data && !recording) { 
      if (DEBUG) printf("Will now start to record to file.\n");
      if (DEBUG) printf("First generating filename.\n");
      /* Get current date and time */
      tval = time(NULL);
      now = localtime(&tval);
      sprintf (timestring,"%02d%02d%02d_%02d%02d%02d",
      now->tm_year+1900, now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
      sprintf (filename, "%s", timestring);
      printf("Starts recording to file %s..... \n",filename);
      if((fptr = fopen(filename,"w+"))==NULL){
        printf("\nError opening file: %s.\n",filename);
        exit(1);
      }
      write_buf_to_file(fptr);
      recording = 1;               // Set variable "recording" to true.
      number_of_silent_runs = 0;   // Set "number_of_silent_runs" to zero.
    } else if (data && recording) {  //  Add data to open file.
      write_buf_to_file(fptr);
      recording = 1;               // Set variable "recording" to true.
      number_of_silent_runs = 0;   // Set "number_of_silent_runs" to zero
    } else if (!data && recording) {
      if (number_of_silent_runs > 10){
	//Copies all from the file (fptr) to another file (fptr_final) excluding the last 10 seconds (which are silence).
	rewind(fptr);
	sprintf (filename_final, "%s.final", filename);
        if((fptr_final = fopen(filename_final,"w"))==NULL){
          printf("\nError: File %s can not be opened!\n",filename_final);
          exit(1);
        }
	fseek(fptr,0,SEEK_END);
	int filesize_fptr=ftell(fptr);   // File size in bytes.
	int file_size_seconds=filesize_fptr/8000;   // File size in seconds.
	rewind(fptr);
	while (file_size_seconds-- > 10) {  // The last 10 seconds should not be included.
	  read_buf_from_file(fptr);
	  write_buf_to_file(fptr_final);
  	  if (DEBUG) printf("Block copied. File_size_seconds is now: %d\n",file_size_seconds);
	}
	int filesize_fptr_final=ftell(fptr_final);
	if (filesize_fptr != filesize_fptr_final + 80000)
	  printf("Error: Final file has other size (%d) than expected (%d)!\n",filesize_fptr_final,filesize_fptr-80000);
	else
	  if (DEBUG) printf("File size seems correct. Recorded %d seconds.\n",filesize_fptr_final/8000);
        fclose(fptr);	             // Close file
	fclose(fptr_final);
	char system_command[100];
	sprintf(system_command,"oggenc -o %s.ogg -B 8 -C 1 -R 8000 -q -1 --quiet %s 2> /dev/null",filename,filename_final);
	if (DEBUG) printf("Is about to run the command: %s\n",system_command);
	system(system_command);
	printf("Recorded %d seconds to file %s.ogg\n\n",filesize_fptr_final/8000, filename); 
	if (DEBUG) printf("Now  pgp encrypting file...");
	sprintf(system_command,"gpg -e -r test %s.ogg",filename);
	if (DEBUG) printf("Is about to run the command: %s\n",system_command);
	system(system_command);
	remove(filename);
	remove(filename_final);
	sprintf(filename_final,"%s.ogg",filename);  //Note: Overwriting filename_final.
	remove(filename_final);
	recording=0;               // Set "recording" to false.
        file_size_seconds=0;
      } else {
	write_buf_to_file(fptr);
      }
    }  // Ending if else for data and recording variable status.
  }  // Ending while-loop
}
Download file

Webmaster

Siden er hentet 9802 gange
Last modified 2016-09-05